diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js deleted file mode 100644 index 6017cd653e4..00000000000 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js +++ /dev/null @@ -1,54 +0,0 @@ -import $ from 'jquery'; -import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; - -export default class TargetBranchDropdown { - constructor() { - this.$dropdown = $('.js-target-branch-dropdown'); - this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text'); - this.$input = $('#schedule_ref'); - this.initDefaultBranch(); - this.initDropdown(); - } - - initDropdown() { - initDeprecatedJQueryDropdown(this.$dropdown, { - data: this.formatBranchesList(), - filterable: true, - selectable: true, - toggleLabel: (item) => item.name, - search: { - fields: ['name'], - }, - clicked: (cfg) => this.updateInputValue(cfg), - text: (item) => item.name, - }); - - this.setDropdownToggle(); - } - - formatBranchesList() { - return this.$dropdown.data('data').map((val) => ({ name: val })); - } - - setDropdownToggle() { - const initialValue = this.$input.val(); - - this.$dropdownToggle.text(initialValue); - } - - initDefaultBranch() { - const initialValue = this.$input.val(); - const defaultBranch = this.$dropdown.data('defaultBranch'); - - if (!initialValue) { - this.$input.val(defaultBranch); - } - } - - updateInputValue({ selectedObj, e }) { - e.preventDefault(); - - this.$input.val(selectedObj.name); - gl.pipelineScheduleFieldErrors.updateFormValidityState(); - } -} diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js index 9056c76d6ca..9c039a6be81 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js @@ -1,10 +1,12 @@ import $ from 'jquery'; import Vue from 'vue'; +import { __ } from '~/locale'; +import RefSelector from '~/ref/components/ref_selector.vue'; +import { REF_TYPE_BRANCHES, REF_TYPE_TAGS } from '~/ref/constants'; import setupNativeFormVariableList from '../../../../ci_variable_list/native_form_variable_list'; import GlFieldErrors from '../../../../gl_field_errors'; import Translate from '../../../../vue_shared/translate'; import intervalPatternInput from './components/interval_pattern_input.vue'; -import TargetBranchDropdown from './components/target_branch_dropdown'; import TimezoneDropdown from './components/timezone_dropdown'; Vue.use(Translate); @@ -30,6 +32,52 @@ function initIntervalPatternInput() { }); } +function getEnabledRefTypes() { + const refTypes = [REF_TYPE_BRANCHES]; + + if (gon.features.pipelineSchedulesWithTags) { + refTypes.push(REF_TYPE_TAGS); + } + + return refTypes; +} + +function initTargetRefDropdown() { + const $refField = document.getElementById('schedule_ref'); + const el = document.querySelector('.js-target-ref-dropdown'); + const { projectId, defaultBranch } = el.dataset; + + if (!$refField.value) { + $refField.value = defaultBranch; + } + + const refDropdown = new Vue({ + el, + render(h) { + return h(RefSelector, { + props: { + enabledRefTypes: getEnabledRefTypes(), + projectId, + value: $refField.value, + useSymbolicRefNames: true, + translations: { + dropdownHeader: gon.features.pipelineSchedulesWithTags + ? __('Select target branch or tag') + : __('Select target branch'), + }, + }, + class: 'gl-w-full', + }); + }, + }); + + refDropdown.$children[0].$on('input', (newRef) => { + $refField.value = newRef; + }); + + return refDropdown; +} + export default () => { /* Most of the form is written in haml, but for fields with more complex behaviors, * you should mount individual Vue components here. If at some point components need @@ -48,9 +96,10 @@ export default () => { gl.pipelineScheduleFieldErrors.updateFormValidityState(); }, }); - gl.targetBranchDropdown = new TargetBranchDropdown(); gl.pipelineScheduleFieldErrors = new GlFieldErrors(formElement); + initTargetRefDropdown(); + setupNativeFormVariableList({ container: $('.js-ci-variable-list-section'), formField: 'schedule', diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue index ce781c64006..d02526160fd 100644 --- a/app/assets/javascripts/ref/components/ref_selector.vue +++ b/app/assets/javascripts/ref/components/ref_selector.vue @@ -58,6 +58,11 @@ export default { required: false, default: () => ({}), }, + useSymbolicRefNames: { + type: Boolean, + required: false, + default: false, + }, /** The validation state of this component. */ state: { @@ -121,8 +126,15 @@ export default { query: this.lastQuery, }; }, + selectedRefForDisplay() { + if (this.useSymbolicRefNames && this.selectedRef) { + return this.selectedRef.replace(/^refs\/(tags|heads)\//, ''); + } + + return this.selectedRef; + }, buttonText() { - return this.selectedRef || this.i18n.noRefSelected; + return this.selectedRefForDisplay || this.i18n.noRefSelected; }, }, watch: { @@ -164,9 +176,20 @@ export default { }, { immediate: true }, ); + + this.$watch( + 'useSymbolicRefNames', + () => this.setUseSymbolicRefNames(this.useSymbolicRefNames), + { immediate: true }, + ); }, methods: { - ...mapActions(['setEnabledRefTypes', 'setProjectId', 'setSelectedRef']), + ...mapActions([ + 'setEnabledRefTypes', + 'setUseSymbolicRefNames', + 'setProjectId', + 'setSelectedRef', + ]), ...mapActions({ storeSearch: 'search' }), focusSearchBox() { this.$refs.searchBox.$el.querySelector('input').focus(); diff --git a/app/assets/javascripts/ref/stores/actions.js b/app/assets/javascripts/ref/stores/actions.js index 3832cc0c21d..a6019f21e73 100644 --- a/app/assets/javascripts/ref/stores/actions.js +++ b/app/assets/javascripts/ref/stores/actions.js @@ -5,6 +5,9 @@ import * as types from './mutation_types'; export const setEnabledRefTypes = ({ commit }, refTypes) => commit(types.SET_ENABLED_REF_TYPES, refTypes); +export const setUseSymbolicRefNames = ({ commit }, useSymbolicRefNames) => + commit(types.SET_USE_SYMBOLIC_REF_NAMES, useSymbolicRefNames); + export const setProjectId = ({ commit }, projectId) => commit(types.SET_PROJECT_ID, projectId); export const setSelectedRef = ({ commit }, selectedRef) => diff --git a/app/assets/javascripts/ref/stores/mutation_types.js b/app/assets/javascripts/ref/stores/mutation_types.js index c26f4fa00c7..4c602908cae 100644 --- a/app/assets/javascripts/ref/stores/mutation_types.js +++ b/app/assets/javascripts/ref/stores/mutation_types.js @@ -1,4 +1,5 @@ export const SET_ENABLED_REF_TYPES = 'SET_ENABLED_REF_TYPES'; +export const SET_USE_SYMBOLIC_REF_NAMES = 'SET_USE_SYMBOLIC_REF_NAMES'; export const SET_PROJECT_ID = 'SET_PROJECT_ID'; export const SET_SELECTED_REF = 'SET_SELECTED_REF'; diff --git a/app/assets/javascripts/ref/stores/mutations.js b/app/assets/javascripts/ref/stores/mutations.js index f91cbae8462..e078d3333d4 100644 --- a/app/assets/javascripts/ref/stores/mutations.js +++ b/app/assets/javascripts/ref/stores/mutations.js @@ -7,6 +7,9 @@ export default { [types.SET_ENABLED_REF_TYPES](state, refTypes) { state.enabledRefTypes = refTypes; }, + [types.SET_USE_SYMBOLIC_REF_NAMES](state, useSymbolicRefNames) { + state.useSymbolicRefNames = useSymbolicRefNames; + }, [types.SET_PROJECT_ID](state, projectId) { state.projectId = projectId; }, @@ -28,6 +31,7 @@ export default { state.matches.branches = { list: convertObjectPropsToCamelCase(response.data).map((b) => ({ name: b.name, + value: state.useSymbolicRefNames ? `refs/heads/${b.name}` : undefined, default: b.default, })), totalCount: parseInt(response.headers[X_TOTAL_HEADER], 10), @@ -46,6 +50,7 @@ export default { state.matches.tags = { list: convertObjectPropsToCamelCase(response.data).map((b) => ({ name: b.name, + value: state.useSymbolicRefNames ? `refs/tags/${b.name}` : undefined, })), totalCount: parseInt(response.headers[X_TOTAL_HEADER], 10), error: null, diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index ac94cc001dd..271c31b6429 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -10,6 +10,10 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play] before_action :authorize_admin_pipeline_schedule!, only: [:destroy] + before_action do + push_frontend_feature_flag(:pipeline_schedules_with_tags, @project, default_enabled: :yaml) + end + feature_category :continuous_integration # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb index b915495ac38..96e5567e85e 100644 --- a/app/models/ci/pipeline_schedule.rb +++ b/app/models/ci/pipeline_schedule.rb @@ -66,6 +66,18 @@ module Ci project.actual_limits.limit_for(:ci_daily_pipeline_schedule_triggers) end + def ref_for_display + return unless ref.present? + + ref.gsub(%r{^refs/(heads|tags)/}, '') + end + + def for_tag? + return false unless ref.present? + + ref.start_with? 'refs/tags/' + end + private def worker_cron_expression diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml index 66aee7dedf3..5208f58ae87 100644 --- a/app/views/projects/pipeline_schedules/_form.html.haml +++ b/app/views/projects/pipeline_schedules/_form.html.haml @@ -15,8 +15,9 @@ = f.text_field :cron_timezone, value: @schedule.cron_timezone, id: 'schedule_cron_timezone', class: 'hidden', name: 'schedule[cron_timezone]', required: true .form-group.row .col-md-9 - = f.label :ref, _('Target Branch'), class: 'label-bold' - = dropdown_tag(_("Select target branch"), options: { toggle_class: 'gl-button btn btn-default js-target-branch-dropdown w-100', dropdown_class: 'git-revision-dropdown w-100', title: _("Select target branch"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: @project.repository.branch_names, default_branch: @project.default_branch } } ) + = f.label :ref, Feature.enabled?(:pipeline_schedules_with_tags) ? _('Target branch or tag') : _('Target branch'), class: 'label-bold' + %div{ data: { testid: 'schedule-target-ref' } } + .js-target-ref-dropdown{ data: { project_id: @project.id, default_branch: @project.default_branch } } = f.text_field :ref, value: @schedule.ref, id: 'schedule_ref', class: 'hidden', name: 'schedule[ref]', required: true .form-group.row.js-ci-variable-list-section .col-md-9 diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml index 908de68f825..edcd44563f7 100644 --- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml +++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml @@ -3,9 +3,12 @@ %td = pipeline_schedule.description %td.branch-name-cell - = sprite_icon('fork', size: 12) + - if pipeline_schedule.for_tag? + = sprite_icon('tag', size: 12) + - else + = sprite_icon('fork', size: 12) - if pipeline_schedule.ref.present? - = link_to pipeline_schedule.ref, project_ref_path(@project, pipeline_schedule.ref), class: "ref-name" + = link_to pipeline_schedule.ref_for_display, project_ref_path(@project, pipeline_schedule.ref_for_display), class: "ref-name" %td - if pipeline_schedule.last_pipeline .status-icon-container{ class: "ci-status-icon-#{pipeline_schedule.last_pipeline.status}" } diff --git a/app/views/shared/milestones/_delete_button.html.haml b/app/views/shared/milestones/_delete_button.html.haml index 6d4ff255f06..8a709a36835 100644 --- a/app/views/shared/milestones/_delete_button.html.haml +++ b/app/views/shared/milestones/_delete_button.html.haml @@ -6,7 +6,7 @@ milestone_issue_count: @milestone.issues.count, milestone_merge_request_count: @milestone.merge_requests.count }, disabled: true } + = gl_loading_icon(inline: true, css_class: "gl-mr-2 js-loading-icon hidden") = _('Delete') - .gl-spinner.js-loading-icon.hidden #js-delete-milestone-modal diff --git a/config/feature_flags/development/pipeline_schedules_with_tags.yml b/config/feature_flags/development/pipeline_schedules_with_tags.yml new file mode 100644 index 00000000000..8d58ff27135 --- /dev/null +++ b/config/feature_flags/development/pipeline_schedules_with_tags.yml @@ -0,0 +1,8 @@ +--- +name: pipeline_schedules_with_tags +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81476 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354421 +milestone: '14.9' +type: development +group: group::pipeline execution +default_enabled: false diff --git a/data/deprecations/14-9-system_monitoring.yml b/data/deprecations/14-9-system_monitoring.yml new file mode 100644 index 00000000000..09901d9f0e8 --- /dev/null +++ b/data/deprecations/14-9-system_monitoring.yml @@ -0,0 +1,14 @@ +- name: "GitLab self-monitoring" # The name of the feature to be deprecated + announcement_milestone: "14.9" # The milestone when this feature was first announced as deprecated. + announcement_date: "2022-03-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. + removal_milestone: "15.0" # The milestone when this feature is planned to be removed + removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. + breaking_change: true # If this deprecation is a breaking change, set this value to true + reporter: abellucci # GitLab username of the person reporting the deprecation + body: | # Do not modify this line, instead modify the lines below. + GitLab self-monitoring gives administrators of self-hosted GitLab instances the tools to monitor the health of their instances. This feature is deprecated in GitLab 14.9, and is scheduled for removal in 15.0. +# The following items are not published on the docs page, but may be used in the future. + stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth + tiers: [Core, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] + issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348909 # (optional) This is a link to the deprecation issue in GitLab + documentation_url: https://docs.gitlab.com/ee/administration/monitoring/gitlab_self_monitoring_project/ # (optional) This is a link to the current documentation page diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md index 04121753372..09cef51d14c 100644 --- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md +++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md @@ -4,10 +4,15 @@ group: Respond info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Self-monitoring project **(FREE SELF)** +# Self-monitoring project (DEPRECATED) **(FREE SELF)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32351) in GitLab 12.7 [with a flag](../../feature_flags.md) named `self_monitoring_project`. Disabled by default. > - Generally available in GitLab 12.8. [Feature flag `self_monitoring_project`](https://gitlab.com/gitlab-org/gitlab/-/issues/198511) removed. +> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/348909) in GitLab 14.9. Planned for removal in GitLab 15.0. + +WARNING: +This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/348909) +for use in GitLab 14.9, and is planned for removal in GitLab 15.0. GitLab provides administrators insights into the health of their GitLab instance. diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md index 76ab00eebfb..049869d13eb 100644 --- a/doc/development/i18n/proofreader.md +++ b/doc/development/i18n/proofreader.md @@ -98,6 +98,7 @@ are very appreciative of the work done by translators and proofreaders! - Paulo George Gomes Bezerra - [GitLab](https://gitlab.com/paulobezerra), [Crowdin](https://crowdin.com/profile/paulogomes.rep) - André Gama - [GitLab](https://gitlab.com/andregamma), [Crowdin](https://crowdin.com/profile/ToeOficial) - Eduardo Addad de Oliveira - [GitLab](https://gitlab.com/eduardoaddad), [Crowdin](https://crowdin.com/profile/eduardoaddad) + - Horberlan Brito - [GitLab](https://gitlab.com/horberlan), [Crowdin](https://crowdin.com/profile/horberlan) - Romanian - Mircea Pop - [GitLab](https://gitlab.com/eeex), [Crowdin](https://crowdin.com/profile/eex) - Rareș Pița - [GitLab](https://gitlab.com/dlphin), [Crowdin](https://crowdin.com/profile/dlphin) @@ -110,6 +111,8 @@ are very appreciative of the work done by translators and proofreaders! - Iaroslav Postovalov - [GitLab](https://gitlab.com/CMDR_Tvis), [Crowdin](https://crowdin.com/profile/CMDR_Tvis) - Serbian (Latin and Cyrillic) - Proofreaders needed. +- Sinhalese/Sinhala සිංහල + - හෙළබස (HelaBasa) - [GitLab](https://gitlab.com/helabasa), [Crowdin](https://crowdin.com/profile/helabasa) - Slovak - Proofreaders needed. - Spanish diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index eac968f2f34..5c5effaa40d 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -36,6 +36,20 @@ For deprecation reviewers (Technical Writers only): https://about.gitlab.com/handbook/marketing/blog/release-posts/#update-the-deprecations-doc --> +## 14.9 + +### GitLab self-monitoring + +WARNING: +This feature will be changed or removed in 15.0 +as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes). +Before updating GitLab, review the details carefully to determine if you need to make any +changes to your code, settings, or workflow. + +GitLab self-monitoring gives administrators of self-hosted GitLab instances the tools to monitor the health of their instances. This feature is deprecated in GitLab 14.9, and is scheduled for removal in 15.0. + +**Planned removal milestone: 15.0 (2022-05-22)** + ## 14.8 ### Changes to the `CI_JOB_JWT` diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md index cdc3fe02a53..0c16b535ed1 100644 --- a/doc/user/group/import/index.md +++ b/doc/user/group/import/index.md @@ -132,3 +132,25 @@ migrated: - image URL - Boards - Board Lists + +## Troubleshooting Group Migration + +In a [rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session), +you can find the failure or error messages for the group import attempt using: + +```shell +# Get relevant import records +import = BulkImports::Entity.where(namespace_id: Group.id).bulk_import + +# Alternative lookup by user +import = BulkImport.where(user_id: User.find(...)).last + +# Get list of import entities. Each entity represents either a group or a project +entities = import.entities + +# Get a list of entity failures +entities.map(&:failures).flatten + +# Alternative failure lookup by status +entities.where(status: [-1]).pluck(:destination_name, :destination_namespace, :status) +``` diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake index c47528fc4ee..50ceb11581e 100644 --- a/lib/tasks/gitlab/db.rake +++ b/lib/tasks/gitlab/db.rake @@ -163,6 +163,11 @@ namespace :gitlab do end ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name| + # We'll temporarily skip this enhancement for geo, since in some situations we + # wish to setup the geo database before the other databases have been setup, + # and partition management attempts to connect to the main database. + next if name == 'geo' + Rake::Task["db:migrate:#{name}"].enhance do Rake::Task['gitlab:db:create_dynamic_partitions'].invoke end @@ -181,6 +186,11 @@ namespace :gitlab do end ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name| + # We'll temporarily skip this enhancement for geo, since in some situations we + # wish to setup the geo database before the other databases have been setup, + # and partition management attempts to connect to the main database. + next if name == 'geo' + Rake::Task["db:schema:load:#{name}"].enhance do Rake::Task['gitlab:db:create_dynamic_partitions'].invoke end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index fff136c55ae..95e0fd5d5bb 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6840,6 +6840,9 @@ msgstr "" msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open." msgstr "" +msgid "Changed" +msgstr "" + msgid "Changed assignee(s)." msgstr "" @@ -30901,6 +30904,9 @@ msgstr "" msgid "Reports|Identifier" msgstr "" +msgid "Reports|Metrics report scanning detected no new changes" +msgstr "" + msgid "Reports|Metrics reports are loading" msgstr "" @@ -30913,6 +30919,12 @@ msgstr "" msgid "Reports|Metrics reports failed loading results" msgstr "" +msgid "Reports|Metrics reports failed to load results" +msgstr "" + +msgid "Reports|Metrics reports: %{strong_start}%{numberOfChanges}%{strong_end} %{changes}" +msgstr "" + msgid "Reports|Scanner" msgstr "" @@ -33289,6 +33301,9 @@ msgstr "" msgid "Select target branch" msgstr "" +msgid "Select target branch or tag" +msgstr "" + msgid "Select timezone" msgstr "" @@ -36041,6 +36056,9 @@ msgstr "" msgid "Target branch" msgstr "" +msgid "Target branch or tag" +msgstr "" + msgid "Target-Branch" msgstr "" @@ -43009,6 +43027,11 @@ msgstr "" msgid "cannot merge" msgstr "" +msgid "change" +msgid_plural "changes" +msgstr[0] "" +msgstr[1] "" + msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_start}%{sameNum} same%{same_end}, and %{success_start}%{improvedNum} improved%{success_end}" msgstr "" diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index aae5ab58b5d..63867a7e900 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -135,8 +135,8 @@ RSpec.describe 'Pipeline Schedules', :js do end it 'shows the pipeline schedule with default ref' do - page.within('.js-target-branch-dropdown') do - expect(first('.dropdown-toggle-text').text).to eq('master') + page.within('[data-testid="schedule-target-ref"]') do + expect(first('.gl-new-dropdown-button-text').text).to eq('master') end end end @@ -148,8 +148,8 @@ RSpec.describe 'Pipeline Schedules', :js do end it 'shows the pipeline schedule with default ref' do - page.within('.js-target-branch-dropdown') do - expect(first('.dropdown-toggle-text').text).to eq('master') + page.within('[data-testid="schedule-target-ref"]') do + expect(first('.gl-new-dropdown-button-text').text).to eq('master') end end end @@ -293,8 +293,8 @@ RSpec.describe 'Pipeline Schedules', :js do end def select_target_branch - find('.js-target-branch-dropdown').click - click_link 'master' + find('[data-testid="schedule-target-ref"] .dropdown-toggle').click + click_button 'master' end def save_pipeline_schedule diff --git a/spec/frontend/ref/components/__snapshots__/ref_selector_spec.js.snap b/spec/frontend/ref/components/__snapshots__/ref_selector_spec.js.snap index 5f05b7fc68b..5053778369e 100644 --- a/spec/frontend/ref/components/__snapshots__/ref_selector_spec.js.snap +++ b/spec/frontend/ref/components/__snapshots__/ref_selector_spec.js.snap @@ -10,30 +10,37 @@ Object { Object { "default": false, "name": "add_images_and_changes", + "value": undefined, }, Object { "default": false, "name": "conflict-contains-conflict-markers", + "value": undefined, }, Object { "default": false, "name": "deleted-image-test", + "value": undefined, }, Object { "default": false, "name": "diff-files-image-to-symlink", + "value": undefined, }, Object { "default": false, "name": "diff-files-symlink-to-image", + "value": undefined, }, Object { "default": false, "name": "markdown", + "value": undefined, }, Object { "default": true, "name": "master", + "value": undefined, }, ], "totalCount": 123, @@ -54,12 +61,15 @@ Object { "list": Array [ Object { "name": "v1.1.1", + "value": undefined, }, Object { "name": "v1.1.0", + "value": undefined, }, Object { "name": "v1.0.0", + "value": undefined, }, ], "totalCount": 456, diff --git a/spec/frontend/ref/stores/mutations_spec.js b/spec/frontend/ref/stores/mutations_spec.js index de1d5c557ce..37eee18dc10 100644 --- a/spec/frontend/ref/stores/mutations_spec.js +++ b/spec/frontend/ref/stores/mutations_spec.js @@ -48,6 +48,14 @@ describe('Ref selector Vuex store mutations', () => { }); }); + describe(`${types.SET_USE_SYMBOLIC_REF_NAMES}`, () => { + it('sets useSymbolicRefNames on the state', () => { + mutations[types.SET_USE_SYMBOLIC_REF_NAMES](state, true); + + expect(state.useSymbolicRefNames).toBe(true); + }); + }); + describe(`${types.SET_PROJECT_ID}`, () => { it('updates the project ID', () => { const newProjectId = '4'; diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb index 0f4f148775e..3c295fb345b 100644 --- a/spec/models/ci/pipeline_schedule_spec.rb +++ b/spec/models/ci/pipeline_schedule_spec.rb @@ -228,6 +228,66 @@ RSpec.describe Ci::PipelineSchedule do end end + describe '#for_tag?' do + context 'when the target is a tag' do + before do + subject.ref = 'refs/tags/v1.0' + end + + it { expect(subject.for_tag?).to eq(true) } + end + + context 'when the target is a branch' do + before do + subject.ref = 'refs/heads/main' + end + + it { expect(subject.for_tag?).to eq(false) } + end + + context 'when there is no ref' do + before do + subject.ref = nil + end + + it { expect(subject.for_tag?).to eq(false) } + end + end + + describe '#ref_for_display' do + context 'when the target is a tag' do + before do + subject.ref = 'refs/tags/v1.0' + end + + it { expect(subject.ref_for_display).to eq('v1.0') } + end + + context 'when the target is a branch' do + before do + subject.ref = 'refs/heads/main' + end + + it { expect(subject.ref_for_display).to eq('main') } + end + + context 'when the ref is ambiguous' do + before do + subject.ref = 'release-2.8' + end + + it { expect(subject.ref_for_display).to eq('release-2.8') } + end + + context 'when there is no ref' do + before do + subject.ref = nil + end + + it { expect(subject.ref_for_display).to eq(nil) } + end + end + context 'loose foreign key on ci_pipeline_schedules.project_id' do it_behaves_like 'cleanup by a loose foreign key' do let!(:parent) { create(:project) } diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb index 4f7afc2f17d..8d3ec7b1ee2 100644 --- a/spec/tasks/gitlab/db_rake_spec.rb +++ b/spec/tasks/gitlab/db_rake_spec.rb @@ -489,6 +489,20 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do expect { run_rake_task('db:migrate:main') }.not_to raise_error end end + + describe 'db:migrate:geo' do + it 'does not invoke gitlab:db:create_dynamic_partitions' do + skip 'Skipping because geo database is not setup' unless geo_configured? + + expect(Rake::Task['gitlab:db:create_dynamic_partitions']).not_to receive(:invoke) + + expect { run_rake_task('db:migrate:geo') }.not_to raise_error + end + + def geo_configured? + !!ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'geo') + end + end end describe 'gitlab:db:reset_as_non_superuser' do