From d00d60a66deeacb19ccbd39501946ed646db64b6 Mon Sep 17 00:00:00 2001 From: Ash McKenzie Date: Tue, 16 Jul 2019 14:20:52 +1000 Subject: Allow UsageData.count to use count_by: --- lib/gitlab/usage_data.rb | 4 ++-- spec/lib/gitlab/usage_data_spec.rb | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 7572c0bdbfd..f02d9f7d7e7 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -176,8 +176,8 @@ module Gitlab {} # augmented in EE end - def count(relation, fallback: -1) - relation.count + def count(relation, count_by: nil, fallback: -1) + count_by ? relation.count(count_by) : relation.count rescue ActiveRecord::StatementInvalid fallback end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 90a534de202..7fe60fd214c 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -234,6 +234,12 @@ describe Gitlab::UsageData do expect(described_class.count(relation)).to eq(1) end + it 'returns the count for count_by when provided' do + allow(relation).to receive(:count).with(:creator_id).and_return(2) + + expect(described_class.count(relation, count_by: :creator_id)).to eq(2) + end + it 'returns the fallback value when counting fails' do allow(relation).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new('')) -- cgit v1.2.1 From f53112de5931144ac74819f87c227f06e115ba58 Mon Sep 17 00:00:00 2001 From: Ash McKenzie Date: Thu, 18 Jul 2019 12:09:30 +1000 Subject: New GroupMember.of_ldap_type scope --- app/models/members/group_member.rb | 2 +- spec/factories/group_members.rb | 4 ++++ spec/models/members/group_member_spec.rb | 36 ++++++++++++++++++++------------ 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index 4cba69069bb..341d2fe2149 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -13,8 +13,8 @@ class GroupMember < Member default_scope { where(source_type: SOURCE_TYPE) } scope :of_groups, ->(groups) { where(source_id: groups.select(:id)) } - scope :count_users_by_group_id, -> { joins(:user).group(:source_id).count } + scope :of_ldap_type, -> { where(ldap: true) } after_create :update_two_factor_requirement, unless: :invite? after_destroy :update_two_factor_requirement, unless: :invite? diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb index 077c6ddc5ae..0cf99a31d20 100644 --- a/spec/factories/group_members.rb +++ b/spec/factories/group_members.rb @@ -16,5 +16,9 @@ FactoryBot.define do invite_token 'xxx' invite_email 'email@email.com' end + + trait(:ldap) do + ldap true + end end end diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index f227abd3dae..a6928ec31f4 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -3,19 +3,29 @@ require 'spec_helper' describe GroupMember do - describe '.count_users_by_group_id' do - it 'counts users by group ID' do - user_1 = create(:user) - user_2 = create(:user) - group_1 = create(:group) - group_2 = create(:group) - - group_1.add_owner(user_1) - group_1.add_owner(user_2) - group_2.add_owner(user_1) - - expect(described_class.count_users_by_group_id).to eq(group_1.id => 2, - group_2.id => 1) + context 'scopes' do + describe '.count_users_by_group_id' do + it 'counts users by group ID' do + user_1 = create(:user) + user_2 = create(:user) + group_1 = create(:group) + group_2 = create(:group) + + group_1.add_owner(user_1) + group_1.add_owner(user_2) + group_2.add_owner(user_1) + + expect(described_class.count_users_by_group_id).to eq(group_1.id => 2, + group_2.id => 1) + end + end + + describe '.of_ldap_type' do + it 'returns ldap type users' do + group_member = create(:group_member, :ldap) + + expect(described_class.of_ldap_type).to eq([group_member]) + end end end -- cgit v1.2.1 From 7dd545b130cb0cc2196ac15d7968736f679e8072 Mon Sep 17 00:00:00 2001 From: Elliot Rushton Date: Thu, 8 Aug 2019 01:00:23 +0000 Subject: Fix required runner permissions --- doc/ci/runners/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md index 03a219e03ca..f5f8e04755e 100644 --- a/doc/ci/runners/README.md +++ b/doc/ci/runners/README.md @@ -88,7 +88,7 @@ visit the project you want to make the Runner work for in GitLab: ## Registering a group Runner -Creating a group Runner requires Maintainer permissions for the group. To create a +Creating a group Runner requires Owner permissions for the group. To create a group Runner visit the group you want to make the Runner work for in GitLab: 1. Go to **Settings > CI/CD** to obtain the token @@ -124,9 +124,9 @@ To lock/unlock a Runner: ## Assigning a Runner to another project -If you are Maintainer on a project where a specific Runner is assigned to, and the +If you are an Owner on a project where a specific Runner is assigned to, and the Runner is not [locked only to that project](#locking-a-specific-runner-from-being-enabled-for-other-projects), -you can enable the Runner also on any other project where you have Maintainer permissions. +you can enable the Runner also on any other project where you have Owner permissions. To enable/disable a Runner in your project: @@ -250,7 +250,7 @@ When you [register a Runner][register], its default behavior is to **only pick** [tagged jobs](../yaml/README.md#tags). NOTE: **Note:** -Maintainer [permissions](../../user/permissions.md) are required to change the +Owner [permissions](../../user/permissions.md) are required to change the Runner settings. To make a Runner pick untagged jobs: -- cgit v1.2.1 From 1a7280220503a4bdcbed6e0b641a22be2368a626 Mon Sep 17 00:00:00 2001 From: Alexander Oleynikov Date: Thu, 8 Aug 2019 18:14:21 +0000 Subject: Remove inoperative >/dev/null --- doc/ci/ssh_keys/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md index d9f022a7125..b6aebd3bd78 100644 --- a/doc/ci/ssh_keys/README.md +++ b/doc/ci/ssh_keys/README.md @@ -76,7 +76,7 @@ to access it. This is where an SSH key pair comes in handy. ## without extra base64 encoding. ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556 ## - - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - ## ## Create the SSH directory and give it the right permissions -- cgit v1.2.1 From 4882303760c9f22112985f78746f2416b701a47b Mon Sep 17 00:00:00 2001 From: Denys Mishunov Date: Mon, 12 Aug 2019 18:13:12 +0200 Subject: Fixed deletion of directories in Web IDE --- app/assets/javascripts/ide/stores/utils.js | 2 +- .../unreleased/64677-delete-directory-webide.yml | 5 ++++ spec/javascripts/ide/stores/utils_spec.js | 35 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/64677-delete-directory-webide.yml diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js index 04e86afb268..52200ce7847 100644 --- a/app/assets/javascripts/ide/stores/utils.js +++ b/app/assets/javascripts/ide/stores/utils.js @@ -129,7 +129,7 @@ export const commitActionForFile = file => { export const getCommitFiles = stagedFiles => stagedFiles.reduce((acc, file) => { - if (file.moved) return acc; + if (file.moved || file.type === 'tree') return acc; return acc.concat({ ...file, diff --git a/changelogs/unreleased/64677-delete-directory-webide.yml b/changelogs/unreleased/64677-delete-directory-webide.yml new file mode 100644 index 00000000000..27d596b6b19 --- /dev/null +++ b/changelogs/unreleased/64677-delete-directory-webide.yml @@ -0,0 +1,5 @@ +--- +title: Fixed removing directories in Web IDE +merge_request: 31727 +author: +type: fixed diff --git a/spec/javascripts/ide/stores/utils_spec.js b/spec/javascripts/ide/stores/utils_spec.js index bceb3a8db91..0fc9519a6bf 100644 --- a/spec/javascripts/ide/stores/utils_spec.js +++ b/spec/javascripts/ide/stores/utils_spec.js @@ -261,6 +261,41 @@ describe('Multi-file store utils', () => { }, ]); }); + + it('filters out folders from the list', () => { + const files = [ + { + path: 'a', + type: 'blob', + deleted: true, + }, + { + path: 'c', + type: 'tree', + deleted: true, + }, + { + path: 'c/d', + type: 'blob', + deleted: true, + }, + ]; + + const flattendFiles = utils.getCommitFiles(files); + + expect(flattendFiles).toEqual([ + { + path: 'a', + type: 'blob', + deleted: true, + }, + { + path: 'c/d', + type: 'blob', + deleted: true, + }, + ]); + }); }); describe('mergeTrees', () => { -- cgit v1.2.1 From 8c2c4e4d75ec60182e37ddaf637bc25095bdd57f Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Wed, 14 Aug 2019 17:48:00 +0100 Subject: Upgrade babel to 7.5.5 Signed-off-by: Takuya Noguchi --- changelogs/unreleased/update-babel-to-7-5-5.yml | 5 ++++ package.json | 8 +++--- yarn.lock | 36 ++++++++++++------------- 3 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 changelogs/unreleased/update-babel-to-7-5-5.yml diff --git a/changelogs/unreleased/update-babel-to-7-5-5.yml b/changelogs/unreleased/update-babel-to-7-5-5.yml new file mode 100644 index 00000000000..c498e2adfe8 --- /dev/null +++ b/changelogs/unreleased/update-babel-to-7-5-5.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade babel to 7.5.5 +merge_request: 31819 +author: Takuya Noguchi +type: other diff --git a/package.json b/package.json index 803aebcb5fd..9c9a7687fc2 100644 --- a/package.json +++ b/package.json @@ -30,13 +30,13 @@ "webpack-vrt": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.review_toolbar.js" }, "dependencies": { - "@babel/core": "^7.4.4", - "@babel/plugin-proposal-class-properties": "^7.4.4", + "@babel/core": "^7.5.5", + "@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-json-strings": "^7.2.0", "@babel/plugin-proposal-private-methods": "^7.4.4", "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-import-meta": "^7.2.0", - "@babel/preset-env": "^7.4.4", + "@babel/preset-env": "^7.5.5", "@gitlab/csslab": "^1.9.0", "@gitlab/svgs": "^1.67.0", "@gitlab/ui": "5.15.0", @@ -145,7 +145,7 @@ "xterm": "^3.5.0" }, "devDependencies": { - "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", "@gitlab/eslint-config": "^1.6.0", "@gitlab/eslint-plugin-i18n": "^1.1.0", "@gitlab/eslint-plugin-vue-i18n": "^1.2.0", diff --git a/yarn.lock b/yarn.lock index ed1f06523c0..5a59f149e8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,7 +9,7 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@>=7.2.2", "@babel/core@^7.1.0", "@babel/core@^7.1.2", "@babel/core@^7.4.4": +"@babel/core@>=7.2.2", "@babel/core@^7.1.0", "@babel/core@^7.1.2", "@babel/core@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== @@ -139,16 +139,16 @@ "@babel/types" "^7.0.0" "@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8" - integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" "@babel/template" "^7.4.4" - "@babel/types" "^7.4.4" - lodash "^4.17.11" + "@babel/types" "^7.5.5" + lodash "^4.17.13" "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" @@ -163,11 +163,11 @@ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" - integrity sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== dependencies: - lodash "^4.17.11" + lodash "^4.17.13" "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" @@ -225,9 +225,9 @@ "@babel/types" "^7.5.5" "@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -252,7 +252,7 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.4.4": +"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== @@ -833,7 +833,7 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" -"@babel/preset-env@^7.1.0", "@babel/preset-env@^7.4.4": +"@babel/preset-env@^7.1.0", "@babel/preset-env@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a" integrity sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A== @@ -914,9 +914,9 @@ integrity sha512-FBMd0IiARPtH5aaOFUVki6evHiJQiY0pFy7fizyRF7dtwc+el3nwpzvhb9qBNzceG1OIJModG1xpE0DDFjPXwA== "@babel/standalone@^7.0.0": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.3.4.tgz#b622c1e522acef91b2a14f22bdcdd4f935a1a474" - integrity sha512-4L9c5i4WlGqbrjOVX0Yp8TIR5cEiw1/tPYYZENW/iuO2uI6viY38U7zALidzNfGdZIwNc+A/AWqMEWKeScWkBg== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.5.5.tgz#9d3143f6078ff408db694a4254bd6f03c5c33962" + integrity sha512-YIp5taErC4uvp4d5urJtWMui3cpvZt83x57l4oVJNvFtDzumf3pMgRmoTSpGuEzh1yzo7jHhg3mbQmMhmKPbjA== "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": version "7.4.4" -- cgit v1.2.1 From 50956e5c85e29d0d1a7634068b782ffce73be479 Mon Sep 17 00:00:00 2001 From: Luke Duncalfe Date: Mon, 12 Aug 2019 10:17:32 +1200 Subject: Link more issues in Design Management Limitations --- doc/user/project/issues/design_management.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md index bffbcb544e3..1324a90e00b 100644 --- a/doc/user/project/issues/design_management.md +++ b/doc/user/project/issues/design_management.md @@ -35,9 +35,19 @@ to be enabled: ## Limitations -- Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`, `gif`, `bmp`, `tiff` or `ico`. The [`svg` extension is not yet supported](https://gitlab.com/gitlab-org/gitlab-ee/issues/12771). +- Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`, `gif`, `bmp`, `tiff` or `ico`. + The [`svg` extension is not yet supported](https://gitlab.com/gitlab-org/gitlab-ee/issues/12771). +- Design uploads are limited to 10 files at a time. - [Designs cannot yet be deleted](https://gitlab.com/gitlab-org/gitlab-ee/issues/11089). -- Design Management is [not yet supported in the project export](https://gitlab.com/gitlab-org/gitlab-ee/issues/11090). +- Design Management is + [not yet supported in the project export](https://gitlab.com/gitlab-org/gitlab-ee/issues/11090). +- Design Management data + [isn't deleted when a project is destroyed](https://gitlab.com/gitlab-org/gitlab-ee/issues/13429) yet. +- Design Management data [won't be moved](https://gitlab.com/gitlab-org/gitlab-ee/issues/13426) + when an issue is moved, nor [deleted](https://gitlab.com/gitlab-org/gitlab-ee/issues/13427) + when an issue is deleted. +- Design Management + [isn't supported by Geo](https://gitlab.com/groups/gitlab-org/-/epics/1633) yet. ## The Design Management page -- cgit v1.2.1 From b179b752e8024679e6ce6fbd2a5fe1da17fef3f6 Mon Sep 17 00:00:00 2001 From: Arun Kumar Mohan Date: Tue, 13 Aug 2019 01:04:10 -0500 Subject: Refactor nextUnresolvedDiscussionId and previousUnresolvedDiscussionId getters --- app/assets/javascripts/notes/stores/getters.js | 39 +++++--- spec/javascripts/notes/stores/getters_spec.js | 130 +++++++++++++++++-------- 2 files changed, 112 insertions(+), 57 deletions(-) diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js index 52410f18d4a..3d0ec8cd3a7 100644 --- a/app/assets/javascripts/notes/stores/getters.js +++ b/app/assets/javascripts/notes/stores/getters.js @@ -171,26 +171,33 @@ export const isLastUnresolvedDiscussion = (state, getters) => (discussionId, dif return lastDiscussionId === discussionId; }; -// Gets the ID of the discussion following the one provided, respecting order (diff or date) -// @param {Boolean} discussionId - id of the current discussion -// @param {Boolean} diffOrder - is ordered by diff? -export const nextUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => { - const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder); - const currentIndex = idsOrdered.indexOf(discussionId); - const slicedIds = idsOrdered.slice(currentIndex + 1, currentIndex + 2); +export const findUnresolvedDiscussionIdNeighbor = (state, getters) => ({ + discussionId, + diffOrder, + step, +}) => { + const ids = getters.unresolvedDiscussionsIdsOrdered(diffOrder); + const index = ids.indexOf(discussionId) + step; + + if (index < 0 && step < 0) { + return ids[ids.length - 1]; + } + + if (index === ids.length && step > 0) { + return ids[0]; + } - // Get the first ID if there is none after the currentIndex - return slicedIds.length ? idsOrdered.slice(currentIndex + 1, currentIndex + 2)[0] : idsOrdered[0]; + return ids[index]; }; -export const previousUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => { - const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder); - const currentIndex = idsOrdered.indexOf(discussionId); - const slicedIds = idsOrdered.slice(currentIndex - 1, currentIndex); +// Gets the ID of the discussion following the one provided, respecting order (diff or date) +// @param {Boolean} discussionId - id of the current discussion +// @param {Boolean} diffOrder - is ordered by diff? +export const nextUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => + getters.findUnresolvedDiscussionIdNeighbor({ discussionId, diffOrder, step: 1 }); - // Get the last ID if there is none after the currentIndex - return slicedIds.length ? slicedIds[0] : idsOrdered[idsOrdered.length - 1]; -}; +export const previousUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => + getters.findUnresolvedDiscussionIdNeighbor({ discussionId, diffOrder, step: -1 }); // @param {Boolean} diffOrder - is ordered by diff? export const firstUnresolvedDiscussionId = (state, getters) => diffOrder => { diff --git a/spec/javascripts/notes/stores/getters_spec.js b/spec/javascripts/notes/stores/getters_spec.js index 71dcba114a9..d69f469c7c7 100644 --- a/spec/javascripts/notes/stores/getters_spec.js +++ b/spec/javascripts/notes/stores/getters_spec.js @@ -14,6 +14,13 @@ import { const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json'; +// Helper function to ensure that we're using the same schema across tests. +const createDiscussionNeighborParams = (discussionId, diffOrder, step) => ({ + discussionId, + diffOrder, + step, +}); + describe('Getters Notes Store', () => { let state; @@ -25,7 +32,6 @@ describe('Getters Notes Store', () => { targetNoteHash: 'hash', lastFetchedAt: 'timestamp', isNotesFetched: false, - notesData: notesDataMock, userData: userDataMock, noteableData: noteableDataMock, @@ -244,62 +250,104 @@ describe('Getters Notes Store', () => { }); }); - describe('nextUnresolvedDiscussionId', () => { - const localGetters = { - unresolvedDiscussionsIdsOrdered: () => ['123', '456', '789'], - }; + describe('findUnresolvedDiscussionIdNeighbor', () => { + let localGetters; + beforeEach(() => { + localGetters = { + unresolvedDiscussionsIdsOrdered: () => ['123', '456', '789'], + }; + }); - it('should return the ID of the discussion after the ID provided', () => { - expect(getters.nextUnresolvedDiscussionId(state, localGetters)('123')).toBe('456'); - expect(getters.nextUnresolvedDiscussionId(state, localGetters)('456')).toBe('789'); - expect(getters.nextUnresolvedDiscussionId(state, localGetters)('789')).toBe('123'); + [ + { step: 1, id: '123', expected: '456' }, + { step: 1, id: '456', expected: '789' }, + { step: 1, id: '789', expected: '123' }, + { step: -1, id: '123', expected: '789' }, + { step: -1, id: '456', expected: '123' }, + { step: -1, id: '789', expected: '456' }, + ].forEach(({ step, id, expected }) => { + it(`with step ${step} and id ${id}, returns next value`, () => { + const params = createDiscussionNeighborParams(id, true, step); + + expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe( + expected, + ); + }); }); - }); - describe('previousUnresolvedDiscussionId', () => { - describe('with unresolved discussions', () => { - const localGetters = { - unresolvedDiscussionsIdsOrdered: () => ['123', '456', '789'], - }; + describe('with 1 unresolved discussion', () => { + beforeEach(() => { + localGetters = { + unresolvedDiscussionsIdsOrdered: () => ['123'], + }; + }); + + [{ step: 1, id: '123', expected: '123' }, { step: -1, id: '123', expected: '123' }].forEach( + ({ step, id, expected }) => { + it(`with step ${step} and match, returns only value`, () => { + const params = createDiscussionNeighborParams(id, true, step); - it('with bogus returns falsey', () => { - expect(getters.previousUnresolvedDiscussionId(state, localGetters)('bogus')).toBe('456'); + expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe( + expected, + ); + }); + }, + ); + + it('with no match, returns only value', () => { + const params = createDiscussionNeighborParams('bogus', true, 1); + + expect(getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params)).toBe('123'); }); + }); - [ - { id: '123', expected: '789' }, - { id: '456', expected: '123' }, - { id: '789', expected: '456' }, - ].forEach(({ id, expected }) => { - it(`with ${id}, returns previous value`, () => { - expect(getters.previousUnresolvedDiscussionId(state, localGetters)(id)).toBe(expected); + describe('with 0 unresolved discussions', () => { + beforeEach(() => { + localGetters = { + unresolvedDiscussionsIdsOrdered: () => [], + }; + }); + + [{ step: 1 }, { step: -1 }].forEach(({ step }) => { + it(`with step ${step}, returns undefined`, () => { + const params = createDiscussionNeighborParams('bogus', true, step); + + expect( + getters.findUnresolvedDiscussionIdNeighbor(state, localGetters)(params), + ).toBeUndefined(); }); }); }); + }); - describe('with 1 unresolved discussion', () => { - const localGetters = { - unresolvedDiscussionsIdsOrdered: () => ['123'], - }; + describe('findUnresolvedDiscussionIdNeighbor aliases', () => { + let neighbor; + let findUnresolvedDiscussionIdNeighbor; + let localGetters; - it('with bogus returns id', () => { - expect(getters.previousUnresolvedDiscussionId(state, localGetters)('bogus')).toBe('123'); - }); + beforeEach(() => { + neighbor = {}; + findUnresolvedDiscussionIdNeighbor = jasmine.createSpy().and.returnValue(neighbor); + localGetters = { findUnresolvedDiscussionIdNeighbor }; + }); - it('with match, returns value', () => { - expect(getters.previousUnresolvedDiscussionId(state, localGetters)('123')).toEqual('123'); + describe('nextUnresolvedDiscussionId', () => { + it('should return result of find neighbor', () => { + const expectedParams = createDiscussionNeighborParams('123', true, 1); + const result = getters.nextUnresolvedDiscussionId(state, localGetters)('123', true); + + expect(findUnresolvedDiscussionIdNeighbor).toHaveBeenCalledWith(expectedParams); + expect(result).toBe(neighbor); }); }); - describe('with 0 unresolved discussions', () => { - const localGetters = { - unresolvedDiscussionsIdsOrdered: () => [], - }; + describe('previosuUnresolvedDiscussionId', () => { + it('should return result of find neighbor', () => { + const expectedParams = createDiscussionNeighborParams('123', true, -1); + const result = getters.previousUnresolvedDiscussionId(state, localGetters)('123', true); - it('returns undefined', () => { - expect( - getters.previousUnresolvedDiscussionId(state, localGetters)('bogus'), - ).toBeUndefined(); + expect(findUnresolvedDiscussionIdNeighbor).toHaveBeenCalledWith(expectedParams); + expect(result).toBe(neighbor); }); }); }); -- cgit v1.2.1 From a5a316baf3146916a1eb3b90b5b9906318d22ddb Mon Sep 17 00:00:00 2001 From: Zeff Morgan Date: Thu, 15 Aug 2019 23:10:37 +0000 Subject: Correct case of GitLab in section header --- doc/user/project/integrations/prometheus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index aa7db97c413..787ac3fce5c 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -354,7 +354,7 @@ Prometheus server. ![Merge Request with Performance Impact](img/merge_request_performance.png) -## Embedding metric charts within Gitlab Flavored Markdown +## Embedding metric charts within GitLab Flavored Markdown > [Introduced][ce-29691] in GitLab 12.2. > Requires [Kubernetes](prometheus_library/kubernetes.md) metrics. -- cgit v1.2.1 From 880c9a25a8738a4f4be26b147655b4cb6ac89d4e Mon Sep 17 00:00:00 2001 From: Steve Azzopardi Date: Thu, 25 Jul 2019 14:14:31 +0200 Subject: Update srmX configuration --- doc/user/gitlab_com/index.md | 83 ++++++++++---------------------------------- 1 file changed, 19 insertions(+), 64 deletions(-) diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index c9fbd7effa0..d21a325d401 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -112,57 +112,6 @@ Below are the shared Runners settings. The full contents of our `config.toml` are: -**DigitalOcean** - -```toml -concurrent = X -check_interval = 1 -metrics_server = "X" -sentry_dsn = "X" - -[[runners]] - name = "docker-auto-scale" - request_concurrency = X - url = "https://gitlab.com/" - token = "SHARED_RUNNER_TOKEN" - executor = "docker+machine" - environment = [ - "DOCKER_DRIVER=overlay2" - ] - limit = X - [runners.docker] - image = "ruby:2.5" - privileged = true - [runners.machine] - IdleCount = 20 - IdleTime = 1800 - OffPeakPeriods = ["* * * * * sat,sun *"] - OffPeakTimezone = "UTC" - OffPeakIdleCount = 5 - OffPeakIdleTime = 1800 - MaxBuilds = 1 - MachineName = "srm-%s" - MachineDriver = "digitalocean" - MachineOptions = [ - "digitalocean-image=X", - "digitalocean-ssh-user=core", - "digitalocean-region=nyc1", - "digitalocean-size=s-2vcpu-2gb", - "digitalocean-private-networking", - "digitalocean-tags=shared_runners,gitlab_com", - "engine-registry-mirror=http://INTERNAL_IP_OF_OUR_REGISTRY_MIRROR", - "digitalocean-access-token=DIGITAL_OCEAN_ACCESS_TOKEN", - ] - [runners.cache] - Type = "s3" - BucketName = "runner" - Insecure = true - Shared = true - ServerAddress = "INTERNAL_IP_OF_OUR_CACHE_SERVER" - AccessKey = "ACCESS_KEY" - SecretKey = "ACCESS_SECRET_KEY" -``` - **Google Cloud Platform** ```toml @@ -178,20 +127,25 @@ sentry_dsn = "X" token = "SHARED_RUNNER_TOKEN" executor = "docker+machine" environment = [ - "DOCKER_DRIVER=overlay2" + "DOCKER_DRIVER=overlay2", + "DOCKER_TLS_CERTDIR=" ] limit = X [runners.docker] image = "ruby:2.5" privileged = true + volumes = [ + "/certs/client", + "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP. + ] [runners.machine] - IdleCount = 20 - IdleTime = 1800 + IdleCount = 50 + IdleTime = 3600 OffPeakPeriods = ["* * * * * sat,sun *"] OffPeakTimezone = "UTC" - OffPeakIdleCount = 5 - OffPeakIdleTime = 1800 - MaxBuilds = 1 + OffPeakIdleCount = 15 + OffPeakIdleTime = 3600 + MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused. MachineName = "srm-%s" MachineDriver = "google" MachineOptions = [ @@ -202,17 +156,18 @@ sentry_dsn = "X" "google-tags=gitlab-com,srm", "google-use-internal-ip", "google-zone=us-east1-d", + "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/issues/3214#note_82892928 "google-machine-image=PROJECT/global/images/IMAGE", - "engine-registry-mirror=http://INTERNAL_IP_OF_OUR_REGISTRY_MIRROR" + "engine-opt=ipv6", # This will create IPv6 interfaces in the containers. + "engine-opt=fixed-cidr-v6=fc00::/7", + "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600 ] [runners.cache] - Type = "s3" - BucketName = "runner" - Insecure = true + Type = "gcs" Shared = true - ServerAddress = "INTERNAL_IP_OF_OUR_CACHE_SERVER" - AccessKey = "ACCESS_KEY" - SecretKey = "ACCESS_SECRET_KEY" + [runners.cache.gcs] + CredentialsFile = "/path/to/file" + BucketName = "bucket-name" ``` ## Sidekiq -- cgit v1.2.1 From 5a574883f95373e13f663568eb4710c9d69d00d6 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 12 Aug 2019 11:29:10 +0100 Subject: Remove MySQL references from development docs I noticed the doc/development/testing_guide/best_practices.md still referenced the `[run mysql]` tags, etc. They no longer work, so I removed them, then realised I had better clean up the rest of doc/development ! --- doc/development/architecture.md | 22 ++++++++-------- doc/development/hash_indexes.md | 2 +- doc/development/rake_tasks.md | 2 +- doc/development/sha1_as_binary.md | 2 +- doc/development/sql.md | 30 +++++++--------------- doc/development/testing_guide/best_practices.md | 10 -------- doc/development/testing_guide/ci.md | 1 - doc/development/testing_guide/flaky_tests.md | 4 +-- doc/development/verifying_database_capabilities.md | 8 +++--- doc/development/what_requires_downtime.md | 25 ++++-------------- 10 files changed, 34 insertions(+), 72 deletions(-) diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 87405bc2fec..5cb2ddf6e52 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -20,7 +20,7 @@ A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a w We also support deploying GitLab on Kubernetes using our [gitlab Helm chart](https://docs.gitlab.com/charts/). -The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. +The GitLab web app uses PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. @@ -511,7 +511,15 @@ To summarize here's the [directory structure of the `git` user home directory](. ps aux | grep '^git' ``` -GitLab has several components to operate. As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. It also uses Apache httpd or Nginx to proxypass Unicorn. As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). Under the GitLab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process). +GitLab has several components to operate. It requires a persistent database +(PostgreSQL) and redis database, and uses Apache httpd or Nginx to proxypass +Unicorn. All these components should run as different system users to GitLab +(e.g., `postgres`, `redis` and `www-data`, instead of `git`). + +As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server +running on port `8080` by default). Under the GitLab user there are normally 4 +processes: `unicorn_rails master` (1 process), `unicorn_rails worker` +(2 processes), `sidekiq` (1 process). ### Repository access @@ -554,12 +562,9 @@ $ /etc/init.d/nginx Usage: nginx {start|stop|restart|reload|force-reload|status|configtest} ``` -Persistent database (one of the following) +Persistent database ``` -/etc/init.d/mysqld -Usage: /etc/init.d/mysqld {start|stop|status|restart|condrestart|try-restart|reload|force-reload} - $ /etc/init.d/postgresql Usage: /etc/init.d/postgresql {start|stop|restart|reload|force-reload|status} [version ..] ``` @@ -597,11 +602,6 @@ PostgreSQL - `/var/log/postgresql/*` -MySQL - -- `/var/log/mysql/*` -- `/var/log/mysql.*` - ### GitLab specific config files GitLab has configuration files located in `/home/git/gitlab/config/*`. Commonly referenced config files include: diff --git a/doc/development/hash_indexes.md b/doc/development/hash_indexes.md index e6c1b3590b1..417ea18e22f 100644 --- a/doc/development/hash_indexes.md +++ b/doc/development/hash_indexes.md @@ -1,6 +1,6 @@ # Hash Indexes -Both PostgreSQL and MySQL support hash indexes besides the regular btree +PostgreSQL supports hash indexes besides the regular btree indexes. Hash indexes however are to be avoided at all costs. While they may _sometimes_ provide better performance the cost of rehashing can be very high. More importantly: at least until PostgreSQL 10.0 hash indexes are not diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index c97e179910b..e9d6cfe00b2 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -9,7 +9,7 @@ bundle exec rake setup ``` The `setup` task is an alias for `gitlab:setup`. -This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database. +This tasks calls `db:reset` to create the database, and calls `db:seed_fu` to seed the database. Note: `db:setup` calls `db:seed` but this does nothing. ### Seeding issues for all or a given project diff --git a/doc/development/sha1_as_binary.md b/doc/development/sha1_as_binary.md index 3151cc29bbc..6c4252ec634 100644 --- a/doc/development/sha1_as_binary.md +++ b/doc/development/sha1_as_binary.md @@ -2,7 +2,7 @@ Storing SHA1 hashes as strings is not very space efficient. A SHA1 as a string requires at least 40 bytes, an additional byte to store the encoding, and -perhaps more space depending on the internals of PostgreSQL and MySQL. +perhaps more space depending on the internals of PostgreSQL. On the other hand, if one were to store a SHA1 as binary one would only need 20 bytes for the actual SHA1, and 1 or 4 bytes of additional space (again depending diff --git a/doc/development/sql.md b/doc/development/sql.md index a256fd46c09..2584dcfb4ca 100644 --- a/doc/development/sql.md +++ b/doc/development/sql.md @@ -15,14 +15,11 @@ FROM issues WHERE title LIKE 'WIP:%'; ``` -On PostgreSQL the `LIKE` statement is case-sensitive. On MySQL this depends on -the case-sensitivity of the collation, which is usually case-insensitive. To -perform a case-insensitive `LIKE` on PostgreSQL you have to use `ILIKE` instead. -This statement in turn isn't supported on MySQL. +On PostgreSQL the `LIKE` statement is case-sensitive. To perform a case-insensitive +`LIKE` you have to use `ILIKE` instead. -To work around this problem you should write `LIKE` queries using Arel instead -of raw SQL fragments as Arel automatically uses `ILIKE` on PostgreSQL and `LIKE` -on MySQL. This means that instead of this: +To handle this automatically you should use `LIKE` queries using Arel instead +of raw SQL fragments, as Arel automatically uses `ILIKE` on PostgreSQL. ```ruby Issue.where('title LIKE ?', 'WIP:%') @@ -45,7 +42,7 @@ table = Issue.arel_table Issue.where(table[:title].matches('WIP:%').or(table[:foo].matches('WIP:%'))) ``` -For PostgreSQL this produces: +On PostgreSQL, this produces: ```sql SELECT * @@ -53,18 +50,10 @@ FROM issues WHERE (title ILIKE 'WIP:%' OR foo ILIKE 'WIP:%') ``` -In turn for MySQL this produces: - -```sql -SELECT * -FROM issues -WHERE (title LIKE 'WIP:%' OR foo LIKE 'WIP:%') -``` - ## LIKE & Indexes -Neither PostgreSQL nor MySQL use any indexes when using `LIKE` / `ILIKE` with a -wildcard at the start. For example, this will not use any indexes: +PostgreSQL won't use any indexes when using `LIKE` / `ILIKE` with a wildcard at +the start. For example, this will not use any indexes: ```sql SELECT * @@ -75,9 +64,8 @@ WHERE title ILIKE '%WIP:%'; Because the value for `ILIKE` starts with a wildcard the database is not able to use an index as it doesn't know where to start scanning the indexes. -MySQL provides no known solution to this problem. Luckily PostgreSQL _does_ -provide a solution: trigram GIN indexes. These indexes can be created as -follows: +Luckily, PostgreSQL _does_ provide a solution: trigram GIN indexes. These +indexes can be created as follows: ```sql CREATE INDEX [CONCURRENTLY] index_name_here diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index 448d9fd01c4..a505d3c79a2 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -15,16 +15,6 @@ manifest themselves within our code. When designing our tests, take time to revi our test design. We can find some helpful heuristics documented in the Handbook in the [Test Design](https://about.gitlab.com/handbook/engineering/quality/guidelines/test-engineering/test-design/) section. -## Run tests against MySQL - -By default, tests are only run against PostgreSQL, but you can run them on -demand against MySQL by following one of the following conventions: - -| Convention | Valid example | -|:----------------------|:-----------------------------| -| Include `mysql` in your branch name | `enhance-mysql-support` | -| Include `[run mysql]` in your commit message | `Fix MySQL support

