Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/projects/compare/components/app_legacy.vue27
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue13
-rw-r--r--app/views/profiles/gpg_keys/_key.html.haml2
-rw-r--r--changelogs/unreleased/225345-re-add-swap-branches-feature.yml5
-rw-r--r--doc/development/what_requires_downtime.md8
-rw-r--r--locale/gitlab.pot3
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb2
-rw-r--r--spec/frontend/projects/compare/components/app_legacy_spec.js55
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js25
-rw-r--r--spec/tooling/lib/tooling/kubernetes_client_spec.rb10
-rw-r--r--tooling/lib/tooling/kubernetes_client.rb2
11 files changed, 132 insertions, 20 deletions
diff --git a/app/assets/javascripts/projects/compare/components/app_legacy.vue b/app/assets/javascripts/projects/compare/components/app_legacy.vue
index c0ff58ee074..d3f09f7d69f 100644
--- a/app/assets/javascripts/projects/compare/components/app_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/app_legacy.vue
@@ -37,10 +37,22 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ from: this.paramsFrom,
+ to: this.paramsTo,
+ };
+ },
methods: {
onSubmit() {
this.$refs.form.submit();
},
+ onSwapRevision() {
+ [this.from, this.to] = [this.to, this.from]; // swaps 'from' and 'to'
+ },
+ onSelectRevision({ direction, revision }) {
+ this[direction] = revision; // direction is either 'from' or 'to'
+ },
},
};
</script>
@@ -57,19 +69,30 @@ export default {
:refs-project-path="refsProjectPath"
revision-text="Source"
params-name="to"
- :params-branch="paramsTo"
+ :params-branch="to"
+ data-testid="sourceRevisionDropdown"
+ @selectRevision="onSelectRevision"
/>
<div class="compare-ellipsis gl-display-inline" data-testid="ellipsis">...</div>
<revision-dropdown
:refs-project-path="refsProjectPath"
revision-text="Target"
params-name="from"
- :params-branch="paramsFrom"
+ :params-branch="from"
+ data-testid="targetRevisionDropdown"
+ @selectRevision="onSelectRevision"
/>
<gl-button category="primary" variant="success" class="gl-ml-3" @click="onSubmit">
{{ s__('CompareRevisions|Compare') }}
</gl-button>
<gl-button
+ data-testid="swapRevisionsButton"
+ class="btn btn-default gl-button gl-ml-3"
+ @click="onSwapRevision"
+ >
+ {{ s__('CompareRevisions|Swap revisions') }}
+ </gl-button>
+ <gl-button
v-if="projectMergeRequestPath"
:href="projectMergeRequestPath"
data-testid="projectMrButton"
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
index 13d80b5ae0b..f57a8942a77 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
@@ -55,6 +55,11 @@ export default {
return this.filteredTags.length;
},
},
+ watch: {
+ paramsBranch(newBranch) {
+ this.setSelectedRevision(newBranch);
+ },
+ },
mounted() {
this.fetchBranchesAndTags();
},
@@ -83,10 +88,14 @@ export default {
return this.paramsBranch || s__('CompareRevisions|Select branch/tag');
},
onClick(revision) {
- this.selectedRevision = revision;
+ this.setSelectedRevision(revision);
},
onSearchEnter() {
- this.selectedRevision = this.searchTerm;
+ this.setSelectedRevision(this.searchTerm);
+ },
+ setSelectedRevision(revision) {
+ this.selectedRevision = revision || s__('CompareRevisions|Select branch/tag');
+ this.$emit('selectRevision', { direction: this.paramsName, revision });
},
},
};
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index c851601d4c3..4b3f6f8cfc7 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -18,7 +18,7 @@
%code= subkey.fingerprint
.float-right
%span.key-created-at
- = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago:time_ago_with_tooltip(key.created_at)}
+ = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago: time_ago_with_tooltip(key.created_at) }
= link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "gl-button btn btn-danger gl-ml-3" do
%span.sr-only= _('Remove')
= sprite_icon('remove')
diff --git a/changelogs/unreleased/225345-re-add-swap-branches-feature.yml b/changelogs/unreleased/225345-re-add-swap-branches-feature.yml
new file mode 100644
index 00000000000..b3960b1d744
--- /dev/null
+++ b/changelogs/unreleased/225345-re-add-swap-branches-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Re-add swap revisions feature (legacy)
+merge_request: 57802
+author:
+type: added
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
new file mode 100644
index 00000000000..7d20382973a
--- /dev/null
+++ b/doc/development/what_requires_downtime.md
@@ -0,0 +1,8 @@
+---
+redirect_to: 'avoiding_downtime_in_migrations.md'
+---
+
+This document was moved to [another location](avoiding_downtime_in_migrations.md).
+
+<!-- This redirect file can be deleted after <2021-07-01>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 47e4199e6fd..b5b7486bb12 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7892,6 +7892,9 @@ msgstr ""
msgid "CompareRevisions|Select target project"
msgstr ""
+msgid "CompareRevisions|Swap revisions"
+msgstr ""
+
msgid "CompareRevisions|Tags"
msgstr ""
diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
index e28e054dc46..176f1139a7a 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
@@ -45,7 +45,7 @@ module QA
# Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect
# scenario with other tests that aren't considered orchestrated.
# It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage
- context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/974', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do
+ context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1755', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do
let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } }
let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } }
let(:project) do
diff --git a/spec/frontend/projects/compare/components/app_legacy_spec.js b/spec/frontend/projects/compare/components/app_legacy_spec.js
index 4c7f0d5cccc..93e96c8b9f7 100644
--- a/spec/frontend/projects/compare/components/app_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/app_legacy_spec.js
@@ -8,7 +8,7 @@ jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
const projectCompareIndexPath = 'some/path';
const refsProjectPath = 'some/refs/path';
const paramsFrom = 'master';
-const paramsTo = 'master';
+const paramsTo = 'some-other-branch';
describe('CompareApp component', () => {
let wrapper;
@@ -36,6 +36,9 @@ describe('CompareApp component', () => {
createComponent();
});
+ const findSourceDropdown = () => wrapper.find('[data-testid="sourceRevisionDropdown"]');
+ const findTargetDropdown = () => wrapper.find('[data-testid="targetRevisionDropdown"]');
+
it('renders component with prop', () => {
expect(wrapper.props()).toEqual(
expect.objectContaining({
@@ -62,12 +65,31 @@ describe('CompareApp component', () => {
expect(wrapper.find('[data-testid="ellipsis"]').exists()).toBe(true);
});
- it('render Source and Target BranchDropdown components', () => {
- const branchDropdowns = wrapper.findAll(RevisionDropdown);
+ describe('Source and Target BranchDropdown components', () => {
+ const findAllBranchDropdowns = () => wrapper.findAll(RevisionDropdown);
+
+ it('renders the components with the correct props', () => {
+ expect(findAllBranchDropdowns().length).toBe(2);
+ expect(findSourceDropdown().props('revisionText')).toBe('Source');
+ expect(findTargetDropdown().props('revisionText')).toBe('Target');
+ });
+
+ it('sets the revision when the "selectRevision" event is emitted', async () => {
+ findSourceDropdown().vm.$emit('selectRevision', {
+ direction: 'to',
+ revision: 'some-source-revision',
+ });
+
+ findTargetDropdown().vm.$emit('selectRevision', {
+ direction: 'from',
+ revision: 'some-target-revision',
+ });
+
+ await wrapper.vm.$nextTick();
- expect(branchDropdowns.length).toBe(2);
- expect(branchDropdowns.at(0).props('revisionText')).toBe('Source');
- expect(branchDropdowns.at(1).props('revisionText')).toBe('Target');
+ expect(findTargetDropdown().props('paramsBranch')).toBe('some-target-revision');
+ expect(findSourceDropdown().props('paramsBranch')).toBe('some-source-revision');
+ });
});
describe('compare button', () => {
@@ -87,6 +109,27 @@ describe('CompareApp component', () => {
});
});
+ describe('swap revisions button', () => {
+ const findSwapRevisionsButton = () => wrapper.find('[data-testid="swapRevisionsButton"]');
+
+ it('renders the swap revisions button', () => {
+ expect(findSwapRevisionsButton().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ expect(findSwapRevisionsButton().text()).toBe('Swap revisions');
+ });
+
+ it('swaps revisions when clicked', async () => {
+ findSwapRevisionsButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTargetDropdown().props('paramsBranch')).toBe(paramsTo);
+ expect(findSourceDropdown().props('paramsBranch')).toBe(paramsFrom);
+ });
+ });
+
describe('merge request buttons', () => {
const findProjectMrButton = () => wrapper.find('[data-testid="projectMrButton"]');
const findCreateMrButton = () => wrapper.find('[data-testid="createMrButton"]');
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
index 270c89e674c..ca208395e82 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createFlash from '~/flash';
@@ -29,6 +29,7 @@ describe('RevisionDropdown component', () => {
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
+ createComponent();
});
afterEach(() => {
@@ -39,7 +40,6 @@ describe('RevisionDropdown component', () => {
const findGlDropdown = () => wrapper.find(GlDropdown);
it('sets hidden input', () => {
- createComponent();
expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe(
defaultProps.paramsBranch,
);
@@ -68,8 +68,6 @@ describe('RevisionDropdown component', () => {
Tags: undefined,
});
- createComponent();
-
await axios.waitForAll();
expect(wrapper.vm.branches).toEqual([]);
@@ -79,15 +77,12 @@ describe('RevisionDropdown component', () => {
it('shows flash message on error', async () => {
axiosMock.onGet('some/invalid/path').replyOnce(404);
- createComponent();
-
await wrapper.vm.fetchBranchesAndTags();
expect(createFlash).toHaveBeenCalled();
});
describe('GlDropdown component', () => {
it('renders props', () => {
- createComponent();
expect(wrapper.props()).toEqual(expect.objectContaining(defaultProps));
});
@@ -99,8 +94,22 @@ describe('RevisionDropdown component', () => {
});
it('display params branch text', () => {
- createComponent();
expect(findGlDropdown().props('text')).toBe(defaultProps.paramsBranch);
});
+
+ it('emits a "selectRevision" event when a revision is selected', async () => {
+ const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findFirstGlDropdownItem = () => findGlDropdownItems().at(0);
+
+ wrapper.setData({ branches: ['some-branch'] });
+
+ await wrapper.vm.$nextTick();
+
+ findFirstGlDropdownItem().vm.$emit('click');
+
+ expect(wrapper.emitted()).toEqual({
+ selectRevision: [[{ direction: 'from', revision: 'some-branch' }]],
+ });
+ });
});
});
diff --git a/spec/tooling/lib/tooling/kubernetes_client_spec.rb b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
index 4a84ec09b5c..636727401af 100644
--- a/spec/tooling/lib/tooling/kubernetes_client_spec.rb
+++ b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
@@ -123,6 +123,16 @@ RSpec.describe Tooling::KubernetesClient do
it_behaves_like 'a kubectl command to delete resources by older than given creation time'
end
+
+ context 'with no resources found' do
+ let(:resource_names) { [] }
+
+ it 'does not call #delete_by_exact_names' do
+ expect(subject).not_to receive(:delete_by_exact_names)
+
+ subject.cleanup_by_created_at(resource_type: resource_type, created_before: two_days_ago)
+ end
+ end
end
describe '#raw_resource_names' do
diff --git a/tooling/lib/tooling/kubernetes_client.rb b/tooling/lib/tooling/kubernetes_client.rb
index 35605fd493c..9bc5626db6b 100644
--- a/tooling/lib/tooling/kubernetes_client.rb
+++ b/tooling/lib/tooling/kubernetes_client.rb
@@ -22,6 +22,8 @@ module Tooling
def cleanup_by_created_at(resource_type:, created_before:, wait: true)
resource_names = resource_names_created_before(resource_type: resource_type, created_before: created_before)
+ return if resource_names.empty?
+
delete_by_exact_names(resource_type: resource_type, resource_names: resource_names, wait: wait)
end