From 6190d24e4be16b2f6a1bdde3720dcced73b2f028 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 11 Jun 2024 12:29:44 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/qa-common/variables.gitlab-ci.yml | 2 +- .gitlab/ci/test-on-cng/main.gitlab-ci.yml | 15 +- .../javascripts/pages/projects/wikis/index.js | 2 + .../wikis/components/clone_wiki_modal.vue | 3 +- .../wikis/components/wiki_more_dropdown.vue | 4 +- .../pages/shared/wikis/more_actions.js | 28 + .../javascripts/pages/shared/wikis/show.js | 2 - .../javascripts/pages/shared/wikis/utils.js | 2 +- .../javascripts/pages/shared/wikis/wikis.js | 20 +- .../global_search_autocomplete_items.vue | 50 +- .../global_search/tracking_constants.js | 13 + .../components/logs_viewer/log_line.vue | 4 +- .../work_item_projects_listbox.vue | 11 +- app/views/shared/wikis/_sidebar.html.haml | 2 +- app/views/shared/wikis/diff.html.haml | 14 +- app/views/shared/wikis/history.html.haml | 16 +- app/views/shared/wikis/pages.html.haml | 17 +- app/views/shared/wikis/show.html.haml | 1 - app/views/shared/wikis/templates.html.haml | 10 +- .../click_issue_result_in_command_palette.yml | 17 + ...erge_request_result_in_command_palette.yml | 17 + ..._recent_epic_result_in_command_palette.yml | 17 + ...recent_issue_result_in_command_palette.yml | 17 + ...erge_request_result_in_command_palette.yml | 17 + ...ssue_result_in_command_palette_monthly.yml | 22 + ...uest_result_in_command_palette_monthly.yml | 22 + ...epic_result_in_command_palette_monthly.yml | 22 + ...ssue_result_in_command_palette_monthly.yml | 22 + ...uest_result_in_command_palette_monthly.yml | 22 + ...issue_result_in_command_palette_weekly.yml | 22 + ...quest_result_in_command_palette_weekly.yml | 22 + ..._epic_result_in_command_palette_weekly.yml | 22 + ...issue_result_in_command_palette_weekly.yml | 22 + ...quest_result_in_command_palette_weekly.yml | 22 + danger/tailwindcss/Dangerfile | 20 +- doc/administration/auth/oidc.md | 4 +- doc/api/projects.md | 3 + doc/development/ai_features/index.md | 63 +- doc/development/code_suggestions/index.md | 27 +- doc/development/testing_guide/flaky_tests.md | 4 + .../group/value_stream_analytics/index.md | 7 + locale/gitlab.pot | 3 + scripts/frontend/tailwind_equivalents.json | 546 ++++++++++++++++++ .../issues/user_toggles_subscription_spec.rb | 2 +- .../wikis/components/clone_wiki_modal_spec.js | 1 - .../components/wiki_more_dropdown_spec.js | 1 - .../global_search_autocomplete_items_spec.js | 50 +- .../work_item_projects_listbox_spec.js | 24 +- spec/requests/api/graphql/ci/jobs_spec.rb | 3 +- 49 files changed, 1164 insertions(+), 115 deletions(-) create mode 100644 app/assets/javascripts/pages/shared/wikis/more_actions.js create mode 100644 config/events/click_issue_result_in_command_palette.yml create mode 100644 config/events/click_merge_request_result_in_command_palette.yml create mode 100644 config/events/click_recent_epic_result_in_command_palette.yml create mode 100644 config/events/click_recent_issue_result_in_command_palette.yml create mode 100644 config/events/click_recent_merge_request_result_in_command_palette.yml create mode 100644 config/metrics/counts_28d/count_distinct_user_id_from_click_issue_result_in_command_palette_monthly.yml create mode 100644 config/metrics/counts_28d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_monthly.yml create mode 100644 config/metrics/counts_28d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_monthly.yml create mode 100644 config/metrics/counts_28d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_monthly.yml create mode 100644 config/metrics/counts_28d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_monthly.yml create mode 100644 config/metrics/counts_7d/count_distinct_user_id_from_click_issue_result_in_command_palette_weekly.yml create mode 100644 config/metrics/counts_7d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_weekly.yml create mode 100644 config/metrics/counts_7d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_weekly.yml create mode 100644 config/metrics/counts_7d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_weekly.yml create mode 100644 config/metrics/counts_7d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_weekly.yml create mode 100644 scripts/frontend/tailwind_equivalents.json diff --git a/.gitlab/ci/qa-common/variables.gitlab-ci.yml b/.gitlab/ci/qa-common/variables.gitlab-ci.yml index baed2bc1d1a..a47be5f5a91 100644 --- a/.gitlab/ci/qa-common/variables.gitlab-ci.yml +++ b/.gitlab/ci/qa-common/variables.gitlab-ci.yml @@ -16,4 +16,4 @@ variables: QA_OMNIBUS_MR_TESTS: "only-smoke" # Retry failed specs in separate process QA_RETRY_FAILED_SPECS: "true" - GITLAB_HELM_CHART_REF: "343ef285e2e06c1d66a7077ba3c251bacad56868" # helm chart ref used by test-on-cng pipeline + GITLAB_HELM_CHART_REF: "d1eaee3922df2bfbdc23b55720965c10eec2b93d" # helm chart ref used by test-on-cng pipeline diff --git a/.gitlab/ci/test-on-cng/main.gitlab-ci.yml b/.gitlab/ci/test-on-cng/main.gitlab-ci.yml index cea2bd3fef6..db70200078a 100644 --- a/.gitlab/ci/test-on-cng/main.gitlab-ci.yml +++ b/.gitlab/ci/test-on-cng/main.gitlab-ci.yml @@ -10,13 +10,6 @@ workflow: rules: - when: always -.set-suite-status: - after_script: - - | - if [ "$CI_JOB_STATUS" == "failed" ]; then - echo "SUITE_FAILED=true" >> "$QA_SUITE_STATUS_ENV_FILE" - fi - .cng-base: image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:bundler-${BUNDLER_VERSION}-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-kubectl-1.23-helm-3.14-kind-0.20 stage: test @@ -72,6 +65,10 @@ workflow: retry_failed_e2e_rspec_examples fi after_script: + - | + if [ "$CI_JOB_STATUS" == "failed" ]; then + echo "SUITE_FAILED=true" >> "$QA_SUITE_STATUS_ENV_FILE" + fi - cd qa - bundle exec cng log events --save - bundle exec cng log pods --save --containers all @@ -119,7 +116,6 @@ download-knapsack-report: # ========================================== # Test stage # ========================================== -# Test suite against cng is still MVP, while we gather metrics, do not report failures cng-instance: extends: .cng-base variables: @@ -139,9 +135,6 @@ cng-qa-min-redis-version: redis_version=$(awk -F "=" "/MIN_REDIS_VERSION =/ {print \$2}" $CI_PROJECT_DIR/lib/system_check/app/redis_version_check.rb | sed "s/['\" ]//g") export EXTRA_DEPLOY_VALUES="--set redis.image.tag=${redis_version%.*}" - !reference [.cng-base, before_script] - after_script: - - !reference [.set-suite-status, after_script] - - !reference [.cng-base, after_script] # ========================================== # Post test stage diff --git a/app/assets/javascripts/pages/projects/wikis/index.js b/app/assets/javascripts/pages/projects/wikis/index.js index d3f9d691737..6df2ebc3fe4 100644 --- a/app/assets/javascripts/pages/projects/wikis/index.js +++ b/app/assets/javascripts/pages/projects/wikis/index.js @@ -1,6 +1,8 @@ import Wikis from '~/pages/shared/wikis/wikis'; import { mountApplications } from '~/pages/shared/wikis/edit'; +import { mountMoreActions } from '~/pages/shared/wikis/more_actions'; mountApplications(); +mountMoreActions(); export default new Wikis(); diff --git a/app/assets/javascripts/pages/shared/wikis/components/clone_wiki_modal.vue b/app/assets/javascripts/pages/shared/wikis/components/clone_wiki_modal.vue index 5fb2ab558c0..be824f5a589 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/clone_wiki_modal.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/clone_wiki_modal.vue @@ -39,7 +39,7 @@ export default { GlModal: GlModalDirective, GlTooltip: GlTooltipDirective, }, - inject: ['wikiPath', 'cloneSshUrl', 'cloneHttpUrl', 'cloneLinkClass'], + inject: ['wikiPath', 'cloneSshUrl', 'cloneHttpUrl'], props: { showAsDropdownItem: { type: Boolean, @@ -71,7 +71,6 @@ export default { return { text: __('Clone repository'), extraAttrs: { - class: this.cloneLinkClass, 'data-testid': 'page-clone-button', }, }; diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_more_dropdown.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_more_dropdown.vue index cbdf88171df..292d11e64b1 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_more_dropdown.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_more_dropdown.vue @@ -23,7 +23,7 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, - inject: ['newUrl', 'historyUrl', 'templatesUrl', 'cloneLinkClass', 'pagePersisted'], + inject: ['newUrl', 'historyUrl', 'templatesUrl', 'pagePersisted'], i18n: { wikiActions: s__('Wiki|Wiki actions'), }, @@ -75,7 +75,7 @@ export default { return !this.isDropdownVisible ? this.$options.i18n.wikiActions : ''; }, showPrintItem() { - return !this.isTemplate; + return !this.isTemplate && this.pagePersisted; }, }, methods: { diff --git a/app/assets/javascripts/pages/shared/wikis/more_actions.js b/app/assets/javascripts/pages/shared/wikis/more_actions.js new file mode 100644 index 00000000000..5081e2bd9f2 --- /dev/null +++ b/app/assets/javascripts/pages/shared/wikis/more_actions.js @@ -0,0 +1,28 @@ +import Vue from 'vue'; +import WikiMoreDropdown from './components/wiki_more_dropdown.vue'; + +const mountWikiMoreActions = () => { + const el = document.querySelector('#js-vue-wiki-more-actions'); + + if (!el) return false; + const { pageHeading, cloneSshUrl, cloneHttpUrl, wikiUrl, newUrl, templatesUrl } = el.dataset; + + return new Vue({ + el, + provide: { + pageHeading, + cloneSshUrl, + cloneHttpUrl, + wikiUrl, + newUrl, + templatesUrl, + }, + render(createElement) { + return createElement(WikiMoreDropdown); + }, + }); +}; + +export const mountMoreActions = () => { + mountWikiMoreActions(); +}; diff --git a/app/assets/javascripts/pages/shared/wikis/show.js b/app/assets/javascripts/pages/shared/wikis/show.js index 36257a0fb5e..de77ba9bb41 100644 --- a/app/assets/javascripts/pages/shared/wikis/show.js +++ b/app/assets/javascripts/pages/shared/wikis/show.js @@ -27,7 +27,6 @@ const mountWikiContentApp = () => { newUrl, historyUrl, templatesUrl, - cloneLinkClass, wikiUrl, pagePersisted, templates, @@ -58,7 +57,6 @@ const mountWikiContentApp = () => { newUrl, historyUrl, templatesUrl, - cloneLinkClass, wikiUrl, formatOptions: JSON.parse(formatOptions), csrfToken: csrf.token, diff --git a/app/assets/javascripts/pages/shared/wikis/utils.js b/app/assets/javascripts/pages/shared/wikis/utils.js index 62c054c3c04..b4ddf666682 100644 --- a/app/assets/javascripts/pages/shared/wikis/utils.js +++ b/app/assets/javascripts/pages/shared/wikis/utils.js @@ -1,3 +1,3 @@ export function isTemplate() { - return window.location.href.includes('/wikis/templates/'); + return window.location.href.includes('/wikis/templates'); } diff --git a/app/assets/javascripts/pages/shared/wikis/wikis.js b/app/assets/javascripts/pages/shared/wikis/wikis.js index 7fb39397307..92fd72b99b0 100644 --- a/app/assets/javascripts/pages/shared/wikis/wikis.js +++ b/app/assets/javascripts/pages/shared/wikis/wikis.js @@ -16,8 +16,26 @@ export default class Wikis { sidebarToggles[i].addEventListener('click', (e) => this.handleToggleSidebar(e)); } - const listToggles = document.querySelectorAll('.js-wiki-list-toggle'); + // Store pages visbility in localStorage + const pagesToggle = document.querySelector('.js-wiki-expand-pages-list'); + if (pagesToggle) { + if (localStorage.getItem('wiki-sidebar-expanded') === 'expanded') { + pagesToggle.classList.remove('collapsed'); + } + pagesToggle.addEventListener('click', (e) => { + pagesToggle.classList.toggle('collapsed'); + if (!pagesToggle.classList.contains('collapsed')) { + localStorage.setItem('wiki-sidebar-expanded', 'expanded'); + } else { + localStorage.removeItem('wiki-sidebar-expanded'); + } + + e.stopImmediatePropagation(); + }); + } + + const listToggles = document.querySelectorAll('.js-wiki-list-toggle'); listToggles.forEach((listToggle) => { listToggle.querySelectorAll('a').forEach((link) => { link.addEventListener('click', (e) => e.stopPropagation()); diff --git a/app/assets/javascripts/super_sidebar/components/global_search/components/global_search_autocomplete_items.vue b/app/assets/javascripts/super_sidebar/components/global_search/components/global_search_autocomplete_items.vue index 754d7372071..16a4817e2e0 100644 --- a/app/assets/javascripts/super_sidebar/components/global_search/components/global_search_autocomplete_items.vue +++ b/app/assets/javascripts/super_sidebar/components/global_search/components/global_search_autocomplete_items.vue @@ -2,6 +2,7 @@ import { GlAvatar, GlAlert, GlLoadingIcon, GlDisclosureDropdownGroup } from '@gitlab/ui'; // eslint-disable-next-line no-restricted-imports import { mapState, mapGetters } from 'vuex'; +import { s__ } from '~/locale'; import { InternalEvents } from '~/tracking'; import SafeHtml from '~/vue_shared/directives/safe_html'; import highlight from '~/lib/utils/highlight'; @@ -10,6 +11,16 @@ import { AUTOCOMPLETE_ERROR_MESSAGE, NO_SEARCH_RESULTS, } from '~/vue_shared/global_search/constants'; +import { + EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE, +} from '~/super_sidebar/components/global_search/tracking_constants'; import { OVERLAY_GOTO, OVERLAY_PROFILE, @@ -40,6 +51,10 @@ export default { ISSUES_GROUP_TITLE, PAGES_GROUP_TITLE, GROUPS_GROUP_TITLE, + MERGE_REQUESTS_GROUP_TITLE: s__('GlobalSearch|Merge Requests'), + RECENT_ISSUES_GROUP_TITLE: s__('GlobalSearch|Recent issues'), + RECENT_EPICS_GROUP_TITLE: s__('GlobalSearch|Recent epics'), + RECENT_MERGE_REQUESTS_GROUP_TITLE: s__('GlobalSearch|Recent merge requests'), }, components: { GlAvatar, @@ -103,20 +118,39 @@ export default { } return text; }, - trackingTypes({ category }) { - switch (category) { - case this.$options.i18n.GROUPS_GROUP_TITLE: { - this.trackEvent('click_group_result_in_command_palette'); + trackingTypes({ name }) { + switch (name) { + case this.$options.i18n.PROJECTS_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE); break; } - - case this.$options.i18n.PROJECTS_GROUP_TITLE: { - this.trackEvent('click_project_result_in_command_palette'); + case this.$options.i18n.GROUPS_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE); + break; + } + case this.$options.i18n.MERGE_REQUESTS_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE); + break; + } + case this.$options.i18n.ISSUES_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE); + break; + } + case this.$options.i18n.RECENT_ISSUES_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE); + break; + } + case this.$options.i18n.RECENT_EPICS_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE); + break; + } + case this.$options.i18n.RECENT_MERGE_REQUESTS_GROUP_TITLE: { + this.trackEvent(EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE); break; } default: { - /* empty */ + this.trackEvent(EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE); } } }, diff --git a/app/assets/javascripts/super_sidebar/components/global_search/tracking_constants.js b/app/assets/javascripts/super_sidebar/components/global_search/tracking_constants.js index 28cef61e59e..54024c92377 100644 --- a/app/assets/javascripts/super_sidebar/components/global_search/tracking_constants.js +++ b/app/assets/javascripts/super_sidebar/components/global_search/tracking_constants.js @@ -19,3 +19,16 @@ export const EVENT_CLICK_GROUP_SCOPED_SEARCH_TO_ADVANCED_SEARCH = 'click_group_scoped_search_to_advanced_search'; export const EVENT_CLICK_PROJECT_SCOPED_SEARCH_TO_ADVANCED_SEARCH = 'click_project_scoped_search_to_advanced_search'; +export const EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE = + 'click_project_result_in_command_palette'; +export const EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE = 'click_group_result_in_command_palette'; +export const EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE = + 'click_merge_request_result_in_command_palette'; +export const EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE = 'click_issue_result_in_command_palette'; +export const EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE = + 'click_recent_issue_result_in_command_palette'; +export const EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE = + 'click_recent_epic_result_in_command_palette'; +export const EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE = + 'click_recent_merge_request_result_in_command_palette'; +export const EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE = 'click_user_result_in_command_palette'; diff --git a/app/assets/javascripts/vue_shared/components/logs_viewer/log_line.vue b/app/assets/javascripts/vue_shared/components/logs_viewer/log_line.vue index f9c2698fff2..4c041996820 100644 --- a/app/assets/javascripts/vue_shared/components/logs_viewer/log_line.vue +++ b/app/assets/javascripts/vue_shared/components/logs_viewer/log_line.vue @@ -22,7 +22,7 @@ export default { return h( 'span', { - class: ['gl-white-space-pre-wrap', content.style], + class: ['gl-whitespace-pre-wrap', content.style], }, // Simple "tokenization": Split text in chunks of text // which alternate between text and urls. @@ -36,7 +36,7 @@ export default { { attrs: { href: chunk, - class: 'gl-reset-color! gl-text-decoration-underline', + class: '!gl-text-inherit gl-underline', rel: 'nofollow noopener noreferrer', // eslint-disable-line @gitlab/require-i18n-strings target: '_blank', }, diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_projects_listbox.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_projects_listbox.vue index de699a795f8..f35a58b528a 100644 --- a/app/assets/javascripts/work_items/components/work_item_links/work_item_projects_listbox.vue +++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_projects_listbox.vue @@ -57,6 +57,11 @@ export default { update(data) { return this.isGroup ? data.group?.projects?.nodes : data.project?.group?.projects?.nodes; }, + result() { + if (this.selectedProject === null) { + this.selectedProjectFullPath = this.fullPath; + } + }, debounce: SEARCH_DEBOUNCE, }, }, @@ -156,7 +161,11 @@ export default { /* Filter for the current group */ storedFrequentProjects = storedFrequentProjects.filter((item) => { - return Boolean(item.webUrl?.slice(1)?.startsWith(this.fullPath)); + const groupPath = this.isGroup + ? this.fullPath + : this.fullPath.substring(0, this.fullPath.lastIndexOf('/')); + + return Boolean(item.webUrl?.slice(1)?.startsWith(groupPath)); }); if (searchTerm) { diff --git a/app/views/shared/wikis/_sidebar.html.haml b/app/views/shared/wikis/_sidebar.html.haml index d7be096ae25..3a7947362f0 100644 --- a/app/views/shared/wikis/_sidebar.html.haml +++ b/app/views/shared/wikis/_sidebar.html.haml @@ -12,7 +12,7 @@ = render 'shared/alert_info', body: s_('Wiki|The sidebar failed to load. You can reload the page to try again.') .blocks-container{ class: '!gl-px-3' } - .gl-flex.gl-place-content-between.gl-items-center.gl-pb-3.gl-pr-1{ class: (@sidebar_page ? 'js-wiki-list-toggle wiki-list collapsed gl-pl-0' : 'gl-pl-3') } + .gl-flex.gl-place-content-between.gl-items-center.gl-pb-3.gl-pr-1{ class: (@sidebar_page ? 'js-wiki-expand-pages-list wiki-list collapsed gl-pl-0' : 'gl-pl-3') } .gl-flex.gl-items-center - if @sidebar_page = render Pajamas::ButtonComponent.new(category: :tertiary, size: :small, icon: 'chevron-right', button_options: { class: "js-wiki-list-expand-button wiki-list-expand-button !gl-static gl-mr-2", data: { testid: 'expand-pages-list' } }) diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml index 55eb1faa51e..4717e26644f 100644 --- a/app/views/shared/wikis/diff.html.haml +++ b/app/views/shared/wikis/diff.html.haml @@ -4,19 +4,27 @@ - commit = @diffs.diffable - add_page_specific_style 'page_bundles/commit_description' -.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row +.wiki-page-header.has-sidebar-toggle.gl-flex.gl-items-center{ class: '!gl-mt-5' } = wiki_sidebar_toggle_button - %h1.page-title.gl-font-size-h-display.gl-flex-grow-1 + %h1.gl-heading-1.gl-grow{ class: '!gl-mb-0' } = link_to_wiki_page @page %span.light · = _('Changes') - .nav-controls.pb-md-3.pb-lg-0 + .nav-controls.gl-flex.gl-gap-3 = link_button_to wiki_page_path(@wiki, @page, action: :history), role: 'button', data: { testid: 'page-history-button' } do = @page.template? ? s_('Wiki|Template history') : s_('Wiki|Page history') + #js-vue-wiki-more-actions{ data: { + clone_ssh_url: ssh_clone_url_to_repo(@wiki), + clone_http_url: http_clone_url_to_repo(@wiki), + wiki_url: wiki_path(@wiki), + new_url: wiki_path(@wiki, action: :new), + templates_url: wiki_page_path(@wiki, Wiki::TEMPLATES_DIR), + } } + .page-content-header .header-main-content %strong= markdown_field(commit, :title) diff --git a/app/views/shared/wikis/history.html.haml b/app/views/shared/wikis/history.html.haml index 05608416047..94035b9c4fa 100644 --- a/app/views/shared/wikis/history.html.haml +++ b/app/views/shared/wikis/history.html.haml @@ -2,17 +2,25 @@ - wiki_page_title @page, _('History') - add_page_specific_style 'page_bundles/wiki' -.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row.gl-border-b-0 +.wiki-page-header.has-sidebar-toggle.gl-flex.gl-items-center{ class: '!gl-mt-5' } = wiki_sidebar_toggle_button - %h1.page-title.gl-font-size-h-display + %h1.gl-heading-1.gl-grow{ class: '!gl-mb-0' } = link_to_wiki_page @page - %span.light + %span.gl-text-secondary · = _('History') + #js-vue-wiki-more-actions{ data: { + clone_ssh_url: ssh_clone_url_to_repo(@wiki), + clone_http_url: http_clone_url_to_repo(@wiki), + wiki_url: wiki_path(@wiki), + new_url: wiki_path(@wiki, action: :new), + templates_url: wiki_page_path(@wiki, Wiki::TEMPLATES_DIR), + } } + .prepend-top-default.gl-mb-3 - = render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-mt-0 gl-mb-5' }, header_options: { class: 'gl-new-card-header gl-border-b-0' }, body_options: { class: 'gl-new-card-body gl-px-0' }) do |c| + = render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-mb-5' }, header_options: { class: 'gl-new-card-header gl-border-b-0' }, body_options: { class: 'gl-new-card-body gl-px-0' }) do |c| - c.with_header do .gl-new-card-title-wrapper.gl-flex-col %h3.gl-new-card-title diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml index 1b262a9a917..229eeb2e405 100644 --- a/app/views/shared/wikis/pages.html.haml +++ b/app/views/shared/wikis/pages.html.haml @@ -3,22 +3,27 @@ - page_title s_("Wiki|Pages"), _("Wiki") - add_page_specific_style 'page_bundles/wiki' -.wiki-page-header.top-area.flex-column.flex-lg-row - %h1.page-title.gl-font-size-h-display.gl-flex-grow-1 +.wiki-page-header.gl-flex.gl-items-center{ class: '!gl-mt-5' } + %h1.gl-heading-1.gl-grow{ class: '!gl-mb-0' } = s_("Wiki|Wiki Pages") - .nav-controls.pb-md-3.pb-lg-0 + .nav-controls.gl-flex.gl-gap-3 .dropdown.inline.wiki-sort-dropdown .btn-group{ role: 'group' } = wiki_sort_controls(@wiki, params[:direction]) - = render Pajamas::ButtonComponent.new(href: wiki_path(@wiki, action: :git_access), icon: 'download') do - = _("Clone repository") - - if can?(current_user, :create_wiki, @project) = render Pajamas::ButtonComponent.new(href: wiki_page_path(@wiki, SecureRandom.uuid, random_title: true), variant: :confirm) do = s_("Wiki|New page") + #js-vue-wiki-more-actions{ data: { + clone_ssh_url: ssh_clone_url_to_repo(@wiki), + clone_http_url: http_clone_url_to_repo(@wiki), + wiki_url: wiki_path(@wiki), + new_url: '', + templates_url: wiki_page_path(@wiki, Wiki::TEMPLATES_DIR), + } } + %ul.wiki-pages-list.content-list - @wiki_entries.each do |entry| = render partial: entry.to_partial_path, object: entry, locals: { context: 'pages' } diff --git a/app/views/shared/wikis/show.html.haml b/app/views/shared/wikis/show.html.haml index 6b9c9df169d..483e5a30f5f 100644 --- a/app/views/shared/wikis/show.html.haml +++ b/app/views/shared/wikis/show.html.haml @@ -21,7 +21,6 @@ wiki_path: @wiki.path, clone_ssh_url: ssh_clone_url_to_repo(@wiki), clone_http_url: http_clone_url_to_repo(@wiki), - clone_link_class: active_nav_link?(path: 'wikis#git_access') ? ' active' : '', page_persisted: (@page.persisted? && can?(current_user, :create_wiki, @wiki.container)).to_s, wiki_url: wiki_page_path(@wiki, @page), edit_button_url: wiki_page_path(@wiki, @page, action: :edit), diff --git a/app/views/shared/wikis/templates.html.haml b/app/views/shared/wikis/templates.html.haml index f70b5b7e681..be535522fab 100644 --- a/app/views/shared/wikis/templates.html.haml +++ b/app/views/shared/wikis/templates.html.haml @@ -7,11 +7,19 @@ %h1.gl-heading-1.gl-grow{ class: '!gl-mb-0' } = s_("Wiki|Wiki templates") - .nav-controls.pb-md-3.pb-lg-0 + .nav-controls.gl-flex.gl-gap-3 .dropdown.inline.wiki-sort-dropdown .btn-group{ role: 'group' } = wiki_sort_controls(@wiki, params[:direction], action: :templates) + #js-vue-wiki-more-actions{ data: { + clone_ssh_url: ssh_clone_url_to_repo(@wiki), + clone_http_url: http_clone_url_to_repo(@wiki), + wiki_url: wiki_path(@wiki), + new_url: wiki_page_path(@wiki, "#{Wiki::TEMPLATES_DIR}/#{SecureRandom.uuid}", random_title: true), + templates_url: wiki_page_path(@wiki, Wiki::TEMPLATES_DIR), + } } + = render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card' }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-0' }) do |c| - c.with_header do .gl-new-card-title-wrapper.gl-flex-col diff --git a/config/events/click_issue_result_in_command_palette.yml b/config/events/click_issue_result_in_command_palette.yml new file mode 100644 index 00000000000..6c6d2fb53e9 --- /dev/null +++ b/config/events/click_issue_result_in_command_palette.yml @@ -0,0 +1,17 @@ +--- +description: User clicks an issue result in the command palette +internal_events: true +action: click_issue_result_in_command_palette +identifiers: +- namespace +- user +product_group: global_search +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/click_merge_request_result_in_command_palette.yml b/config/events/click_merge_request_result_in_command_palette.yml new file mode 100644 index 00000000000..c054e49f080 --- /dev/null +++ b/config/events/click_merge_request_result_in_command_palette.yml @@ -0,0 +1,17 @@ +--- +description: User clicks a merge request result in the command palette +internal_events: true +action: click_merge_request_result_in_command_palette +identifiers: +- namespace +- user +product_group: global_search +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/click_recent_epic_result_in_command_palette.yml b/config/events/click_recent_epic_result_in_command_palette.yml new file mode 100644 index 00000000000..d5e633c67b6 --- /dev/null +++ b/config/events/click_recent_epic_result_in_command_palette.yml @@ -0,0 +1,17 @@ +--- +description: User clicks an epic result in recent epics section +internal_events: true +action: click_recent_epic_result_in_command_palette +identifiers: +- namespace +- user +product_group: global_search +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/click_recent_issue_result_in_command_palette.yml b/config/events/click_recent_issue_result_in_command_palette.yml new file mode 100644 index 00000000000..3be92714ead --- /dev/null +++ b/config/events/click_recent_issue_result_in_command_palette.yml @@ -0,0 +1,17 @@ +--- +description: User clicks an issue result in the recent issues section +internal_events: true +action: click_recent_issue_result_in_command_palette +identifiers: +- namespace +- user +product_group: global_search +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/events/click_recent_merge_request_result_in_command_palette.yml b/config/events/click_recent_merge_request_result_in_command_palette.yml new file mode 100644 index 00000000000..8648c33e9a9 --- /dev/null +++ b/config/events/click_recent_merge_request_result_in_command_palette.yml @@ -0,0 +1,17 @@ +--- +description: User clicks a merge request result in the recent merge reqeusts section +internal_events: true +action: click_recent_merge_request_result_in_command_palette +identifiers: +- namespace +- user +product_group: global_search +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_click_issue_result_in_command_palette_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_click_issue_result_in_command_palette_monthly.yml new file mode 100644 index 00000000000..eb6a9257ad2 --- /dev/null +++ b/config/metrics/counts_28d/count_distinct_user_id_from_click_issue_result_in_command_palette_monthly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_issue_result_in_command_palette_monthly +description: Monthly count of unique users User clicks an issue result in the command palette +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_issue_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_monthly.yml new file mode 100644 index 00000000000..e4e2e566ae2 --- /dev/null +++ b/config/metrics/counts_28d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_monthly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_merge_request_result_in_command_palette_monthly +description: Monthly count of unique users User clicks a merge request result in the command palette +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_merge_request_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_monthly.yml new file mode 100644 index 00000000000..7940c1861a9 --- /dev/null +++ b/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_monthly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_recent_epic_result_in_command_palette_monthly +description: Monthly count of unique users User clicks an epic result in recent epics section +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_recent_epic_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_monthly.yml new file mode 100644 index 00000000000..6b139ce6a4d --- /dev/null +++ b/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_monthly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_recent_issue_result_in_command_palette_monthly +description: Monthly count of unique users User clicks an issue result in the recent issues section +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_recent_issue_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_monthly.yml new file mode 100644 index 00000000000..698526e662e --- /dev/null +++ b/config/metrics/counts_28d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_monthly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_monthly +description: Monthly count of unique users User clicks a merge request result in the recent merge reqeusts section +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 28d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_recent_merge_request_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_click_issue_result_in_command_palette_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_click_issue_result_in_command_palette_weekly.yml new file mode 100644 index 00000000000..4091a39a4cb --- /dev/null +++ b/config/metrics/counts_7d/count_distinct_user_id_from_click_issue_result_in_command_palette_weekly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_issue_result_in_command_palette_weekly +description: Weekly count of unique users who click an issue result in the command palette +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_issue_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_weekly.yml new file mode 100644 index 00000000000..1c288438b71 --- /dev/null +++ b/config/metrics/counts_7d/count_distinct_user_id_from_click_merge_request_result_in_command_palette_weekly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_merge_request_result_in_command_palette_weekly +description: Weekly count of unique users who click a merge request result in the command palette +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_merge_request_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_weekly.yml new file mode 100644 index 00000000000..5350fe713d1 --- /dev/null +++ b/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_epic_result_in_command_palette_weekly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_recent_epic_result_in_command_palette_weekly +description: Weekly count of unique users who click an epic result in recent epics section +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_recent_epic_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_weekly.yml new file mode 100644 index 00000000000..7495e01b62c --- /dev/null +++ b/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_issue_result_in_command_palette_weekly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_recent_issue_result_in_command_palette_weekly +description: Weekly count of unique users who click an issue result in the recent issues section +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_recent_issue_result_in_command_palette + unique: user.id diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_weekly.yml new file mode 100644 index 00000000000..4a81ef54309 --- /dev/null +++ b/config/metrics/counts_7d/count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_weekly.yml @@ -0,0 +1,22 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_recent_merge_request_result_in_command_palette_weekly +description: Weekly count of unique users who click a merge request result in the recent merge reqeusts section +product_group: global_search +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.1' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154576 +time_frame: 7d +data_source: internal_events +data_category: optional +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +events: +- name: click_recent_merge_request_result_in_command_palette + unique: user.id diff --git a/danger/tailwindcss/Dangerfile b/danger/tailwindcss/Dangerfile index 10ebb63118b..bd78a3423b1 100644 --- a/danger/tailwindcss/Dangerfile +++ b/danger/tailwindcss/Dangerfile @@ -39,6 +39,8 @@ module Danger end files_with_legacy_utils = @helper.all_changed_files.flat_map do |file| + next [] if file.end_with?('tailwind_equivalents.json') + diff = @git.diff_for_file(file) # When a file is just moved around it appears in the changed files list @@ -75,8 +77,7 @@ module Danger We are in the process of migrating our CSS utility classes to [Tailwind CSS](https://tailwindcss.com/). The above CSS utility classes do not comply with Tailwind CSS naming conventions. Please use the Tailwind CSS equivalent if it is available. - For more information on how to determine what CSS utility classes to use see - our [Tailwind CSS developer documentation](https://docs.gitlab.com/ee/development/fe_guide/style/scss.html#tailwind-css). + For more information see [Tailwind CSS developer documentation](https://docs.gitlab.com/ee/development/fe_guide/style/scss.html#tailwind-css). If the Tailwind CSS equivalent is not available, it is okay to use the legacy CSS utility class for now. The Tailwind CSS equivalent will be made available when the corresponding migration issue @@ -123,8 +124,21 @@ module Danger end def format_files_with_legacy_utils_list(files) + # rubocop:disable Gitlab/Json -- we are outside of the GitLab Rails context + # and therefore do not have access to the dependencies required for + # Gitlab::Json.parse to work. + tailwind_equivalents = JSON.parse( + File.read("./scripts/frontend/tailwind_equivalents.json") + ) + # rubocop:enable Gitlab/Json + files.map do |file, legacy_utils| - "- `#{file}`\n" + legacy_utils.map { |legacy_util| " - `#{legacy_util}`" }.join("\n") + legacy_utils_bullet_points = legacy_utils.map do |legacy_util| + tailwind_equivalent = tailwind_equivalents[legacy_util] || "Not available" + " - `#{legacy_util}` - Tailwind CSS equivalent: `#{tailwind_equivalent}`" + end.join("\n") + + "- `#{file}`\n" + legacy_utils_bullet_points end.join("\n") end end diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md index 6f7e01fbcd2..dcdbf63a669 100644 --- a/doc/administration/auth/oidc.md +++ b/doc/administration/auth/oidc.md @@ -287,7 +287,7 @@ To migrate to the Generic OpenID Connect configuration, you must change the conf ::Tabs -:::Azure OAuth 2.0 +:::TabTitle Azure OAuth 2.0 ```ruby gitlab_rails['omniauth_providers'] = [ @@ -314,7 +314,7 @@ gitlab_rails['omniauth_providers'] = [ ] ``` -:::Azure Active Directory v2 +:::TabTitle Azure Active Directory v2 ```ruby gitlab_rails['omniauth_providers'] = [ diff --git a/doc/api/projects.md b/doc/api/projects.md index 162662fbc78..9862c67d45a 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -12,6 +12,9 @@ DETAILS: Interact with [projects](../user/project/index.md) by using the REST API. +NOTE: +Users with any [default role](../user/permissions.md#roles) can read project properties with the Projects API. Only users with the Owner or Maintainer role can edit project properties in the UI or with the API. + ## Project visibility level A project in GitLab can be private, internal, or public. diff --git a/doc/development/ai_features/index.md b/doc/development/ai_features/index.md index 274eab42ed2..c0f404a568f 100644 --- a/doc/development/ai_features/index.md +++ b/doc/development/ai_features/index.md @@ -10,7 +10,7 @@ info: Any user with at least the Maintainer role can merge updates to this conte ### Access -Access to both Google Cloud Vertex and Anthropic are recommended for setup. +Access to both Google Cloud Vertex and Anthropic are recommended for setup. #### Google Cloud Vertex @@ -21,7 +21,7 @@ To obtain a Google Cloud service key for local development, follow the steps bel existing group Google Cloud project (`ai-enablement-dev-69497ba7`) by using [this template](https://gitlab.com/gitlab-com/it/infra/issue-tracker/-/issues/new?issuable_template=gcp_group_account_iam_update_request) This project has Vertex APIs and Vertex AI Search (for Duo Chat - documentaton questions) already enabled + documentation questions) already enabled. 1. Option 2: Create a sandbox Google Cloud project by following the instructions in [the handbook](https://handbook.gitlab.com/handbook/infrastructure-standards/#individual-environment). If you are using an individual Google Cloud project, you may also need to @@ -34,11 +34,11 @@ To obtain a Google Cloud service key for local development, follow the steps bel 1. Select **Vertex AI API**, then select **Enable**. 1. Install the [`gcloud` CLI](https://cloud.google.com/sdk/docs/install) 1. If you already use [`asdf`](https://asdf-vm.com/) for runtime version - management, you can install `gcloud` with the - [`asdf gcloud` plugin](https://github.com/jthegedus/asdf-gcloud) + management, you can install `gcloud` with the + [`asdf gcloud` plugin](https://github.com/jthegedus/asdf-gcloud) 1. Authenticate locally with Google Cloud using the - [`gcloud auth application-default login`](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login) - command. + [`gcloud auth application-default login`](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login) + command. 1. Open a Rails console. Update the settings to: ```ruby @@ -175,7 +175,7 @@ Gitlab::Llm::VertexAi::Client.new(User.first, unit_primitive: 'explain_vulnerabi Here is the underlying process happening per request: 1. GitLab-Rails generates a new JWT with a given scope (e.g. `duo_chat`). -1. GitLab-Rails requets to AI Gateway with the JWT (bearer token in `Authorization` HTTP header). +1. GitLab-Rails sends a request to AI Gateway with the JWT (bearer token in `Authorization` HTTP header). 1. AI Gateway decodes the JWT with the JWKS issued by the GitLab-Rails. If it's successful, the request is authenticated. 1. AI Gateway verifies if the `scopes` claim in the JWT satisfies the target endpoint's scope requirement. Required scope varies per endpoint (e.g. `/v1/chat/agent` requires `duo_chat`, `/v2/code/suggestions` requires `code_suggestions`). @@ -214,9 +214,9 @@ Otherwise, it can be skipped as long as your GDK has doesn't work, try `gdk kill` and then `gdk start`. 1. Alternatively, bypass Sidekiq entirely and run the service synchronously. This can help with debugging errors as GraphQL errors are now available in - the network inspector instead of the Sidekiq logs. To do that temporary alter - `perform_for` method in `Llm::CompletionWorker` class by changing - `perform_async` to `perform_inline`. + the network inspector instead of the Sidekiq logs. To do that, temporarily alter + the `perform_for` method in `Llm::CompletionWorker` class by changing + `perform_async` to `perform_inline`. ## Feature development (Abstraction Layer) @@ -241,7 +241,7 @@ Example of a mutation: ```graphql mutation { - aiAction(input: {summarizeComments: {resourceId: "gid://gitlab/Issue/52"}}) { + aiAction(input: { summarizeComments: { resourceId: "gid://gitlab/Issue/52" } }) { clientMutationId } } @@ -252,7 +252,11 @@ As an example, assume we want to build an "explain code" action. To do this, we ```graphql mutation { - aiAction(input: {explainCode: {resourceId: "gid://gitlab/MergeRequest/52", code: "foo() { console.log() }" }}) { + aiAction( + input: { + explainCode: { resourceId: "gid://gitlab/MergeRequest/52", code: "foo() { console.log() }" } + } + ) { clientMutationId } } @@ -278,7 +282,12 @@ As an example mutation for summarizing comments, we provide a `randomId` as part ```graphql mutation { - aiAction(input: {summarizeComments: {resourceId: "gid://gitlab/Issue/52"}, clientSubscriptionId: "randomId"}) { + aiAction( + input: { + summarizeComments: { resourceId: "gid://gitlab/Issue/52" } + clientSubscriptionId: "randomId" + } + ) { clientMutationId } } @@ -287,8 +296,16 @@ mutation { In our component, we then listen on the `aiCompletionResponse` using the `userId`, `resourceId` and `clientSubscriptionId` (`"randomId"`): ```graphql -subscription aiCompletionResponse($userId: UserID, $resourceId: AiModelID, $clientSubscriptionId: String) { - aiCompletionResponse(userId: $userId, resourceId: $resourceId, clientSubscriptionId: $clientSubscriptionId) { +subscription aiCompletionResponse( + $userId: UserID + $resourceId: AiModelID + $clientSubscriptionId: String +) { + aiCompletionResponse( + userId: $userId + resourceId: $resourceId + clientSubscriptionId: $clientSubscriptionId + ) { content errors } @@ -359,12 +376,12 @@ end We recommend to use [policies](../policies.md) to deal with authorization for a feature. Currently we need to make sure to cover the following checks: -1. For GitLab Duo Chat feature, `ai_duo_chat_switch` is enabled -1. For other general AI features, `ai_global_switch` is enabled -1. Feature specific feature flag is enabled -1. The namespace has the required license for the feature -1. User is a member of the group/project -1. `experiment_features_enabled` settings are set on the `Namespace` +1. For GitLab Duo Chat feature, `ai_duo_chat_switch` is enabled. +1. For other general AI features, `ai_global_switch` is enabled. +1. Feature specific feature flag is enabled. +1. The namespace has the required license for the feature. +1. User is a member of the group/project. +1. `experiment_features_enabled` settings are set on the `Namespace`. For our example, we need to implement the `allowed?(:amazing_new_ai_feature)` call. As an example, you can look at the [Issue Policy for the summarize comments feature](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/policies/ee/issue_policy.rb). In our example case, we want to implement the feature for Issues as well: @@ -424,8 +441,8 @@ query { ``` This cache is especially useful for chat functionality. For other services, -caching is disabled. (It can be enabled for a service by using `cache_response: true` -option.) +caching is disabled. You can enable this for a service by using the `cache_response: true` +option. Caching has following limitations: diff --git a/doc/development/code_suggestions/index.md b/doc/development/code_suggestions/index.md index 23f6a9d7d8f..b16001546a0 100644 --- a/doc/development/code_suggestions/index.md +++ b/doc/development/code_suggestions/index.md @@ -83,23 +83,30 @@ with the deployed staging AI Gateway. To do this: ### Setup instructions to use GDK with the Code Suggestions Add-on -On February 15, 2023 we will require the code suggestions add-on subscription to be able to use code suggestions. -To set up your GDK for local development using the add-on, please follow these steps: +1. Add a **GitLab Ultimate Self-Managed** subscription with a [Duo Pro subscription add-on](../../subscriptions/subscription-add-ons.md) to your GDK instance. + + [Self-purchase your own subscription](https://gitlab.com/gitlab-org/customers-gitlab-com/-/blob/30a6670d39da223565081cbe46ba17d8e610aad1/doc/flows/buy_subscription.md#buy-subscription) for GitLab Ultimate Self-Managed from the [staging Customers Portal](https://customers.staging.gitlab.com). + To do this, send a message to the `#s_fulfillment` or `s_fulfillment_engineering` Slack channels. The team will: + + - Give you instructions or set your account so you do not have to pay for a subscription. + - Add the Duo Pro add-on to your account. + + After this step is complete, you will have an activation code for a _GitLab Ultimate Self-Managed subscription with a Duo Pro add-on_. -1. Drop a note in the `#s_fulfillment` or `s_fulfillment_engineering` internal Slack channel to request an activation code with the Code Suggestions add-on. -1. Someone will reach out to you with a code. 1. Follow the [activation instructions](https://gitlab.com/gitlab-org/customers-gitlab-com/-/blob/main/doc/license/cloud_license.md?ref_type=heads#testing-activation): + 1. Set environment variables. - ```shell - export GITLAB_LICENSE_MODE=test - export CUSTOMER_PORTAL_URL=https://customers.staging.gitlab.com - export GITLAB_SIMULATE_SAAS=0 - ``` + ```shell + export GITLAB_LICENSE_MODE=test + export CUSTOMER_PORTAL_URL=https://customers.staging.gitlab.com + export GITLAB_SIMULATE_SAAS=0 + ``` 1. Restart your GDK. 1. Go to `/admin/subscription`. - 1. Remove any active license. + 1. Optional. Remove any active license. 1. Add the new activation code. + 1. Inside your GDK, navigate to Admin Area > GitLab Duo Pro, go to `/admin/code_suggestions` 1. Filter users to find `root` and click the toggle to assign a GitLab Duo Pro add-on seat to the root user diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md index a3caa5e65cd..fac4b48d7f9 100644 --- a/doc/development/testing_guide/flaky_tests.md +++ b/doc/development/testing_guide/flaky_tests.md @@ -178,9 +178,13 @@ When we have a flaky test in `master`: #### Fast quarantine +Unless you really need to have a test disabled very fast (`< 10min`), consider [using the `~pipeline::expedited` label instead](../pipelines/index.md#the-pipelineexpedited-label). + To quickly quarantine a test without having to open a merge request and wait for pipelines, you can follow [the fast quarantining process](https://gitlab.com/gitlab-org/quality/engineering-productivity/fast-quarantine/-/tree/main/#fast-quarantine-a-test). +**Please always proceed** to [open a long-term quarantine merge request](#long-term-quarantine) after fast-quarantining a test! This is to ensure the fast-quarantined test was correctly fixed by running tests from the CI/CD pipelines (which are not run in the context of the fast-quarantine project). + #### Long-term quarantine Once a test is fast-quarantined, you can proceed with the long-term quarantining process. This can be done by opening a merge request. diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md index d518747c968..4e1d6696488 100644 --- a/doc/user/group/value_stream_analytics/index.md +++ b/doc/user/group/value_stream_analytics/index.md @@ -489,6 +489,13 @@ time from a staging environment to production, you could use the following label ![Label-based value stream analytics stage](img/vsa_label_based_stage_v14_0.png "Creating a label-based value stream analytics stage") +##### Automatic data labeling with webhooks + +You can automatically add labels by using [GitLab webhook events](../../project/integrations/webhook_events.md), +so that a label is applied to merge requests or issues when a specific event occurs. +Then, you can add label-based stages to track your workflow. +To learn more about the implementation, see the blog post [Applying GitLab Labels Automatically](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/). + #### Example for custom value stream configuration ![Example configuration](img/object_hierarchy_example_V14_10.png "Example custom value stream configuration") diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b03262a0350..968d7a6558d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -24074,6 +24074,9 @@ msgstr "" msgid "GlobalSearch|List of filtered labels." msgstr "" +msgid "GlobalSearch|Merge Requests" +msgstr "" + msgid "GlobalSearch|Merge requests I've created" msgstr "" diff --git a/scripts/frontend/tailwind_equivalents.json b/scripts/frontend/tailwind_equivalents.json new file mode 100644 index 00000000000..05ecf6584fa --- /dev/null +++ b/scripts/frontend/tailwind_equivalents.json @@ -0,0 +1,546 @@ +{ + "gl-sr-only-focusable": null, + "gl-spin": null, + "gl-animate-skeleton-loader": null, + "gl-hover-bg-transparent": "hover:gl-bg-transparent", + "gl-bg-transparent!": "!gl-bg-transparent", + "gl-hover-bg-transparent!": "hover:!gl-bg-transparent", + "gl-bg-white!": "!gl-bg-white", + "gl-bg-gray-10!": "!gl-bg-gray-10", + "gl-focus-bg-gray-50": "focus:gl-bg-gray-50", + "gl-hover-bg-gray-50": "hover:gl-bg-gray-50", + "gl-bg-gray-50!": "!gl-bg-gray-50", + "gl-bg-gray-100!": "!gl-bg-gray-100", + "gl-bg-gray-900!": "!gl-bg-gray-900", + "gl-hover-bg-blue-50": "hover:gl-bg-blue-50", + "gl-bg-blue-50!": "!gl-bg-blue-50", + "gl-hover-bg-blue-50!": "hover:!gl-bg-blue-50", + "gl-bg-blue-100!": "!gl-bg-blue-100", + "gl-bg-red-200!": "!gl-bg-red-200", + "gl-bg-t-gray-a-08": null, + "gl-hover-bg-t-gray-a-08": null, + "gl-bg-none": null, + "gl-bg-size-cover": "gl-bg-cover", + "gl-border!": null, + "gl-border-l!": null, + "gl-border-none!": "!gl-border-none", + "gl-border-t-none": null, + "gl-border-t-none!": null, + "gl-border-solid!": "!gl-border-solid", + "gl-border-t-solid": null, + "gl-border-r-solid": null, + "gl-border-b-solid": null, + "gl-hover-border-b-solid": null, + "gl-border-b-solid!": null, + "gl-border-b-initial": null, + "gl-border-l-solid": null, + "gl-border-t-transparent!": "!gl-border-t-transparent", + "gl-hover-border-gray-100": "hover:gl-border-gray-100", + "gl-border-gray-100!": "!gl-border-gray-100", + "gl-hover-border-gray-200": "hover:gl-border-gray-200", + "gl-border-gray-200!": "!gl-border-gray-200", + "gl-hover-border-gray-200!": "hover:!gl-border-gray-200", + "gl-border-gray-500!": "!gl-border-gray-500", + "gl-border-red-500!": "!gl-border-red-500", + "gl-hover-border-blue-200": "hover:gl-border-blue-200", + "gl-border-blue-600!": "!gl-border-blue-600", + "gl-border-gray-a-08": null, + "gl-border-gray-a-24": null, + "gl-border-t-gray-200!": "!gl-border-t-gray-200", + "gl-border-r-gray-200!": "!gl-border-r-gray-200", + "gl-border-b-gray-100!": "!gl-border-b-gray-100", + "gl-border-0!": "!gl-border-0", + "gl-border-t-0!": "!gl-border-t-0", + "gl-border-b-0!": "!gl-border-b-0", + "gl-border-l-0!": "!gl-border-l-0", + "gl-border-r-0!": "!gl-border-r-0", + "gl-border-1!": null, + "gl-border-t-1!": null, + "gl-border-b-1!": null, + "gl-border-b-2!": null, + "gl-border-top-0": "gl-border-t-0", + "gl-border-top-0!": "!gl-border-t-0", + "gl-border-bottom-0": "gl-border-b-0", + "gl-border-bottom-0!": "!gl-border-b-0", + "gl-rounded-0": "gl-rounded-none", + "gl-rounded-0!": "!gl-rounded-none", + "gl-rounded-6": null, + "gl-rounded-base": null, + "gl-rounded-base!": null, + "gl-rounded-full!": null, + "gl-rounded-small": null, + "gl-rounded-lg!": null, + "gl-rounded-pill": null, + "gl-rounded-left-none!": "!gl-rounded-l-none", + "gl-rounded-top-left-base": null, + "gl-rounded-top-left-none": "gl-rounded-tl-none", + "gl-rounded-top-left-none!": "!gl-rounded-tl-none", + "gl-rounded-top-right-base": null, + "gl-rounded-top-right-base!": null, + "gl-rounded-top-right-none": "gl-rounded-tr-none", + "gl-rounded-top-right-none!": "!gl-rounded-tr-none", + "gl-rounded-top-base": null, + "gl-rounded-bottom-left-small": null, + "gl-rounded-bottom-left-base": null, + "gl-rounded-bottom-left-base!": null, + "gl-rounded-bottom-left-none": "gl-rounded-bl-none", + "gl-rounded-bottom-left-none!": "!gl-rounded-bl-none", + "gl-rounded-bottom-right-small": null, + "gl-rounded-bottom-right-base": null, + "gl-rounded-bottom-right-base!": null, + "gl-rounded-bottom-right-none": "gl-rounded-br-none", + "gl-rounded-bottom-right-none!": "!gl-rounded-br-none", + "gl-rounded-bottom-base": null, + "gl-rounded-top-left-small": null, + "gl-rounded-top-right-small": null, + "gl-inset-border-1-gray-100!": null, + "gl-inset-border-1-gray-400": null, + "gl-inset-border-1-gray-400!": null, + "gl-focus-inset-border-2-blue-400!": null, + "gl-inset-border-1-red-500!": null, + "gl-shadow-none!": "!gl-shadow-none", + "gl-clearfix": null, + "gl-clearfix!": null, + "gl-reset-color": null, + "gl-reset-color!": null, + "gl-text-white!": "!gl-text-white", + "gl-text-body": "gl-text-primary", + "gl-text-body!": "!gl-text-primary", + "gl-text-secondary!": "!gl-text-secondary", + "gl-sm-text-body": "sm:gl-text-primary", + "gl-text-black-normal": "gl-text-gray-900", + "gl-text-black-normal!": "!gl-text-gray-900", + "gl-text-gray-300!": "!gl-text-gray-300", + "gl-text-gray-400!": "!gl-text-gray-400", + "gl-text-gray-500!": "!gl-text-gray-500", + "gl-text-gray-700!": "!gl-text-gray-700", + "gl-focus-text-gray-900": "focus:gl-text-gray-900", + "gl-hover-text-gray-900": "hover:gl-text-gray-900", + "gl-text-gray-900!": "!gl-text-gray-900", + "gl-hover-text-gray-900!": "hover:!gl-text-gray-900", + "gl-text-blue-500!": "!gl-text-blue-500", + "gl-hover-text-blue-600": "hover:gl-text-blue-600", + "gl-text-blue-600!": "!gl-text-blue-600", + "gl-hover-text-blue-800": "hover:gl-text-blue-800", + "gl-hover-text-blue-800!": "hover:!gl-text-blue-800", + "gl-text-red-500!": "!gl-text-red-500", + "gl--flex-center": null, + "gl-focus--focus": null, + "gl-cursor-default!": "!gl-cursor-default", + "gl-hover-cursor-pointer": "hover:gl-cursor-pointer", + "gl-cursor-grabbing!": "!gl-cursor-grabbing", + "gl-hover-cursor-not-allowed!": "hover:!gl-cursor-not-allowed", + "gl-cursor-text!": "!gl-cursor-text", + "gl-hover-cursor-crosshair": "hover:gl-cursor-crosshair", + "gl-cursor-help!": "!gl-cursor-help", + "gl-deprecated-top-66vh": null, + "gl-number-as-text-input": null, + "gl-display-none": "gl-hidden", + "gl-display-none!": "!gl-hidden", + "gl-sm-display-none": "sm:gl-hidden", + "gl-sm-display-none!": "sm:!gl-hidden", + "gl-md-display-none": "md:gl-hidden", + "gl-md-display-none!": "md:!gl-hidden", + "gl-lg-display-none": "lg:gl-hidden", + "gl-lg-display-none!": "lg:!gl-hidden", + "gl-display-flex": "gl-flex", + "gl-display-flex!": "!gl-flex", + "gl-sm-display-flex": "sm:gl-flex", + "gl-sm-display-flex!": "sm:!gl-flex", + "gl-md-display-flex": "md:gl-flex", + "gl-md-display-flex!": "md:!gl-flex", + "gl-lg-display-flex": "lg:gl-flex", + "gl-display-inline-flex": "gl-inline-flex", + "gl-display-inline-flex!": "!gl-inline-flex", + "gl-sm-display-inline-flex": "sm:gl-inline-flex", + "gl-sm-display-inline-flex!": "sm:!gl-inline-flex", + "gl-md-display-inline-flex": "md:gl-inline-flex", + "gl-md-display-inline-flex!": "md:!gl-inline-flex", + "gl-lg-display-inline-flex": "lg:gl-inline-flex", + "gl-display-block": "gl-block", + "gl-display-block!": "!gl-block", + "gl-sm-display-block": "sm:gl-block", + "gl-sm-display-block!": "sm:!gl-block", + "gl-md-display-block": "md:gl-block", + "gl-md-display-block!": "md:!gl-block", + "gl-lg-display-block": "lg:gl-block", + "gl-lg-display-block!": "lg:!gl-block", + "gl-display-inline": "gl-inline", + "gl-display-inline!": "!gl-inline", + "gl-sm-display-inline": "sm:gl-inline", + "gl-md-display-inline": "md:gl-inline", + "gl-display-inline-block": "gl-inline-block", + "gl-sm-display-inline-block": "sm:gl-inline-block", + "gl-sm-display-inline-block!": "sm:!gl-inline-block", + "gl-md-display-inline-block": "md:gl-inline-block", + "gl-md-display-inline-block!": "md:!gl-inline-block", + "gl-lg-display-inline-block": "lg:gl-inline-block", + "gl-display-table": "gl-table", + "gl-display-table-row": "gl-table-row", + "gl-display-table-row!": "!gl-table-row", + "gl-display-table-cell": "gl-table-cell", + "gl-display-table-cell!": "!gl-table-cell", + "gl-display-grid": "gl-grid", + "gl-sm-display-table-cell!": "sm:!gl-table-cell", + "gl-md-display-table-cell": "md:gl-table-cell", + "gl-lg-display-table-cell!": "lg:!gl-table-cell", + "gl-display-contents": "gl-contents", + "gl-align-items-baseline": "gl-items-baseline", + "gl-align-items-center": "gl-items-center", + "gl-align-items-center!": "!gl-items-center", + "gl-align-items-flex-start": "gl-items-start", + "gl-align-items-flex-start!": "!gl-items-start", + "gl-align-items-flex-end": "gl-items-end", + "gl-align-items-stretch": "gl-items-stretch", + "gl-align-items-stretch!": "!gl-items-stretch", + "gl-sm-align-items-center": "sm:gl-items-center", + "gl-md-align-items-center": "md:gl-items-center", + "gl-lg-align-items-center": "lg:gl-items-center", + "gl-sm-align-items-flex-start": "sm:gl-items-start", + "gl-sm-align-items-flex-end": "sm:gl-items-end", + "gl-md-align-items-flex-start": "md:gl-items-start", + "gl-lg-align-items-flex-start": "lg:gl-items-start", + "gl-lg-align-items-flex-end": "lg:gl-items-end", + "gl-sm-flex-wrap": "sm:gl-flex-wrap", + "gl-md-flex-nowrap": "md:gl-flex-nowrap", + "gl-sm-flex-nowrap": "sm:gl-flex-nowrap", + "gl-flex-direction-column": "gl-flex-col", + "gl-md-flex-direction-column": "md:gl-flex-col", + "gl-md-flex-direction-column!": "md:!gl-flex-col", + "gl-lg-flex-direction-column!": "lg:!gl-flex-col", + "gl-flex-direction-column-reverse": "gl-flex-col-reverse", + "gl-flex-direction-row": "gl-flex-row", + "gl-flex-direction-row!": "!gl-flex-row", + "gl-sm-flex-direction-row": "sm:gl-flex-row", + "gl-sm-flex-direction-row!": "sm:!gl-flex-row", + "gl-md-flex-direction-row": "md:gl-flex-row", + "gl-lg-flex-direction-row": "lg:gl-flex-row", + "gl-lg-flex-direction-row!": "lg:!gl-flex-row", + "gl-xl-flex-direction-row": "xl:gl-flex-row", + "gl-flex-direction-row-reverse": "gl-flex-row-reverse", + "gl-sm-flex-direction-row-reverse": "sm:gl-flex-row-reverse", + "gl-md-flex-direction-row-reverse": "md:gl-flex-row-reverse", + "gl-flex-grow-0!": "!gl-grow-0", + "gl-flex-grow-1": "gl-grow", + "gl-flex-grow-2": null, + "gl-md-flex-grow-0": "md:gl-grow-0", + "gl-flex-basis-0": "gl-basis-0", + "gl-flex-basis-quarter": "gl-basis-1/4", + "gl-flex-basis-third": "gl-basis-1/3", + "gl-md-flex-basis-13": "md:gl-basis-13", + "gl-flex-basis-two-thirds": "gl-basis-2/3", + "gl-flex-basis-half": "gl-basis-1/2", + "gl-flex-basis-full": "gl-basis-full", + "gl-flex-basis-full!": "!gl-basis-full", + "gl-flex-flow-row-wrap": null, + "gl-justify-content-center": "gl-justify-center", + "gl-justify-content-end": "gl-justify-end", + "gl-justify-content-end!": "!gl-justify-end", + "gl-sm-justify-content-end": "sm:gl-justify-end", + "gl-md-justify-content-center!": "md:!gl-justify-center", + "gl-md-justify-content-end": "md:gl-justify-end", + "gl-lg-justify-content-end": "lg:gl-justify-end", + "gl-justify-content-space-between": "gl-justify-between", + "gl-md-justify-content-space-between": "md:gl-justify-between", + "gl-justify-content-start": "gl-justify-start", + "gl-justify-content-start!": "!gl-justify-start", + "gl-sm-justify-content-start": "sm:gl-justify-start", + "gl-md-justify-content-start": "md:gl-justify-start", + "gl-lg-justify-content-start": "lg:gl-justify-start", + "gl-align-self-start": "gl-self-start", + "gl-align-self-end": "gl-self-end", + "gl-align-self-center": "gl-self-center", + "gl-md-align-self-center": "md:gl-self-center", + "gl-align-self-baseline": "gl-self-baseline", + "gl-sm-grid-template-columns-2": null, + "gl-md-grid-template-columns-2": null, + "gl-lg-grid-template-columns-4": null, + "gl-list-style-none": "gl-list-none", + "gl-opacity-0!": "!gl-opacity-0", + "gl-outline-0": null, + "gl-outline-0!": null, + "gl-outline-none": null, + "gl-outline-none!": null, + "gl-overflow-hidden!": "!gl-overflow-hidden", + "gl-overflow-x-hidden!": "!gl-overflow-x-hidden", + "gl-overflow-wrap-break": "gl-break-words", + "gl-overflow-wrap-anywhere": "gl-break-anywhere", + "gl-overflow-visible!": "!gl-overflow-visible", + "gl-w-auto!": "!gl-w-auto", + "gl-w-31!": "!gl-w-31", + "gl-w-10p": "gl-w-1/10", + "gl-w-40p": "gl-w-4/10", + "gl-w-90p": "gl-w-9/10", + "gl-md-w-full": "md:gl-w-full", + "gl-h-auto!": "!gl-h-auto", + "gl-h-6!": "!gl-h-6", + "gl-h-7!": "!gl-h-7", + "gl-h-full!": "!gl-h-full", + "gl-sm-w-auto": "sm:gl-w-auto", + "gl-sm-w-half": "sm:gl-w-1/2", + "gl-sm-w-25p": "sm:gl-w-1/4", + "gl-sm-w-30p": "sm:gl-w-3/10", + "gl-sm-w-40p": "sm:gl-w-4/10", + "gl-sm-w-75p": "sm:gl-w-3/4", + "gl-md-w-15": "md:gl-w-15", + "gl-md-w-20": "md:gl-w-20", + "gl-md-w-30": "md:gl-w-30", + "gl-md-w-half": "md:gl-w-1/2", + "gl-lg-w-half": "lg:gl-w-1/2", + "gl-md-w-auto": "md:gl-w-auto", + "gl-md-w-50p": "md:gl-w-1/2", + "gl-lg-w-1px": null, + "gl-lg-w-auto": "lg:gl-w-auto", + "gl-lg-w-25p": "lg:gl-w-1/4", + "gl-lg-w-30p": "lg:gl-w-3/10", + "gl-lg-w-40p": "lg:gl-w-4/10", + "gl-min-w-full!": "!gl-min-w-full", + "gl-min-w-fit-content!": "!gl-min-w-fit", + "gl-min-h-6!": "!gl-min-h-6", + "gl-min-h-7!": "!gl-min-h-7", + "gl-max-w-20!": "!gl-max-w-20", + "gl-max-w-30!": "!gl-max-w-30", + "gl-max-w-none!": "!gl-max-w-none", + "gl-max-w-full!": "!gl-max-w-full", + "gl-max-h-full!": "!gl-max-h-full", + "gl-max-w-50p": "gl-max-w-1/2", + "gl-md-max-w-26": "md:gl-max-w-26", + "gl-md-max-w-15p": null, + "gl-md-max-w-30p": null, + "gl-md-max-w-50p": null, + "gl-md-max-w-70p": null, + "gl-lg-max-w-80p": null, + "gl-p-0!": "!gl-p-0", + "gl-p-1!": "!gl-p-1", + "gl-p-2!": "!gl-p-2", + "gl-p-3!": "!gl-p-3", + "gl-p-4!": "!gl-p-4", + "gl-p-5!": "!gl-p-5", + "gl-px-0!": "!gl-px-0", + "gl-px-2!": "!gl-px-2", + "gl-px-3!": "!gl-px-3", + "gl-px-4!": "!gl-px-4", + "gl-px-5!": "!gl-px-5", + "gl-px-9!": "!gl-px-9", + "gl-pr-0!": "!gl-pr-0", + "gl-pr-2!": "!gl-pr-2", + "gl-pr-3!": "!gl-pr-3", + "gl-pr-4!": "!gl-pr-4", + "gl-pr-7!": "!gl-pr-7", + "gl-pr-8!": "!gl-pr-8", + "gl-pr-9!": "!gl-pr-9", + "gl-pl-0!": "!gl-pl-0", + "gl-pl-2!": "!gl-pl-2", + "gl-pl-3!": "!gl-pl-3", + "gl-pl-5!": "!gl-pl-5", + "gl-pl-6!": "!gl-pl-6", + "gl-pl-7!": "!gl-pl-7", + "gl-pl-9!": "!gl-pl-9", + "gl-pt-0!": "!gl-pt-0", + "gl-pt-2!": "!gl-pt-2", + "gl-pt-3!": "!gl-pt-3", + "gl-pt-4!": "!gl-pt-4", + "gl-pt-5!": "!gl-pt-5", + "gl-pt-6!": "!gl-pt-6", + "gl-pb-0!": "!gl-pb-0", + "gl-pb-1!": "!gl-pb-1", + "gl-pb-2!": "!gl-pb-2", + "gl-pb-3!": "!gl-pb-3", + "gl-pb-4!": "!gl-pb-4", + "gl-pb-5!": "!gl-pb-5", + "gl-pb-6!": "!gl-pb-6", + "gl-py-0!": "!gl-py-0", + "gl-py-2!": "!gl-py-2", + "gl-py-3!": "!gl-py-3", + "gl-py-4!": "!gl-py-4", + "gl-py-5!": "!gl-py-5", + "gl-py-6!": "!gl-py-6", + "gl-m-0!": "!gl-m-0", + "gl-mt-0!": "!gl-mt-0", + "gl-mt-2!": "!gl-mt-2", + "gl-mt-n2": "-gl-mt-2", + "gl-mt-3!": "!gl-mt-3", + "gl-mt-4!": "!gl-mt-4", + "gl-mt-5!": "!gl-mt-5", + "gl-mt-6!": "!gl-mt-6", + "gl-mr-0!": "!gl-mr-0", + "gl-mr-2!": "!gl-mr-2", + "gl-mr-3!": "!gl-mr-3", + "gl-mr-n3": "-gl-mr-3", + "gl-mr-4!": "!gl-mr-4", + "gl-sm-mr-3": "sm:gl-mr-3", + "gl-mb-0!": "!gl-mb-0", + "gl-mb-1!": "!gl-mb-1", + "gl-mb-n1": "-gl-mb-1", + "gl-mb-2!": "!gl-mb-2", + "gl-mb-n2": "-gl-mb-2", + "gl-mb-3!": "!gl-mb-3", + "gl-mb-n3": "-gl-mb-3", + "gl-mb-n3!": "!-gl-mb-3", + "gl-mb-4!": "!gl-mb-4", + "gl-mb-5!": "!gl-mb-5", + "gl-mb-6!": "!gl-mb-6", + "gl-sm-ml-auto": "sm:gl-ml-auto", + "gl-ml-0!": "!gl-ml-0", + "gl-ml-n1": "-gl-ml-1", + "gl-ml-2!": "!gl-ml-2", + "gl-ml-n2": "-gl-ml-2", + "gl-ml-3!": "!gl-ml-3", + "gl-ml-n3": "-gl-ml-3", + "gl-ml-n4": "-gl-ml-4", + "gl-ml-n4!": "!-gl-ml-4", + "gl-my-0!": "!gl-my-0", + "gl-my-2!": "!gl-my-2", + "gl-my-4!": "!gl-my-4", + "gl-mx-auto!": "!gl-mx-auto", + "gl-mx-0!": "!gl-mx-0", + "gl-mx-1!": "!gl-mx-1", + "gl-mx-2!": "!gl-mx-2", + "gl-mx-3!": "!gl-mx-3", + "gl-my-n1": "-gl-my-1", + "gl-mx-n1": "-gl-mx-1", + "gl-my-n2": "-gl-my-2", + "gl-my-n2!": "!-gl-my-2", + "gl-mx-n2": "-gl-mx-2", + "gl-my-n3": "-gl-my-3", + "gl-my-n3!": "!-gl-my-3", + "gl-mx-n3": "-gl-mx-3", + "gl-mx-n4": "-gl-mx-4", + "gl-mx-n5": "-gl-mx-5", + "gl-sm-gap-3": "sm:gl-gap-3", + "gl-sm-ml-3": "sm:gl-ml-3", + "gl-sm-ml-3!": "sm:!gl-ml-3", + "gl-sm-ml-5": "sm:gl-ml-5", + "gl-sm-ml-7": "sm:gl-ml-7", + "gl-sm-mr-0": "sm:gl-mr-0", + "gl-sm-mt-0": "sm:gl-mt-0", + "gl-sm-mt-6!": "sm:!gl-mt-6", + "gl-sm-mb-0": "sm:gl-mb-0", + "gl-sm-mb-0!": "sm:!gl-mb-0", + "gl-sm-mb-7": "sm:gl-mb-7", + "gl-sm-mx-0": "sm:gl-mx-0", + "gl-md-mt-0": "md:gl-mt-0", + "gl-md-mt-5": "md:gl-mt-5", + "gl-md-mb-0": "md:gl-mb-0", + "gl-md-mb-0!": "md:!gl-mb-0", + "gl-md-mb-3!": "md:!gl-mb-3", + "gl-lg-mb-0": "lg:gl-mb-0", + "gl-lg-mb-5": "lg:gl-mb-5", + "gl-md-ml-auto": "md:gl-ml-auto", + "gl-md-ml-2": "md:gl-ml-2", + "gl-md-ml-3": "md:gl-ml-3", + "gl-md-mr-3": "md:gl-mr-3", + "gl-md-mr-5": "md:gl-mr-5", + "gl-lg-mr-3": "lg:gl-mr-3", + "gl-lg-mr-10": "lg:gl-mr-10", + "gl-lg-mr-12": "lg:gl-mr-12", + "gl-lg-ml-2": "lg:gl-ml-2", + "gl-lg-ml-3": "lg:gl-ml-3", + "gl-lg-ml-10": "lg:gl-ml-10", + "gl-lg-ml-12": "lg:gl-ml-12", + "gl-xl-ml-3": "xl:gl-ml-3", + "gl-lg-mx-3": "lg:gl-mx-3", + "gl-lg-mx-12": "lg:gl-mx-12", + "gl-lg-my-5": "lg:gl-my-5", + "gl-lg-mt-0": "lg:gl-mt-0", + "gl-lg-mt-5": "lg:gl-mt-5", + "gl-sm-pr-2": "sm:gl-pr-2", + "gl-sm-pr-4": "sm:gl-pr-4", + "gl-sm-pl-6": "sm:gl-pl-6", + "gl-md-pt-0": "md:gl-pt-0", + "gl-md-pt-2": "md:gl-pt-2", + "gl-md-pt-3": "md:gl-pt-3", + "gl-md-pt-11!": "md:!gl-pt-11", + "gl-md-pr-0": "md:gl-pr-0", + "gl-md-pr-0!": "md:!gl-pr-0", + "gl-md-pr-3": "md:gl-pr-3", + "gl-md-pr-5": "md:gl-pr-5", + "gl-md-pl-0": "md:gl-pl-0", + "gl-md-pl-0!": "md:!gl-pl-0", + "gl-md-pl-3": "md:gl-pl-3", + "gl-md-pl-5": "md:gl-pl-5", + "gl-md-pl-7": "md:gl-pl-7", + "gl-md-px-7": "md:gl-px-7", + "gl-lg-pt-3": "lg:gl-pt-3", + "gl-lg-pr-5": "lg:gl-pr-5", + "gl-text-left!": "!gl-text-left", + "gl-text-center!": "!gl-text-center", + "gl-reset-text-align": null, + "gl-reset-text-align!": null, + "gl-text-decoration-none": null, + "gl-active-text-decoration-none": null, + "gl-focus-text-decoration-none": null, + "gl-hover-text-decoration-none": null, + "gl-text-decoration-none!": null, + "gl-active-text-decoration-none!": null, + "gl-hover-text-decoration-none!": null, + "gl-text-decoration-underline": "gl-underline", + "gl-hover-text-decoration-underline": "hover:gl-underline", + "gl-text-transform-capitalize": "gl-capitalize", + "gl-text-transform-uppercase": "gl-uppercase", + "gl-text-overflow-ellipsis": "gl-text-ellipsis", + "gl-text-overflow-ellipsis!": "!gl-text-ellipsis", + "gl-line-clamp-1": null, + "gl-line-clamp-2": null, + "gl-white-space-normal": "gl-whitespace-normal", + "gl-white-space-normal!": "!gl-whitespace-normal", + "gl-white-space-nowrap": "gl-whitespace-nowrap", + "gl-white-space-pre-wrap": "gl-whitespace-pre-wrap", + "gl-white-space-pre-wrap!": "!gl-whitespace-pre-wrap", + "gl-white-space-pre-line": "gl-whitespace-pre-line", + "gl-word-break-word": "gl-break-anywhere", + "gl-str-truncated": null, + "gl-text-truncate": "gl-truncate", + "gl-translate-y-n100": "-gl-translate-y-full", + "gl-transition-duration-slow": "gl-duration-slow", + "gl-transition-duration-medium": "gl-duration-medium", + "gl-transition-timing-function-ease": null, + "gl-transition-medium": "gl-transition-all", + "gl-font-style-italic": "gl-italic", + "gl-heading-5": null, + "gl-heading-4": null, + "gl-heading-3": null, + "gl-heading-2": null, + "gl-heading-1": null, + "gl-font-sm": "gl-text-sm", + "gl-font-sm!": "!gl-text-sm", + "gl-font-base": "gl-text-base", + "gl-font-lg": "gl-text-lg", + "gl-font-lg!": "!gl-text-lg", + "gl-font-size-h-display": null, + "gl-font-size-h1": null, + "gl-font-size-h2": null, + "gl-font-size-h1-xl": null, + "gl-font-size-h2-xl": null, + "gl-font-size-markdown": null, + "gl-reset-font-size": null, + "gl-font-weight-100": null, + "gl-font-weight-300": null, + "gl-font-weight-normal": null, + "gl-font-weight-normal!": null, + "gl-font-weight-semibold": null, + "gl-font-weight-semibold!": null, + "gl-font-weight-bold": null, + "gl-font-weight-bold!": null, + "gl-sm-font-weight-bold": null, + "gl-line-height-0": null, + "gl-line-height-1": null, + "gl-line-height-ratio-1000": null, + "gl-line-height-normal": null, + "gl-line-height-normal!": null, + "gl-line-height-20": null, + "gl-line-height-20!": null, + "gl-line-height-24": null, + "gl-line-height-28": null, + "gl-line-height-28!": null, + "gl-line-height-32": null, + "gl-line-height-36": null, + "gl-line-height-42": null, + "gl-vertical-align-top": "gl-align-top", + "gl-vertical-align-bottom": "gl-align-bottom", + "gl-vertical-align-text-bottom": "gl-align-text-bottom", + "gl-vertical-align-text-bottom!": "!gl-align-text-bottom", + "gl-visibility-hidden": "gl-invisible", + "gl-z-index-200": "gl-z-200", + "gl-z-index-9999!": "!gl-z-9999" +} diff --git a/spec/features/issues/user_toggles_subscription_spec.rb b/spec/features/issues/user_toggles_subscription_spec.rb index 6c611608510..c77b5e4935f 100644 --- a/spec/features/issues/user_toggles_subscription_spec.rb +++ b/spec/features/issues/user_toggles_subscription_spec.rb @@ -83,7 +83,7 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin visit(project_issue_path(project, issue)) end - it 'toggles subscription' do + it 'toggles subscription', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/435076' do subscription_button = find_by_testid('subscribe-button') expect(page).to have_selector("button[title='Notifications off']") diff --git a/spec/frontend/pages/shared/wikis/components/clone_wiki_modal_spec.js b/spec/frontend/pages/shared/wikis/components/clone_wiki_modal_spec.js index 408b543efd1..25f58de31ee 100644 --- a/spec/frontend/pages/shared/wikis/components/clone_wiki_modal_spec.js +++ b/spec/frontend/pages/shared/wikis/components/clone_wiki_modal_spec.js @@ -22,7 +22,6 @@ describe('DeleteWikiModal', () => { wikiPath: 'wiki-path', cloneSshUrl: 'ssh://clone.url/path', cloneHttpUrl: 'http://clone.url/path', - cloneLinkClass: '', }, propsData: { ...propsData }, stubs: { diff --git a/spec/frontend/pages/shared/wikis/components/wiki_more_dropdown_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_more_dropdown_spec.js index f833177f025..b8eda603723 100644 --- a/spec/frontend/pages/shared/wikis/components/wiki_more_dropdown_spec.js +++ b/spec/frontend/pages/shared/wikis/components/wiki_more_dropdown_spec.js @@ -23,7 +23,6 @@ describe('pages/shared/wikis/components/wiki_more_dropdown', () => { wikiPath: '', cloneSshUrl: 'ssh://clone.url/path', cloneHttpUrl: 'http://clone.url/path', - cloneLinkClass: '', templatesUrl: 'https://templates.url/path', pagePersisted: true, ...provide, diff --git a/spec/frontend/super_sidebar/components/global_search/components/global_search_autocomplete_items_spec.js b/spec/frontend/super_sidebar/components/global_search/components/global_search_autocomplete_items_spec.js index dcc9d897d16..5dca7744246 100644 --- a/spec/frontend/super_sidebar/components/global_search/components/global_search_autocomplete_items_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/components/global_search_autocomplete_items_spec.js @@ -15,9 +15,16 @@ import GlobalSearchNoResults from '~/super_sidebar/components/global_search/comp import { useMockInternalEventsTracking } from 'helpers/tracking_internal_events_helper'; import { - PROJECTS_GROUP_TITLE, - GROUPS_GROUP_TITLE, -} from '~/super_sidebar/components/global_search/command_palette/constants'; + EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE, + EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE, +} from '~/super_sidebar/components/global_search/tracking_constants'; + import { MOCK_GROUPED_AUTOCOMPLETE_OPTIONS, MOCK_SCOPED_SEARCH_OPTIONS, @@ -150,21 +157,6 @@ describe('GlobalSearchAutocompleteItems', () => { }); }); - describe.each` - event | category - ${'click_project_result_in_command_palette'} | ${PROJECTS_GROUP_TITLE} - ${'click_group_result_in_command_palette'} | ${GROUPS_GROUP_TITLE} - `('event tracking', ({ event, category }) => { - it(`tracks click for ${category} results`, async () => { - const { trackEventSpy } = bindInternalEventDocument(wrapper.element); - await findGlDisclosureDropdownGroup().vm.$emit('action', { - category, - }); - - expect(trackEventSpy).toHaveBeenCalledWith(event, {}, undefined); - }); - }); - describe.each` group | text ${'asdfasdf'} | ${'Go to %{kbdStart}↵%{kbdEnd}'} @@ -194,6 +186,28 @@ describe('GlobalSearchAutocompleteItems', () => { expect(findLayover().props('textMessage')).toBe(text); }); }); + + describe('tracking', () => { + it.each` + action | event + ${'Projects'} | ${EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE} + ${'Groups'} | ${EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE} + ${'Merge Requests'} | ${EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE} + ${'Issues'} | ${EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE} + ${'Recent issues'} | ${EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE} + ${'Recent epics'} | ${EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE} + ${'Recent merge requests'} | ${EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE} + ${undefined} | ${EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE} + `( + "triggers tracking event '$event' after emiting action '$action'", + ({ action, event }) => { + const { trackEventSpy } = bindInternalEventDocument(wrapper.element); + + findGlDisclosureDropdownGroup().vm.$emit('action', { name: action }); + expect(trackEventSpy).toHaveBeenCalledWith(event, {}, undefined); + }, + ); + }); }); }); }); diff --git a/spec/frontend/work_items/components/work_item_links/work_item_projects_listbox_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_projects_listbox_spec.js index 306fbdddcdd..0edc7411ae8 100644 --- a/spec/frontend/work_items/components/work_item_links/work_item_projects_listbox_spec.js +++ b/spec/frontend/work_items/components/work_item_links/work_item_projects_listbox_spec.js @@ -45,14 +45,14 @@ describe('WorkItemProjectsListbox', () => { const findRecentDropdownItems = () => findDropdown().find('ul').findAll('[role=option]'); const findRecentDropdownItemAt = (index) => findRecentDropdownItems().at(index); - const createComponent = async (isGroup = true) => { + const createComponent = async (isGroup = true, fullPath = 'group-a') => { wrapper = mountExtended(WorkItemProjectsListbox, { apolloProvider: createMockApollo([ [groupProjectsForLinksWidgetQuery, groupProjectsFormLinksWidgetResolver], [relatedProjectsForLinksWidgetQuery, relatedProjectsFormLinksWidgetResolver], ]), propsData: { - fullPath: 'group-a', + fullPath, isGroup, }, }); @@ -91,7 +91,7 @@ describe('WorkItemProjectsListbox', () => { const emitted = wrapper.emitted('selectProject'); - expect(emitted[0][0]).toEqual(groupProjectsData[0]); + expect(emitted[1][0]).toEqual(groupProjectsData[0]); }); it('renders recent projects if present', async () => { @@ -122,7 +122,7 @@ describe('WorkItemProjectsListbox', () => { const emitted = wrapper.emitted('selectProject'); - expect(emitted[0][0]).toEqual(groupProjectsData[1]); + expect(emitted[1][0]).toEqual(groupProjectsData[1]); }); it('supports filtering recent projects via search input', async () => { @@ -149,7 +149,7 @@ describe('WorkItemProjectsListbox', () => { describe('project level work items', () => { beforeEach(async () => { - await createComponent(false); + await createComponent(false, 'group-a/example-project-a'); gon.current_username = 'root'; }); @@ -164,6 +164,14 @@ describe('WorkItemProjectsListbox', () => { expect(dropdownItem.text()).toContain(relatedProjectsData[0].namespace.name); }); + it('auto-selects the current project', async () => { + await nextTick(); + + const emitted = wrapper.emitted('selectProject'); + + expect(emitted[0][0]).toEqual(relatedProjectsData[0]); + }); + it('supports selecting a project', async () => { removeLocalstorageFrequentItems(); @@ -171,13 +179,13 @@ describe('WorkItemProjectsListbox', () => { await nextTick(); - await findDropdownItemFor(relatedProjectsData[0].fullPath).trigger('click'); + await findDropdownItemFor(relatedProjectsData[1].fullPath).trigger('click'); await nextTick(); const emitted = wrapper.emitted('selectProject'); - expect(emitted[0][0]).toEqual(relatedProjectsData[0]); + expect(emitted[1][0]).toEqual(relatedProjectsData[1]); }); it('renders recent projects if present', async () => { @@ -208,7 +216,7 @@ describe('WorkItemProjectsListbox', () => { const emitted = wrapper.emitted('selectProject'); - expect(emitted[0][0]).toEqual(relatedProjectsData[1]); + expect(emitted[1][0]).toEqual(relatedProjectsData[1]); }); it('supports filtering recent projects via search input', async () => { diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb index 654c3e6939a..215634152dd 100644 --- a/spec/requests/api/graphql/ci/jobs_spec.rb +++ b/spec/requests/api/graphql/ci/jobs_spec.rb @@ -232,7 +232,8 @@ RSpec.describe 'Query.project.pipeline', feature_category: :continuous_integrati create(:ci_build_need, build: test_job, name: 'my test job') end - it 'reports the build needs and execution requirements' do + it 'reports the build needs and execution requirements', + quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/448867' do post_graphql(query, current_user: user) expect(jobs_graphql_data).to contain_exactly(