[run mysql]` | - ## Test speed GitLab has a massive test suite that, without [parallelization], can take hours diff --git a/doc/development/testing_guide/ci.md b/doc/development/testing_guide/ci.md index 87d48726268..d9f66a827de 100644 --- a/doc/development/testing_guide/ci.md +++ b/doc/development/testing_guide/ci.md @@ -39,7 +39,6 @@ slowest test files and try to improve them. ## CI setup -- On CE and EE, the test suite runs both PostgreSQL and MySQL. - Rails logging to `log/test.log` is disabled by default in CI [for performance reasons][logging]. To override this setting, provide the `RAILS_ENABLE_TEST_LOG` environment variable. diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md index 931cbc51cae..eb0bf6fc563 100644 --- a/doc/development/testing_guide/flaky_tests.md +++ b/doc/development/testing_guide/flaky_tests.md @@ -35,8 +35,8 @@ Once a test is in quarantine, there are 3 choices: Quarantined tests are run on the CI in dedicated jobs that are allowed to fail: -- `rspec-pg-quarantine` and `rspec-mysql-quarantine` (CE & EE) -- `rspec-pg-quarantine-ee` and `rspec-mysql-quarantine-ee` (EE only) +- `rspec-pg-quarantine` (CE & EE) +- `rspec-pg-quarantine-ee` (EE only) ## Automatic retries and flaky tests detection diff --git a/doc/development/verifying_database_capabilities.md b/doc/development/verifying_database_capabilities.md index ccec6f7d719..6b4995aebe2 100644 --- a/doc/development/verifying_database_capabilities.md +++ b/doc/development/verifying_database_capabilities.md @@ -1,15 +1,15 @@ # Verifying Database Capabilities -Sometimes certain bits of code may only work on a certain database and/or +Sometimes certain bits of code may only work on a certain database version. While we try to avoid such code as much as possible sometimes it is necessary to add database (version) specific behaviour. To facilitate this we have the following methods that you can use: -- `Gitlab::Database.postgresql?`: returns `true` if PostgreSQL is being used -- `Gitlab::Database.mysql?`: returns `true` if MySQL is being used +- `Gitlab::Database.postgresql?`: returns `true` if PostgreSQL is being used. + You can normally just assume this is the case. - `Gitlab::Database.version`: returns the PostgreSQL version number as a string - in the format `X.Y.Z`. This method does not work for MySQL + in the format `X.Y.Z`. This allows you to write code such as: diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md index f0da1cc2ddc..944bf5900c5 100644 --- a/doc/development/what_requires_downtime.md +++ b/doc/development/what_requires_downtime.md @@ -7,9 +7,8 @@ downtime. ## Adding Columns -On PostgreSQL you can safely add a new column to an existing table as long as it -does **not** have a default value. For example, this query would not require -downtime: +You can safely add a new column to an existing table as long as it does **not** +have a default value. For example, this query would not require downtime: ```sql ALTER TABLE projects ADD COLUMN random_value int; @@ -27,11 +26,6 @@ This requires updating every single row in the `projects` table so that indexes in a table. This in turn acquires enough locks on the table for it to effectively block any other queries. -As of MySQL 5.6 adding a column to a table is still quite an expensive -operation, even when using `ALGORITHM=INPLACE` and `LOCK=NONE`. This means -downtime _may_ be required when modifying large tables as otherwise the -operation could potentially take hours to complete. - Adding a column with a default value _can_ be done without requiring downtime when using the migration helper method `Gitlab::Database::MigrationHelpers#add_column_with_default`. This method works @@ -311,8 +305,7 @@ migrations](background_migrations.md#cleaning-up). ## Adding Indexes Adding indexes is an expensive process that blocks INSERT and UPDATE queries for -the duration. When using PostgreSQL one can work around this by using the -`CONCURRENTLY` option: +the duration. You can work around this by using the `CONCURRENTLY` option: ```sql CREATE INDEX CONCURRENTLY index_name ON projects (column_name); @@ -336,17 +329,9 @@ end Note that `add_concurrent_index` can not be reversed automatically, thus you need to manually define `up` and `down`. -When running this on PostgreSQL the `CONCURRENTLY` option mentioned above is -used. On MySQL this method produces a regular `CREATE INDEX` query. - -MySQL doesn't really have a workaround for this. Supposedly it _can_ create -indexes without the need for downtime but only for variable width columns. The -details on this are a bit sketchy. Since it's better to be safe than sorry one -should assume that adding indexes requires downtime on MySQL. - ## Dropping Indexes -Dropping an index does not require downtime on both PostgreSQL and MySQL. +Dropping an index does not require downtime. ## Adding Tables @@ -370,7 +355,7 @@ transaction this means this approach would require downtime. GitLab allows you to work around this by using `Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key`. This method -ensures that when PostgreSQL is used no downtime is needed. +ensures that no downtime is needed. ## Removing Foreign Keys -- cgit v1.2.1 From 3488da59363a5edfbf431a37ba59247b836bc50a Mon Sep 17 00:00:00 2001 From: Jarek Ostrowski Date: Fri, 16 Aug 2019 10:27:11 -0400 Subject: Add expand up and expand down icons Add changelog Add MR to changelog Remove stray file --- app/assets/javascripts/diffs/components/diff_expansion_cell.vue | 6 ++---- changelogs/unreleased/66161-replace-expand-icons.yml | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/66161-replace-expand-icons.yml diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue index 925385fa98a..43edc116ed1 100644 --- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue +++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue @@ -223,8 +223,7 @@ export default { :title="__('Expand up')" @click="handleExpandLines(EXPAND_UP)" > - -