diff --git a/.gitlab/ci/package-and-test/main.gitlab-ci.yml b/.gitlab/ci/package-and-test/main.gitlab-ci.yml index 1f7ed5aa2e6..e621c959e9d 100644 --- a/.gitlab/ci/package-and-test/main.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test/main.gitlab-ci.yml @@ -30,19 +30,6 @@ download-fast-quarantine-report: - .download-fast-quarantine-report - .rules:download-fast-quarantine-report -cache-gems: - extends: - - .qa-install - - .ruby-image - - .rules:update-cache - stage: .pre - tags: - - e2e - script: - - echo "Populated qa cache" - cache: - policy: pull-push - # ========================================== # Test stage # ========================================== diff --git a/.gitlab/ci/preflight.gitlab-ci.yml b/.gitlab/ci/preflight.gitlab-ci.yml index 6a2ea85f393..745d85ab084 100644 --- a/.gitlab/ci/preflight.gitlab-ci.yml +++ b/.gitlab/ci/preflight.gitlab-ci.yml @@ -44,7 +44,9 @@ rails-production-server-boot-puma-cng: extends: - .rails-production-server-boot script: - - curl --silent https://gitlab.com/gitlab-org/build/CNG/-/raw/master/gitlab-webservice/configuration/puma.rb > config/puma.rb + - define_trigger_branch_in_build_env + - echo "TRIGGER_BRANCH is defined as ${TRIGGER_BRANCH}" + - curl --silent "https://gitlab.com/gitlab-org/build/CNG/-/raw/${TRIGGER_BRANCH}/gitlab-webservice/configuration/puma.rb" > config/puma.rb - sed --in-place "s:/srv/gitlab:${PWD}:" config/puma.rb - bundle exec puma --environment production --config config/puma.rb & - sleep 40 # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114124#note_1309506358 diff --git a/.gitlab/ci/qa-common/main.gitlab-ci.yml b/.gitlab/ci/qa-common/main.gitlab-ci.yml index c44aa327762..f263c72aed7 100644 --- a/.gitlab/ci/qa-common/main.gitlab-ci.yml +++ b/.gitlab/ci/qa-common/main.gitlab-ci.yml @@ -14,7 +14,7 @@ include: gitlab_auth_token_variable_name: "PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE" allure_job_name: "${QA_RUN_TYPE}" - project: gitlab-org/quality/pipeline-common - ref: 7.10.2 + ref: 7.12.1 file: - /ci/base.gitlab-ci.yml - /ci/knapsack-report.yml diff --git a/.gitlab/ci/qa-common/rules.gitlab-ci.yml b/.gitlab/ci/qa-common/rules.gitlab-ci.yml index 7fa66fa4384..36c601261d8 100644 --- a/.gitlab/ci/qa-common/rules.gitlab-ci.yml +++ b/.gitlab/ci/qa-common/rules.gitlab-ci.yml @@ -64,10 +64,6 @@ rules: - when: always -.rules:update-cache: - rules: - - if: '$UPDATE_QA_CACHE == "true"' - .rules:download-knapsack: rules: - when: always diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index 7c72c301aef..cbb68985bb4 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -62,15 +62,21 @@ qa:master-auto-quarantine-dequarantine: - bundle exec confiner -r .confiner/master.yml allow_failure: true -qa:update-qa-cache: +cache-qa-gems: extends: - .qa-job-base - .qa-cache-push - - .shared:rules:update-cache + - .qa:rules:update-gem-cache stage: prepare script: - echo "Cache has been updated and ready to be uploaded." +# E2E runners have separate infra setup and different cache bucket +cache-qa-gems-e2e-runners: + extends: cache-qa-gems + tags: + - e2e + trigger-omnibus: stage: qa extends: diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 00b10c2ae2b..866a1843744 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -1443,6 +1443,16 @@ ############ # QA rules # ############ +.qa:rules:update-gem-cache: + rules: + - <<: *if-default-refs + changes: + - qa/Gemfile.lock + - <<: *if-schedule-maintenance + - <<: *if-security-schedule + - <<: *if-foss-schedule + - <<: *if-merge-request-labels-update-caches + .qa:rules:code-merge-request-manual: rules: - <<: *if-merge-request @@ -1592,11 +1602,6 @@ - <<: *if-merge-request changes: *ci-qa-patterns allow_failure: true - - <<: *if-merge-request - changes: - - qa/Gemfile.lock # qa/Gemfile.lock is a part of *qa-patterns, so this rule must be placed before the one with *qa-patterns changes - variables: - UPDATE_QA_CACHE: "true" - <<: *if-merge-request changes: *qa-patterns allow_failure: true @@ -1636,11 +1641,6 @@ when: manual - <<: *if-merge-request changes: *nodejs-patterns - - <<: *if-merge-request - changes: - - qa/Gemfile.lock # qa/Gemfile.lock is a part of *qa-patterns, so this rule must be placed before the one with *qa-patterns changes - variables: - UPDATE_QA_CACHE: "true" - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified changes: *code-patterns - <<: *if-merge-request @@ -1657,7 +1657,6 @@ CREATE_TEST_FAILURE_ISSUES: "true" PROCESS_TEST_RESULTS: "true" KNAPSACK_GENERATE_REPORT: "true" - UPDATE_QA_CACHE: "true" QA_SAVE_TEST_METRICS: "true" QA_EXPORT_TEST_METRICS: "false" # on main runs, metrics are exported to separate bucket via rake task for better consistency diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml index cc5e9bd2985..a101901d57b 100644 --- a/.gitlab/ci/setup.gitlab-ci.yml +++ b/.gitlab/ci/setup.gitlab-ci.yml @@ -197,8 +197,7 @@ trigger-omnibus-env: echo "NEXT_RUBY_VERSION=${NEXT_RUBY_VERSION}" >> $BUILD_ENV echo "GITLAB_ASSETS_TAG=$(assets_image_tag)" >> $BUILD_ENV echo "EE=$([[ $FOSS_ONLY == '1' ]] && echo 'false' || echo 'true')" >> $BUILD_ENV - target_branch_name="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_COMMIT_REF_NAME}}" - echo "TRIGGER_BRANCH=$([[ "${target_branch_name}" =~ ^[0-9-]+-stable(-ee)?$ ]] && echo ${target_branch_name%-ee} || echo 'master')" >> $BUILD_ENV + define_trigger_branch_in_build_env - | echo "Built environment file for omnibus build:" cat $BUILD_ENV diff --git a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml index f0a5ea5090f..d56564b1295 100644 --- a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml +++ b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml @@ -124,17 +124,6 @@ download-knapsack-report: - .download-knapsack-report - .rules:download-knapsack -cache-gems: - extends: - - .ruby-image - - .qa-cache-push - - .rules:update-cache - stage: .pre - tags: - - e2e - script: - - cd qa && bundle install - # Take the existing GDK docker image and reconfigure it with Postgres load # balancing. Adding 5s lag to 1 of the replicas to validate robustness of # the load balancer. diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 40ee5c26ff4..42b84f073a4 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -db9003ccaed4618cb6c9e1d8ce99f7794c868a65 +6835085898eb8d3881ee98c476a7bfc2981f0067 diff --git a/app/assets/javascripts/admin/abuse_report/components/abuse_report_notes.vue b/app/assets/javascripts/admin/abuse_report/components/abuse_report_notes.vue index 80af7d7400a..29de7e1ad1d 100644 --- a/app/assets/javascripts/admin/abuse_report/components/abuse_report_notes.vue +++ b/app/assets/javascripts/admin/abuse_report/components/abuse_report_notes.vue @@ -6,6 +6,7 @@ import SkeletonLoadingContainer from '~/vue_shared/components/notes/skeleton_not import { SKELETON_NOTES_COUNT } from '~/admin/abuse_report/constants'; import abuseReportNotesQuery from '../graphql/notes/abuse_report_notes.query.graphql'; import AbuseReportDiscussion from './notes/abuse_report_discussion.vue'; +import AbuseReportAddNote from './notes/abuse_report_add_note.vue'; export default { name: 'AbuseReportNotes', @@ -16,6 +17,7 @@ export default { components: { SkeletonLoadingContainer, AbuseReportDiscussion, + AbuseReportAddNote, }, props: { abuseReportId: { @@ -60,6 +62,9 @@ export default { const discussionId = discussion.notes.nodes[0].id; return discussionId.split('/')[discussionId.split('/').length - 1]; }, + updateKey() { + this.addNoteKey = uniqueId(`abuse-report-add-note-${this.abuseReportId}`); + }, }, }; @@ -86,6 +91,16 @@ export default { :abuse-report-id="abuseReportId" /> +
+ +
diff --git a/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_add_note.vue b/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_add_note.vue new file mode 100644 index 00000000000..3c709fc565f --- /dev/null +++ b/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_add_note.vue @@ -0,0 +1,138 @@ + + + diff --git a/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_comment_form.vue b/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_comment_form.vue new file mode 100644 index 00000000000..646ffc690d0 --- /dev/null +++ b/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_comment_form.vue @@ -0,0 +1,136 @@ + + + diff --git a/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_discussion.vue b/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_discussion.vue index 4d24471fa43..49ba777f697 100644 --- a/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_discussion.vue +++ b/app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_discussion.vue @@ -4,6 +4,7 @@ import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item import DiscussionNotesRepliesWrapper from '~/notes/components/discussion_notes_replies_wrapper.vue'; import ToggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue'; import AbuseReportNote from './abuse_report_note.vue'; +import AbuseReportAddNote from './abuse_report_add_note.vue'; export default { name: 'AbuseReportDiscussion', @@ -12,6 +13,7 @@ export default { DiscussionNotesRepliesWrapper, ToggleRepliesWidget, AbuseReportNote, + AbuseReportAddNote, }, props: { abuseReportId: { @@ -92,6 +94,11 @@ export default { :abuse-report-id="abuseReportId" /> + diff --git a/app/assets/javascripts/admin/abuse_report/index.js b/app/assets/javascripts/admin/abuse_report/index.js index c2117130d26..e4319b3edef 100644 --- a/app/assets/javascripts/admin/abuse_report/index.js +++ b/app/assets/javascripts/admin/abuse_report/index.js @@ -30,6 +30,7 @@ export const initAbuseReportApp = () => { allowScopedLabels: false, updatePath: abuseReport.report.updatePath, listPath: abuseReportsListPath, + uploadNoteAttachmentPath: abuseReport.uploadNoteAttachmentPath, labelsManagePath: '', allowLabelCreate: true, }, diff --git a/app/assets/javascripts/ci/pipeline_details/pipelines_index.js b/app/assets/javascripts/ci/pipeline_details/pipelines_index.js index ea2875713a9..b4528ab895d 100644 --- a/app/assets/javascripts/ci/pipeline_details/pipelines_index.js +++ b/app/assets/javascripts/ci/pipeline_details/pipelines_index.js @@ -44,6 +44,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { params, fullPath, visibilityPipelineIdType, + showJenkinsCiPrompt, } = el.dataset; return new Vue({ @@ -57,6 +58,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => { pipelineEditorPath, pipelineSchedulesPath, suggestedCiTemplates: JSON.parse(suggestedCiTemplates), + showJenkinsCiPrompt: parseBoolean(showJenkinsCiPrompt), }, data() { return { diff --git a/app/assets/javascripts/ci/pipeline_editor/constants.js b/app/assets/javascripts/ci/pipeline_editor/constants.js index e85138e361f..66725df15f0 100644 --- a/app/assets/javascripts/ci/pipeline_editor/constants.js +++ b/app/assets/javascripts/ci/pipeline_editor/constants.js @@ -1,4 +1,5 @@ import { s__ } from '~/locale'; +import { helpPagePath } from '~/helpers/help_page_helper'; export const EDITOR_APP_DRAWER_HELP = 'HELP'; export const EDITOR_APP_DRAWER_JOB_ASSISTANT = 'JOB_ASSISTANT'; @@ -93,6 +94,9 @@ export const VALIDATE_TAB_FEEDBACK_URL = 'https://gitlab.com/gitlab-org/gitlab/- export const COMMIT_SHA_POLL_INTERVAL = 1000; +export const MIGRATION_PLAN_HELP_PATH = helpPagePath('ci/migration/plan_a_migration'); +export const MIGRATE_FROM_JENKINS_TRACKING_LABEL = 'migrate_from_jenkins_prompt'; + export const I18N = { title: s__('Pipelines|Get started with GitLab CI/CD'), learnBasics: { @@ -107,6 +111,13 @@ export const I18N = { ), cta: s__('Pipelines|Try test template'), }, + migrateFromJenkins: { + title: s__('Pipelines|Migrate to GitLab CI/CD from Jenkins'), + description: s__( + 'Pipelines|Take advantage of simple, scalable pipelines and CI/CD-enabled features. You can view integration results, security scans, tests, code coverage and more directly in merge requests!', + ), + cta: s__('Pipelines|Start with a migration plan'), + }, }, templates: { title: s__('Pipelines|Ready to set up CI/CD for your project?'), diff --git a/app/assets/javascripts/ci/pipelines_page/components/empty_state/pipelines_ci_templates.vue b/app/assets/javascripts/ci/pipelines_page/components/empty_state/pipelines_ci_templates.vue index a6297213402..c9631d8f36b 100644 --- a/app/assets/javascripts/ci/pipelines_page/components/empty_state/pipelines_ci_templates.vue +++ b/app/assets/javascripts/ci/pipelines_page/components/empty_state/pipelines_ci_templates.vue @@ -1,7 +1,12 @@ + + + diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js deleted file mode 100644 index 8f3681952c6..00000000000 --- a/app/assets/javascripts/header.js +++ /dev/null @@ -1,50 +0,0 @@ -// TODO: Remove this with the removal of the old navigation. -// See https://gitlab.com/groups/gitlab-org/-/epics/11875. - -import { highCountTrim } from '~/lib/utils/text_utility'; -import Tracking from '~/tracking'; - -/** - * Updates todo counter when todos are toggled. - * When count is 0, we hide the badge. - * - * @param {jQuery.Event} e - * @param {String} count - */ -export default function initTodoToggle() { - document.addEventListener('todo:toggle', (e) => { - const updatedCount = e.detail.count || 0; - const todoPendingCount = document.querySelector('.js-todos-count'); - - if (todoPendingCount) { - todoPendingCount.textContent = highCountTrim(updatedCount); - if (updatedCount === 0) { - todoPendingCount.classList.add('hidden'); - } else { - todoPendingCount.classList.remove('hidden'); - } - } - }); -} - -function trackShowUserDropdownLink(trackEvent, elToTrack, el) { - const { trackLabel, trackProperty } = elToTrack.dataset; - - el.addEventListener('shown.bs.dropdown', () => { - Tracking.event(document.body.dataset.page, trackEvent, { - label: trackLabel, - property: trackProperty, - }); - }); -} - -export function initNavUserDropdownTracking() { - const el = document.querySelector('.js-nav-user-dropdown'); - const buyEl = document.querySelector('.js-buy-pipeline-minutes-link'); - - if (el && buyEl) { - trackShowUserDropdownLink('show_buy_ci_minutes', buyEl, el); - } -} - -requestIdleCallback(initNavUserDropdownTracking); diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index b41f306eabd..43ae13915ad 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -15,7 +15,6 @@ import * as tooltips from '~/tooltips'; import { initPrefetchLinks } from '~/lib/utils/navigation_utility'; import { logHelloDeferred } from 'jh_else_ce/lib/logger/hello_deferred'; import initAlertHandler from './alert_handler'; -import initTodoToggle from './header'; import initLayoutNav from './layout_nav'; import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils'; import { localTimeAgo } from './lib/utils/datetime/timeago_utility'; @@ -86,7 +85,6 @@ function deferredInitialisation() { if (!gon.use_new_navigation) { initTopNav(); - initTodoToggle(); } initBreadcrumbs(); initPrefetchLinks('.js-prefetch-document'); diff --git a/app/assets/javascripts/vue_shared/components/list_selector/constants.js b/app/assets/javascripts/vue_shared/components/list_selector/constants.js index cff9c56a1c0..ad826c6f3e5 100644 --- a/app/assets/javascripts/vue_shared/components/list_selector/constants.js +++ b/app/assets/javascripts/vue_shared/components/list_selector/constants.js @@ -1,6 +1,26 @@ import { __ } from '~/locale'; +import UserItem from './user_item.vue'; +import GroupItem from './group_item.vue'; +import DeployKeyItem from './deploy_key_item.vue'; export const CONFIG = { - users: { title: __('Users'), icon: 'user', filterKey: 'username', showNamespaceDropdown: true }, - groups: { title: __('Groups'), icon: 'group', filterKey: 'name' }, + users: { + title: __('Users'), + icon: 'user', + filterKey: 'username', + showNamespaceDropdown: true, + component: UserItem, + }, + groups: { + title: __('Groups'), + icon: 'group', + filterKey: 'name', + component: GroupItem, + }, + deployKeys: { + title: __('Deploy keys'), + icon: 'key', + filterKey: 'name', + component: DeployKeyItem, + }, }; diff --git a/app/assets/javascripts/vue_shared/components/list_selector/deploy_key_item.vue b/app/assets/javascripts/vue_shared/components/list_selector/deploy_key_item.vue new file mode 100644 index 00000000000..4dbbd44f0b5 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/list_selector/deploy_key_item.vue @@ -0,0 +1,51 @@ + + + diff --git a/app/assets/javascripts/vue_shared/components/list_selector/index.vue b/app/assets/javascripts/vue_shared/components/list_selector/index.vue index b8480a0c496..d79a8d6a00c 100644 --- a/app/assets/javascripts/vue_shared/components/list_selector/index.vue +++ b/app/assets/javascripts/vue_shared/components/list_selector/index.vue @@ -5,8 +5,6 @@ import { createAlert } from '~/alert'; import { __ } from '~/locale'; import groupsAutocompleteQuery from '~/graphql_shared/queries/groups_autocomplete.query.graphql'; import Api from '~/api'; -import UserItem from './user_item.vue'; -import GroupItem from './group_item.vue'; import { CONFIG } from './constants'; const I18N = { @@ -25,10 +23,6 @@ export default { GlCollapsibleListbox, }, props: { - title: { - type: String, - required: true, - }, type: { type: String, required: true, @@ -61,12 +55,6 @@ export default { config() { return CONFIG[this.type]; }, - isUserVariant() { - return this.type === 'users'; - }, - component() { - return this.isUserVariant ? UserItem : GroupItem; - }, namespaceDropdownText() { return parseBoolean(this.isProjectNamespace) ? this.$options.i18n.projectGroups @@ -77,12 +65,14 @@ export default { async handleSearchInput(search) { this.$refs.results.open(); + const searchMethod = { + users: this.fetchUsersBySearchTerm, + groups: this.fetchGroupsBySearchTerm, + deployKeys: this.fetchDeployKeysBySearchTerm, + }; + try { - if (this.isUserVariant) { - this.items = await this.fetchUsersBySearchTerm(search); - } else { - this.items = await this.fetchGroupsBySearchTerm(search); - } + this.items = await searchMethod[this.type](search); } catch (e) { createAlert({ message: this.$options.i18n.apiErrorMessage, @@ -114,6 +104,10 @@ export default { })), ); }, + fetchDeployKeysBySearchTerm() { + // TODO - implement API request (follow-up) + // https://gitlab.com/gitlab-org/gitlab/-/issues/432494 + }, getItemByKey(key) { return this.items.find((item) => item[this.config.filterKey] === key); }, @@ -139,7 +133,7 @@ export default {