diff options
181 files changed, 899 insertions, 596 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4b5ce1ff7b2..50441492d60 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,8 @@ workflow: # If `$FORCE_GITLAB_CI` is set, create a pipeline. - if: '$FORCE_GITLAB_CI' variables: - RUBY_VERSION: "3.0" + <<: *ruby3-variables + PIPELINE_NAME: 'Ruby 3 forced pipeline' # As part of the process of creating RCs automatically, we update stable # branches with the changes of the most recent production deployment. The # merge requests used for this merge a branch release-tools/X into a stable @@ -55,6 +56,11 @@ workflow: variables: <<: *ruby2-variables PIPELINE_NAME: 'Ruby 2 $CI_MERGE_REQUEST_EVENT_TYPE MR pipeline' + - if: '$CI_MERGE_REQUEST_LABELS =~ /Community contribution/' + variables: + <<: *ruby3-variables + GITLAB_DEPENDENCY_PROXY_ADDRESS: "" + PIPELINE_NAME: 'Ruby 3 $CI_MERGE_REQUEST_EVENT_TYPE MR pipeline (community contribution)' # For (detached) merge request pipelines. - if: '$CI_MERGE_REQUEST_IID' variables: @@ -66,13 +72,13 @@ workflow: <<: *ruby3-variables <<: *default-branch-incident-variables CRYSTALBALL: "true" - PIPELINE_NAME: 'Scheduled $CI_COMMIT_BRANCH pipeline' + PIPELINE_NAME: 'Scheduled Ruby 3 $CI_COMMIT_BRANCH branch pipeline' # Run pipelines for ruby2 branch - if: '$CI_COMMIT_BRANCH == "ruby2" && $CI_PIPELINE_SOURCE == "schedule"' variables: <<: *ruby2-variables NOTIFY_PIPELINE_FAILURE_CHANNEL: "f_ruby3" - PIPELINE_NAME: 'Scheduled ruby 2 pipeline' + PIPELINE_NAME: 'Scheduled Ruby 2 $CI_COMMIT_BRANCH branch pipeline' # This work around https://gitlab.com/gitlab-org/gitlab/-/issues/332411 whichs prevents usage of dependency proxy # when pipeline is triggered by a project access token. - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $GITLAB_USER_LOGIN =~ /project_\d+_bot\d*/' @@ -80,15 +86,18 @@ workflow: <<: *ruby3-variables <<: *default-branch-incident-variables GITLAB_DEPENDENCY_PROXY_ADDRESS: "" + PIPELINE_NAME: 'Ruby 3 $CI_COMMIT_BRANCH branch pipeline (trigerred by a project token)' # For `$CI_DEFAULT_BRANCH` branch, create a pipeline (this includes on schedules, pushes, merges, etc.). - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' variables: <<: *ruby3-variables <<: *default-branch-incident-variables + PIPELINE_NAME: 'Ruby 3 $CI_COMMIT_BRANCH branch pipeline' # For tags, create a pipeline. - if: '$CI_COMMIT_TAG' variables: <<: *ruby2-variables + PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_TAG tag pipeline' # If `$GITLAB_INTERNAL` isn't set, don't create a pipeline. - if: '$GITLAB_INTERNAL == null' when: never @@ -97,12 +106,15 @@ workflow: variables: <<: *ruby2-variables NOTIFY_PIPELINE_FAILURE_CHANNEL: "releases" + PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline' - if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/' variables: <<: *ruby2-variables + PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline' - if: '$CI_COMMIT_BRANCH =~ /^security\//' variables: <<: *ruby2-variables + PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline' variables: PG_VERSION: "12" diff --git a/.gitlab/ci/as-if-jh.gitlab-ci.yml b/.gitlab/ci/as-if-jh.gitlab-ci.yml index 768c7df0219..7680bc6eac3 100644 --- a/.gitlab/ci/as-if-jh.gitlab-ci.yml +++ b/.gitlab/ci/as-if-jh.gitlab-ci.yml @@ -10,7 +10,7 @@ add-jh-files: extends: - .shared-as-if-jh - .as-if-jh:rules:prepare-as-if-jh - image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION} + image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION} stage: prepare before_script: - source ./scripts/utils.sh diff --git a/.gitlab/ci/caching.gitlab-ci.yml b/.gitlab/ci/caching.gitlab-ci.yml index 6a13fc3c56f..fba2efc46e4 100644 --- a/.gitlab/ci/caching.gitlab-ci.yml +++ b/.gitlab/ci/caching.gitlab-ci.yml @@ -56,7 +56,7 @@ packages-cleanup: extends: - .default-retry - .caching:rules:packages-cleanup - image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION} + image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION} stage: prepare before_script: - source scripts/utils.sh diff --git a/.gitlab/ci/package-and-test/main.gitlab-ci.yml b/.gitlab/ci/package-and-test/main.gitlab-ci.yml index 68c3d5a6706..44b28d28734 100644 --- a/.gitlab/ci/package-and-test/main.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test/main.gitlab-ci.yml @@ -625,11 +625,6 @@ e2e-test-report: ALLURE_MERGE_REQUEST_IID: $CI_MERGE_REQUEST_IID ALLURE_JOB_NAME: e2e-package-and-test GIT_STRATEGY: none - artifacts: # save rspec results for displaying in parent pipeline - expire_in: 1 day - when: always - paths: - - gitlab-qa-run-*/**/rspec-*.xml upload-knapsack-report: extends: diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index f6668d7864e..2864014e17e 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -89,25 +89,3 @@ e2e:package-and-test: include: - artifact: package-and-test-pipeline.yml job: e2e-test-pipeline-generate - -# Fetch child pipeline test results and store in parent pipeline -# workaround until natively implemented: https://gitlab.com/groups/gitlab-org/-/epics/8205 -e2e:package-and-test-results: - image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3 - extends: - - .qa-job-base - - .qa:rules:package-and-test - stage: qa - needs: - - e2e:package-and-test - variables: - COLORIZED_LOGS: "true" - QA_LOG_LEVEL: "debug" - when: always - allow_failure: true - script: - - bundle exec rake "ci:download_test_results[e2e:package-and-test,e2e-test-report,${CI_PROJECT_DIR}]" - artifacts: - when: always - reports: - junit: gitlab-qa-run-*/**/rspec-*.xml diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml index 41f36215045..da3a2afcbb6 100644 --- a/.gitlab/ci/review-apps/main.gitlab-ci.yml +++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml @@ -32,7 +32,7 @@ review-build-cng-env: extends: - .default-retry - .review:rules:review-build-cng - image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}-alpine3.16 + image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-alpine3.16 stage: prepare needs: # We need this job because we need its `cached-assets-hash.txt` artifact, so that we can pass the assets image tag to the downstream CNG pipeline. @@ -108,7 +108,7 @@ review-deploy: - .review-workflow-base - .review:rules:review-deploy stage: deploy - image: ${GITLAB_DEPENDENCY_PROXY}dtzar/helm-kubectl:3.10.3 + image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}dtzar/helm-kubectl:3.10.3 needs: - review-build-cng - review-delete-deployment # We always want to start from a clean slate (i.e. no helm release, no k8s namespace) diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml index 01a738127f7..912df0ede29 100644 --- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml +++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml @@ -147,11 +147,6 @@ e2e-test-report: GIT_STRATEGY: none allow_failure: true when: always - artifacts: # re-save rspec results for displaying in parent pipeline - expire_in: 1 day - when: always - paths: - - qa/tmp/rspec-*.xml upload-knapsack-report: extends: diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index c331671d180..20e4dec7dbf 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -88,30 +88,6 @@ start-review-app-pipeline: - artifact: review-app-pipeline.yml job: e2e-test-pipeline-generate -# Fetch child pipeline test results and store in parent pipeline -# workaround until natively implemented: https://gitlab.com/groups/gitlab-org/-/epics/8205 -review-app-test-results: - image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3 - stage: review - extends: - - .qa-cache - - .review:rules:start-review-app-pipeline - needs: - - start-review-app-pipeline - variables: - COLORIZED_LOGS: "true" - QA_LOG_LEVEL: "debug" - before_script: - - cd qa && bundle install - script: - - bundle exec rake "ci:download_test_results[start-review-app-pipeline,e2e-test-report,${CI_PROJECT_DIR}]" - when: always - allow_failure: true - artifacts: - when: always - reports: - junit: qa/tmp/rspec-*.xml - danger-review: extends: - .default-retry diff --git a/.rubocop_todo/gitlab/delegate_predicate_methods.yml b/.rubocop_todo/gitlab/delegate_predicate_methods.yml deleted file mode 100644 index eb96914796f..00000000000 --- a/.rubocop_todo/gitlab/delegate_predicate_methods.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -Gitlab/DelegatePredicateMethods: - Exclude: - - 'app/models/clusters/cluster.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 7279197a244..89a5c6b44c3 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -a966c74ae41b0c749ea0433501cc39dbff96ce3f +9e9717d60e83bc08e6bcb3ca0e636edf1668a9b3 diff --git a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue index dcdc939a947..ce2c511ddd4 100644 --- a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue @@ -33,6 +33,7 @@ import { INSTANCE_TYPE, I18N_FETCH_ERROR, FILTER_CSS_CLASSES, + JOBS_ROUTE_PATH, } from '../constants'; import { captureException } from '../sentry_utils'; @@ -150,7 +151,7 @@ export default { methods: { jobsUrl(runner) { const url = new URL(runner.adminUrl); - url.hash = '#/jobs'; + url.hash = `#${JOBS_ROUTE_PATH}`; return url.href; }, @@ -228,17 +229,17 @@ export default { :checkable="true" @deleted="onDeleted" > - <template #runner-name="{ runner }"> - <gl-link :href="runner.adminUrl"> - <runner-name :runner="runner" /> - </gl-link> - </template> <template #runner-job-status-badge="{ runner }"> <runner-job-status-badge :href="jobsUrl(runner)" :job-status="runner.jobExecutionStatus" /> </template> + <template #runner-name="{ runner }"> + <gl-link :href="runner.adminUrl"> + <runner-name :runner="runner" /> + </gl-link> + </template> <template #runner-actions-cell="{ runner }"> <runner-actions-cell :runner="runner" diff --git a/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue b/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue index cfbe37f5ba2..4d04b5d4b14 100644 --- a/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue +++ b/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue @@ -36,5 +36,6 @@ export default { v-if="paused" class="gl-display-inline-block gl-max-w-full gl-text-truncate" /> + <slot :runner="runner" name="runner-job-status-badge"></slot> </div> </template> diff --git a/app/assets/javascripts/ci/runner/components/cells/runner_summary_cell.vue b/app/assets/javascripts/ci/runner/components/cells/runner_summary_cell.vue index 4a72023b6a0..97dfbe1a051 100644 --- a/app/assets/javascripts/ci/runner/components/cells/runner_summary_cell.vue +++ b/app/assets/javascripts/ci/runner/components/cells/runner_summary_cell.vue @@ -6,7 +6,6 @@ import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import RunnerName from '../runner_name.vue'; import RunnerTags from '../runner_tags.vue'; import RunnerTypeBadge from '../runner_type_badge.vue'; -import RunnerJobStatusBadge from '../runner_job_status_badge.vue'; import { formatJobCount } from '../../utils'; import { @@ -27,7 +26,6 @@ export default { RunnerName, RunnerTags, RunnerTypeBadge, - RunnerJobStatusBadge, RunnerUpgradeStatusIcon: () => import('ee_component/ci/runner/components/runner_upgrade_status_icon.vue'), TooltipOnTruncate, @@ -90,10 +88,6 @@ export default { </div> <div> - <slot :runner="runner" name="runner-job-status-badge"> - <runner-job-status-badge :job-status="runner.jobExecutionStatus" /> - </slot> - <runner-summary-field icon="clock"> <gl-sprintf :message="$options.i18n.I18N_LAST_CONTACT_LABEL"> <template #timeAgo> diff --git a/app/assets/javascripts/ci/runner/components/runner_details_tabs.vue b/app/assets/javascripts/ci/runner/components/runner_details_tabs.vue index 23076915001..e4190a4dffd 100644 --- a/app/assets/javascripts/ci/runner/components/runner_details_tabs.vue +++ b/app/assets/javascripts/ci/runner/components/runner_details_tabs.vue @@ -2,7 +2,7 @@ import { GlBadge, GlTabs, GlTab } from '@gitlab/ui'; import VueRouter from 'vue-router'; import HelpPopover from '~/vue_shared/components/help_popover.vue'; -import { I18N_DETAILS, I18N_JOBS } from '../constants'; +import { JOBS_ROUTE_PATH, I18N_DETAILS, I18N_JOBS } from '../constants'; import { formatJobCount } from '../utils'; import RunnerDetails from './runner_details.vue'; import RunnerJobs from './runner_jobs.vue'; @@ -17,7 +17,7 @@ const routes = [ component: RunnerDetails, }, { - path: '/jobs', + path: JOBS_ROUTE_PATH, name: ROUTE_JOBS, component: RunnerJobs, }, diff --git a/app/assets/javascripts/ci/runner/components/runner_job_status_badge.vue b/app/assets/javascripts/ci/runner/components/runner_job_status_badge.vue index 1e52acecfb8..bed592e3f30 100644 --- a/app/assets/javascripts/ci/runner/components/runner_job_status_badge.vue +++ b/app/assets/javascripts/ci/runner/components/runner_job_status_badge.vue @@ -45,8 +45,7 @@ export default { <gl-badge v-if="badge" v-bind="$attrs" - size="sm" - class="gl-mr-3 gl-bg-transparent!" + class="gl-display-inline-block gl-max-w-full gl-text-truncate gl-bg-transparent!" variant="muted" :class="badge.classes" > diff --git a/app/assets/javascripts/ci/runner/components/runner_list.vue b/app/assets/javascripts/ci/runner/components/runner_list.vue index b2aad0aac4f..ec04701db2c 100644 --- a/app/assets/javascripts/ci/runner/components/runner_list.vue +++ b/app/assets/javascripts/ci/runner/components/runner_list.vue @@ -150,16 +150,17 @@ export default { </template> <template #cell(status)="{ item }"> - <runner-status-cell :runner="item" /> + <runner-status-cell :runner="item"> + <template #runner-job-status-badge="{ runner }"> + <slot name="runner-job-status-badge" :runner="runner"></slot> + </template> + </runner-status-cell> </template> - <template #cell(summary)="{ item, index }"> + <template #cell(summary)="{ item }"> <runner-summary-cell :runner="item"> <template #runner-name="{ runner }"> - <slot name="runner-name" :runner="runner" :index="index"></slot> - </template> - <template #runner-job-status-badge="{ runner }"> - <slot name="runner-job-status-badge" :runner="runner" :index="index"></slot> + <slot name="runner-name" :runner="runner"></slot> </template> </runner-summary-cell> </template> diff --git a/app/assets/javascripts/ci/runner/constants.js b/app/assets/javascripts/ci/runner/constants.js index 31900a1fe89..dc4a62852ed 100644 --- a/app/assets/javascripts/ci/runner/constants.js +++ b/app/assets/javascripts/ci/runner/constants.js @@ -98,6 +98,8 @@ export const I18N_ADMIN = s__('Runners|Administrator'); // Runner details +export const JOBS_ROUTE_PATH = '/jobs'; // vue-router route path + export const I18N_DETAILS = s__('Runners|Details'); export const I18N_JOBS = s__('Runners|Jobs'); export const I18N_ASSIGNED_PROJECTS = s__('Runners|Assigned Projects (%{projectCount})'); diff --git a/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue index f61c19b151e..e66a1c7b1aa 100644 --- a/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue +++ b/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue @@ -24,6 +24,7 @@ import RunnerPagination from '../components/runner_pagination.vue'; import RunnerTypeTabs from '../components/runner_type_tabs.vue'; import RunnerActionsCell from '../components/cells/runner_actions_cell.vue'; import RunnerMembershipToggle from '../components/runner_membership_toggle.vue'; +import RunnerJobStatusBadge from '../components/runner_job_status_badge.vue'; import { pausedTokenConfig } from '../components/search_tokens/paused_token_config'; import { statusTokenConfig } from '../components/search_tokens/status_token_config'; @@ -34,6 +35,7 @@ import { PROJECT_TYPE, I18N_FETCH_ERROR, FILTER_CSS_CLASSES, + JOBS_ROUTE_PATH, } from '../constants'; import { captureException } from '../sentry_utils'; @@ -51,6 +53,7 @@ export default { RunnerPagination, RunnerTypeTabs, RunnerActionsCell, + RunnerJobStatusBadge, }, mixins: [glFeatureFlagMixin()], inject: ['emptyStateSvgPath', 'emptyStateFilteredSvgPath'], @@ -171,6 +174,12 @@ export default { editUrl(runner) { return this.runners.urlsById[runner.id]?.edit; }, + jobsUrl(runner) { + const url = new URL(this.webUrl(runner)); + url.hash = `#${JOBS_ROUTE_PATH}`; + + return url.href; + }, refetchCounts() { this.$apollo.getClient().refetchQueries({ include: [groupRunnersCountQuery] }); }, @@ -251,6 +260,12 @@ export default { :loading="runnersLoading" @deleted="onDeleted" > + <template #runner-job-status-badge="{ runner }"> + <runner-job-status-badge + :href="jobsUrl(runner)" + :job-status="runner.jobExecutionStatus" + /> + </template> <template #runner-name="{ runner }"> <gl-link :href="webUrl(runner)"> <runner-name :runner="runner" /> diff --git a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue index 93970ce5193..ace128e22db 100644 --- a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue +++ b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue @@ -1,5 +1,5 @@ <script> -import { GlButton, GlEmptyState, GlTooltipDirective } from '@gitlab/ui'; +import { GlButton, GlEmptyState, GlFilteredSearchToken, GlTooltipDirective } from '@gitlab/ui'; import * as Sentry from '@sentry/browser'; import getIssuesQuery from 'ee_else_ce/issues/dashboard/queries/get_issues.query.graphql'; import IssueCardStatistics from 'ee_else_ce/issues/list/components/issue_card_statistics.vue'; @@ -7,6 +7,7 @@ import IssueCardTimeInfo from 'ee_else_ce/issues/list/components/issue_card_time import { IssuableStatus } from '~/issues/constants'; import { CREATED_DESC, + defaultTypeTokenOptions, i18n, PAGE_SIZE, PARAM_STATE, @@ -28,16 +29,24 @@ import axios from '~/lib/utils/axios_utils'; import { scrollUp } from '~/lib/utils/scroll_utils'; import { getParameterByName } from '~/lib/utils/url_utility'; import { + OPERATORS_IS, + OPERATORS_IS_NOT_OR, TOKEN_TITLE_ASSIGNEE, TOKEN_TITLE_AUTHOR, + TOKEN_TITLE_CONFIDENTIAL, TOKEN_TITLE_LABEL, TOKEN_TITLE_MILESTONE, TOKEN_TITLE_MY_REACTION, + TOKEN_TITLE_SEARCH_WITHIN, + TOKEN_TITLE_TYPE, TOKEN_TYPE_ASSIGNEE, TOKEN_TYPE_AUTHOR, + TOKEN_TYPE_CONFIDENTIAL, TOKEN_TYPE_LABEL, TOKEN_TYPE_MILESTONE, TOKEN_TYPE_MY_REACTION, + TOKEN_TYPE_SEARCH_WITHIN, + TOKEN_TYPE_TYPE, } from '~/vue_shared/components/filtered_search_bar/constants'; import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue'; import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants'; @@ -201,6 +210,7 @@ export default { title: TOKEN_TITLE_ASSIGNEE, icon: 'user', token: UserToken, + operators: OPERATORS_IS_NOT_OR, fetchUsers: this.fetchUsers, preloadedUsers, recentSuggestionsStorageKey: 'dashboard-issues-recent-tokens-assignee', @@ -210,6 +220,7 @@ export default { title: TOKEN_TITLE_AUTHOR, icon: 'pencil', token: UserToken, + operators: OPERATORS_IS_NOT_OR, fetchUsers: this.fetchUsers, defaultUsers: [], preloadedUsers, @@ -220,6 +231,7 @@ export default { title: TOKEN_TITLE_LABEL, icon: 'labels', token: LabelToken, + operators: OPERATORS_IS_NOT_OR, fetchLabels: this.fetchLabels, recentSuggestionsStorageKey: 'dashboard-issues-recent-tokens-label', }, @@ -232,10 +244,46 @@ export default { recentSuggestionsStorageKey: 'dashboard-issues-recent-tokens-milestone', shouldSkipSort: true, }, + { + type: TOKEN_TYPE_SEARCH_WITHIN, + title: TOKEN_TITLE_SEARCH_WITHIN, + icon: 'search', + token: GlFilteredSearchToken, + unique: true, + operators: OPERATORS_IS, + options: [ + { icon: 'title', value: 'TITLE', title: this.$options.i18n.titles }, + { + icon: 'text-description', + value: 'DESCRIPTION', + title: this.$options.i18n.descriptions, + }, + ], + }, + { + type: TOKEN_TYPE_TYPE, + title: TOKEN_TITLE_TYPE, + icon: 'issues', + token: GlFilteredSearchToken, + options: defaultTypeTokenOptions, + }, ]; if (this.isSignedIn) { tokens.push({ + type: TOKEN_TYPE_CONFIDENTIAL, + title: TOKEN_TITLE_CONFIDENTIAL, + icon: 'eye-slash', + token: GlFilteredSearchToken, + unique: true, + operators: OPERATORS_IS, + options: [ + { icon: 'eye-slash', value: 'yes', title: this.$options.i18n.confidentialYes }, + { icon: 'eye', value: 'no', title: this.$options.i18n.confidentialNo }, + ], + }); + + tokens.push({ type: TOKEN_TYPE_MY_REACTION, title: TOKEN_TITLE_MY_REACTION, icon: 'thumb-up', diff --git a/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql b/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql index c9fae7cc05d..5625e6afad3 100644 --- a/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql +++ b/app/assets/javascripts/issues/dashboard/queries/get_issues.query.graphql @@ -10,11 +10,15 @@ query getDashboardIssues( $assigneeId: String $assigneeUsernames: [String!] $authorUsername: String + $confidential: Boolean $labelName: [String] $milestoneTitle: [String] $milestoneWildcardId: MilestoneWildcardId $myReactionEmoji: String + $types: [IssueType!] + $in: [IssuableSearchableField!] $not: NegatedIssueFilterInput + $or: UnionedIssueFilterInput $afterCursor: String $beforeCursor: String $firstPageSize: Int @@ -27,11 +31,15 @@ query getDashboardIssues( assigneeId: $assigneeId assigneeUsernames: $assigneeUsernames authorUsername: $authorUsername + confidential: $confidential labelName: $labelName milestoneTitle: $milestoneTitle milestoneWildcardId: $milestoneWildcardId myReactionEmoji: $myReactionEmoji + types: $types + in: $in not: $not + or: $or after: $afterCursor before: $beforeCursor first: $firstPageSize diff --git a/app/assets/javascripts/issues/dashboard/queries/get_issues_counts.query.graphql b/app/assets/javascripts/issues/dashboard/queries/get_issues_counts.query.graphql index 00a2b8a2407..b36f546e4ab 100644 --- a/app/assets/javascripts/issues/dashboard/queries/get_issues_counts.query.graphql +++ b/app/assets/javascripts/issues/dashboard/queries/get_issues_counts.query.graphql @@ -3,11 +3,15 @@ query getDashboardIssuesCount( $assigneeId: String $assigneeUsernames: [String!] $authorUsername: String + $confidential: Boolean $labelName: [String] $milestoneTitle: [String] $milestoneWildcardId: MilestoneWildcardId $myReactionEmoji: String + $types: [IssueType!] + $in: [IssuableSearchableField!] $not: NegatedIssueFilterInput + $or: UnionedIssueFilterInput ) { openedIssues: issues( state: opened @@ -15,11 +19,15 @@ query getDashboardIssuesCount( assigneeId: $assigneeId assigneeUsernames: $assigneeUsernames authorUsername: $authorUsername + confidential: $confidential labelName: $labelName milestoneTitle: $milestoneTitle milestoneWildcardId: $milestoneWildcardId myReactionEmoji: $myReactionEmoji + types: $types + in: $in not: $not + or: $or ) { count } @@ -29,11 +37,15 @@ query getDashboardIssuesCount( assigneeId: $assigneeId assigneeUsernames: $assigneeUsernames authorUsername: $authorUsername + confidential: $confidential labelName: $labelName milestoneTitle: $milestoneTitle milestoneWildcardId: $milestoneWildcardId myReactionEmoji: $myReactionEmoji + types: $types + in: $in not: $not + or: $or ) { count } @@ -43,11 +55,15 @@ query getDashboardIssuesCount( assigneeId: $assigneeId assigneeUsernames: $assigneeUsernames authorUsername: $authorUsername + confidential: $confidential labelName: $labelName milestoneTitle: $milestoneTitle milestoneWildcardId: $milestoneWildcardId myReactionEmoji: $myReactionEmoji + types: $types + in: $in not: $not + or: $or ) { count } diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue index 541923bb735..95e140f30a9 100644 --- a/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue +++ b/app/assets/javascripts/projects/settings/branch_rules/components/edit/protections/push_protections.vue @@ -4,7 +4,7 @@ import { s__ } from '~/locale'; import { helpPagePath } from '~/helpers/help_page_helper'; export const i18n = { - allowedToPush: s__('BranchRules|Allowed to push'), + allowedToPush: s__('BranchRules|Allowed to push and merge'), forcePushTitle: s__( 'BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}.', ), diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js index 9897f1cf054..a98c2439cde 100644 --- a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js +++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js @@ -30,7 +30,7 @@ export const I18N = { ), statusChecksLinkTitle: s__('BranchRules|Manage in status checks'), statusChecksHeader: s__('BranchRules|Status checks (%{total})'), - allowedToPushHeader: s__('BranchRules|Allowed to push (%{total})'), + allowedToPushHeader: s__('BranchRules|Allowed to push and merge (%{total})'), allowedToMergeHeader: s__('BranchRules|Allowed to merge (%{total})'), approvalsHeader: s__('BranchRules|Required approvals (%{total})'), noData: s__('BranchRules|No data to display'), diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue index 4a24df4b0dc..10a1d895249 100644 --- a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue +++ b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue @@ -13,7 +13,7 @@ export const i18n = { approvalRules: s__('BranchRules|%{total} approval %{subject}'), matchingBranches: s__('BranchRules|%{total} matching %{subject}'), pushAccessLevels: s__('BranchRules|Allowed to merge'), - mergeAccessLevels: s__('BranchRules|Allowed to push'), + mergeAccessLevels: s__('BranchRules|Allowed to push and merge'), }; export default { diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js index 993b4c11c0e..0a34e5e55e1 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js @@ -85,5 +85,4 @@ export const TOKEN_TYPE_STATUS = 'status'; export const TOKEN_TYPE_TARGET_BRANCH = 'target-branch'; export const TOKEN_TYPE_TYPE = 'type'; export const TOKEN_TYPE_WEIGHT = 'weight'; - export const TOKEN_TYPE_SEARCH_WITHIN = 'in'; diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 6a5680c080b..58843435fa0 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -105,7 +105,7 @@ module Emails @written_count = export_status.fetch(:rows_written) @truncated = export_status.fetch(:truncated) @size_limit = ActiveSupport::NumberHelper - .number_to_human_size(Issuable::ExportCsv::BaseService::TARGET_FILESIZE) + .number_to_human_size(ExportCsv::BaseService::TARGET_FILESIZE) filename = "#{project.full_path.parameterize}_issues_#{Date.today.iso8601}.csv" attachments[filename] = { content: csv_data, mime_type: 'text/csv' } diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index fc944c34166..6678bb563ed 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -138,7 +138,7 @@ module Emails @written_count = export_status.fetch(:rows_written) @truncated = export_status.fetch(:truncated) @size_limit = ActiveSupport::NumberHelper - .number_to_human_size(Issuable::ExportCsv::BaseService::TARGET_FILESIZE) + .number_to_human_size(ExportCsv::BaseService::TARGET_FILESIZE) filename = "#{project.full_path.parameterize}_merge_requests_#{Date.current.iso8601}.csv" attachments[filename] = { content: csv_data, mime_type: 'text/csv' } diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index bac85b6095e..5c4512c5f72 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -15,6 +15,8 @@ module Ci include EachBatch include Ci::HasRunnerExecutor + extend ::Gitlab::Utils::Override + add_authentication_token_field :token, encrypted: :optional, expires_at: :compute_token_expiration enum access_level: { @@ -28,6 +30,9 @@ module Ci project_type: 3 } + # Prefix assigned to runners created from the UI, instead of registered via the command line + CREATED_RUNNER_TOKEN_PREFIX = 'glrt-' + # This `ONLINE_CONTACT_TIMEOUT` needs to be larger than # `RUNNER_QUEUE_EXPIRY_TIME+UPDATE_CONTACT_COLUMN_EVERY` # @@ -191,6 +196,8 @@ module Ci cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at, :executor_type + attr_writer :legacy_registered + chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout, error_message: 'Maximum job timeout has a value which could not be accepted' @@ -290,6 +297,13 @@ module Ci end end + def initialize(params) + @legacy_registered = params&.delete(:legacy_registered) + @legacy_registered = true if @legacy_registered.nil? + + super(params) + end + def assign_to(project, current_user = nil) if instance_type? raise ArgumentError, 'Transitioning an instance runner to a project runner is not supported' @@ -474,6 +488,13 @@ module Ci end end + override :format_token + def format_token(token) + return token if @legacy_registered + + "#{CREATED_RUNNER_TOKEN_PREFIX}#{token}" + end + private scope :with_upgrade_status, ->(upgrade_status) do diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 84e9b6a8df7..55dbaf9c6b7 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -89,15 +89,7 @@ module Clusters delegate :status, to: :provider, allow_nil: true delegate :status_reason, to: :provider, allow_nil: true - delegate :on_creation?, to: :provider, allow_nil: true - delegate :knative_pre_installed?, to: :provider, allow_nil: true - - delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true - delegate :rbac?, to: :platform_kubernetes, prefix: true, allow_nil: true - delegate :available?, to: :application_helm, prefix: true, allow_nil: true - delegate :available?, to: :application_ingress, prefix: true, allow_nil: true - delegate :available?, to: :application_knative, prefix: true, allow_nil: true - delegate :available?, to: :integration_prometheus, prefix: true, allow_nil: true + delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true delegate :external_hostname, to: :application_ingress, prefix: true, allow_nil: true @@ -264,6 +256,38 @@ module Clusters integration_prometheus || build_integration_prometheus end + def on_creation? + !!provider&.on_creation? + end + + def knative_pre_installed? + !!provider&.knative_pre_installed? + end + + def platform_kubernetes_active? + !!platform_kubernetes&.active? + end + + def platform_kubernetes_rbac? + !!platform_kubernetes&.rbac? + end + + def application_helm_available? + !!application_helm&.available? + end + + def application_ingress_available? + !!application_ingress&.available? + end + + def application_knative_available? + !!application_knative&.available? + end + + def integration_prometheus_available? + !!integration_prometheus&.available? + end + def provider if gcp? provider_gcp diff --git a/app/models/group.rb b/app/models/group.rb index c7ad4d61ddb..f48484f04f7 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -422,15 +422,14 @@ class Group < Namespace ) end - def add_member(user, access_level, current_user: nil, expires_at: nil, ldap: false, blocking_refresh: true) + def add_member(user, access_level, current_user: nil, expires_at: nil, ldap: false) Members::Groups::CreatorService.add_member( # rubocop:disable CodeReuse/ServiceClass self, user, access_level, current_user: current_user, expires_at: expires_at, - ldap: ldap, - blocking_refresh: blocking_refresh + ldap: ldap ) end @@ -539,7 +538,6 @@ class Group < Namespace # rubocop: disable CodeReuse/ServiceClass def refresh_members_authorized_projects( - blocking: true, priority: UserProjectAccessChangedService::HIGH_PRIORITY, direct_members_only: false ) @@ -552,7 +550,7 @@ class Group < Namespace UserProjectAccessChangedService .new(user_ids) - .execute(blocking: blocking, priority: priority) + .execute(priority: priority) end # rubocop: enable CodeReuse/ServiceClass @@ -748,7 +746,7 @@ class Group < Namespace end def refresh_project_authorizations - refresh_members_authorized_projects(blocking: false) + refresh_members_authorized_projects end # each existing group needs to have a `runners_token`. diff --git a/app/models/member.rb b/app/models/member.rb index ecf9013f197..e97c9e929ac 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -22,7 +22,6 @@ class Member < ApplicationRecord STATE_AWAITING = 1 attr_accessor :raw_invite_token - attr_writer :blocking_refresh belongs_to :created_by, class_name: "User" belongs_to :user @@ -279,12 +278,8 @@ class Member < ApplicationRecord after_save :log_invitation_token_cleanup after_commit :send_request, if: :request?, unless: :importing?, on: [:create] - after_commit on: [:create, :update], unless: :importing? do - refresh_member_authorized_projects(blocking: blocking_refresh) - end - - after_commit on: [:destroy], unless: :importing? do - refresh_member_authorized_projects(blocking: false) + after_commit on: [:create, :update, :destroy], unless: :importing? do + refresh_member_authorized_projects end attribute :notification_level, default: -> { NotificationSetting.levels[:global] } @@ -555,8 +550,8 @@ class Member < ApplicationRecord # rubocop: disable CodeReuse/ServiceClass # This method is overridden in the test environment, see stubbed_member.rb - def refresh_member_authorized_projects(blocking:) - UserProjectAccessChangedService.new(user_id).execute(blocking: blocking) + def refresh_member_authorized_projects + UserProjectAccessChangedService.new(user_id).execute end # rubocop: enable CodeReuse/ServiceClass @@ -642,12 +637,6 @@ class Member < ApplicationRecord error = StandardError.new("Invitation token is present but invite was already accepted!") Gitlab::ErrorTracking.track_exception(error, attributes.slice(%w["invite_accepted_at created_at source_type source_id user_id id"])) end - - def blocking_refresh - return true if @blocking_refresh.nil? - - @blocking_refresh - end end Member.prepend_mod_with('Member') diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index 796b05b7fff..f23d7208b6e 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -64,7 +64,7 @@ class GroupMember < Member private override :refresh_member_authorized_projects - def refresh_member_authorized_projects(blocking:) + def refresh_member_authorized_projects # Here, `destroyed_by_association` will be present if the # GroupMember is being destroyed due to the `dependent: :destroy` # callback on Group. In this case, there is no need to refresh the diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 6aa6afb595d..733b7c4bc87 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -109,28 +109,24 @@ class ProjectMember < Member end end + # This method is overridden in the test environment, see stubbed_member.rb override :refresh_member_authorized_projects - def refresh_member_authorized_projects(blocking:) + def refresh_member_authorized_projects return unless user - # rubocop:disable CodeReuse/ServiceClass - if blocking - blocking_project_authorizations_refresh - else - AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.perform_async(project.id, user.id) - end + execute_project_authorizations_refresh + # rubocop:disable CodeReuse/ServiceClass # Until we compare the inconsistency rates of the new, specialized service and # the old approach, we still run AuthorizedProjectsWorker # but with some delay and lower urgency as a safety net. UserProjectAccessChangedService.new(user_id) - .execute(blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY) + .execute(priority: UserProjectAccessChangedService::LOW_PRIORITY) # rubocop:enable CodeReuse/ServiceClass end - # This method is overridden in the test environment, see stubbed_member.rb - def blocking_project_authorizations_refresh - AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.bulk_perform_and_wait([[project.id, user.id]]) + def execute_project_authorizations_refresh + AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.perform_async(project.id, user.id) end # TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054 diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 053989d8eb1..a0d44bcc26e 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -660,7 +660,6 @@ class Namespace < ApplicationRecord groups_requiring_authorizations_refresh.find_each do |group| group.refresh_members_authorized_projects( - blocking: false, priority: priority ) end diff --git a/app/models/repository.rb b/app/models/repository.rb index 3fd7b6126d8..4100218944f 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -696,14 +696,22 @@ class Repository end def head_tree(skip_flat_paths: true) - if head_commit + if Feature.enabled?(:optimized_head_tree) + return if empty? || root_ref.nil? + + @head_tree ||= Tree.new(self, root_ref, nil, skip_flat_paths: skip_flat_paths) + elsif head_commit @head_tree ||= Tree.new(self, head_commit.sha, nil, skip_flat_paths: skip_flat_paths) end end def tree(sha = :head, path = nil, recursive: false, skip_flat_paths: true, pagination_params: nil) if sha == :head - return unless head_commit + if Feature.enabled?(:optimized_head_tree) + return if empty? || root_ref.nil? + else + return unless head_commit + end if path.nil? return head_tree(skip_flat_paths: skip_flat_paths) diff --git a/app/services/authorized_project_update/project_access_changed_service.rb b/app/services/authorized_project_update/project_access_changed_service.rb index dafec1fef59..ca039187c50 100644 --- a/app/services/authorized_project_update/project_access_changed_service.rb +++ b/app/services/authorized_project_update/project_access_changed_service.rb @@ -6,16 +6,12 @@ module AuthorizedProjectUpdate @project_ids = Array.wrap(project_ids) end - def execute(blocking: true) + def execute return if @project_ids.empty? bulk_args = @project_ids.map { |id| [id] } - if blocking - AuthorizedProjectUpdate::ProjectRecalculateWorker.bulk_perform_and_wait(bulk_args) - else - AuthorizedProjectUpdate::ProjectRecalculateWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext - end + AuthorizedProjectUpdate::ProjectRecalculateWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext end end end diff --git a/app/services/export_csv/base_service.rb b/app/services/export_csv/base_service.rb new file mode 100644 index 00000000000..21b830d427a --- /dev/null +++ b/app/services/export_csv/base_service.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module ExportCsv + class BaseService + # Target attachment size before base64 encoding + TARGET_FILESIZE = 15.megabytes + + def initialize(relation, resource_parent) + @objects = relation + @resource_parent = resource_parent + end + + def csv_data + csv_builder.render(TARGET_FILESIZE) + end + + def email(user) + raise NotImplementedError + end + + private + + attr_reader :resource_parent, :objects + + # rubocop: disable CodeReuse/ActiveRecord + def csv_builder + @csv_builder ||= + CsvBuilder.new(objects.preload(associations_to_preload), header_to_value_hash) + end + # rubocop: enable CodeReuse/ActiveRecord + + def associations_to_preload + [] + end + + def header_to_value_hash + raise NotImplementedError + end + end +end diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb index 02a760ccf29..45e8972213e 100644 --- a/app/services/groups/destroy_service.rb +++ b/app/services/groups/destroy_service.rb @@ -42,7 +42,7 @@ module Groups if user_ids_for_project_authorizations_refresh.present? UserProjectAccessChangedService .new(user_ids_for_project_authorizations_refresh) - .execute(blocking: true) + .execute end publish_event diff --git a/app/services/groups/group_links/create_service.rb b/app/services/groups/group_links/create_service.rb index 52180c39972..9c1a003ff36 100644 --- a/app/services/groups/group_links/create_service.rb +++ b/app/services/groups/group_links/create_service.rb @@ -31,7 +31,7 @@ module Groups end def setup_authorizations - shared_with_group.refresh_members_authorized_projects(blocking: false, direct_members_only: true) + shared_with_group.refresh_members_authorized_projects(direct_members_only: true) end end end diff --git a/app/services/groups/group_links/destroy_service.rb b/app/services/groups/group_links/destroy_service.rb index d1f16775ab3..dc3cab927be 100644 --- a/app/services/groups/group_links/destroy_service.rb +++ b/app/services/groups/group_links/destroy_service.rb @@ -18,7 +18,7 @@ module Groups groups_to_refresh.uniq.each do |group| next if Feature.enabled?(:skip_group_share_unlink_auth_refresh, group.root_ancestor) - group.refresh_members_authorized_projects(blocking: false, direct_members_only: true) + group.refresh_members_authorized_projects(direct_members_only: true) end else Gitlab::AppLogger.info( diff --git a/app/services/groups/group_links/update_service.rb b/app/services/groups/group_links/update_service.rb index 244ec2254a8..66d0d63cb9b 100644 --- a/app/services/groups/group_links/update_service.rb +++ b/app/services/groups/group_links/update_service.rb @@ -13,7 +13,7 @@ module Groups group_link.update!(group_link_params) if requires_authorization_refresh?(group_link_params) - group_link.shared_with_group.refresh_members_authorized_projects(blocking: false, direct_members_only: true) + group_link.shared_with_group.refresh_members_authorized_projects(direct_members_only: true) end end diff --git a/app/services/issuable/export_csv/base_service.rb b/app/services/issuable/export_csv/base_service.rb deleted file mode 100644 index 49ff05935c9..00000000000 --- a/app/services/issuable/export_csv/base_service.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -module Issuable - module ExportCsv - class BaseService - # Target attachment size before base64 encoding - TARGET_FILESIZE = 15.megabytes - - def initialize(issuables_relation, project) - @issuables = issuables_relation - @project = project - end - - def csv_data - csv_builder.render(TARGET_FILESIZE) - end - - private - - attr_reader :project, :issuables - - # rubocop: disable CodeReuse/ActiveRecord - def csv_builder - @csv_builder ||= - CsvBuilder.new(issuables.preload(associations_to_preload), header_to_value_hash) - end - # rubocop: enable CodeReuse/ActiveRecord - - def associations_to_preload - [] - end - - def header_to_value_hash - raise NotImplementedError - end - end - end -end diff --git a/app/services/issues/export_csv_service.rb b/app/services/issues/export_csv_service.rb index 46e4b865dc3..9efded4aa43 100644 --- a/app/services/issues/export_csv_service.rb +++ b/app/services/issues/export_csv_service.rb @@ -1,18 +1,18 @@ # frozen_string_literal: true module Issues - class ExportCsvService < Issuable::ExportCsv::BaseService + class ExportCsvService < ExportCsv::BaseService include Gitlab::Routing.url_helpers include GitlabRoutingHelper - def initialize(issuables_relation, project, user = nil) - super(issuables_relation, project) + def initialize(relation, resource_parent, user = nil) + super(relation, resource_parent) - @labels = @issuables.labels_hash.transform_values { |labels| labels.sort.join(',').presence } + @labels = objects.labels_hash.transform_values { |labels| labels.sort.join(',').presence } end def email(mail_to_user) - Notify.issues_csv_email(mail_to_user, project, csv_data, csv_builder.status).deliver_now + Notify.issues_csv_email(mail_to_user, resource_parent, csv_data, csv_builder.status).deliver_now end private diff --git a/app/services/members/creator_service.rb b/app/services/members/creator_service.rb index 2d378a64c02..3ce8390d07d 100644 --- a/app/services/members/creator_service.rb +++ b/app/services/members/creator_service.rb @@ -21,8 +21,7 @@ module Members expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil, - ldap: nil, - blocking_refresh: nil + ldap: nil ) return [] unless invitees.present? @@ -40,8 +39,7 @@ module Members expires_at: expires_at, tasks_to_be_done: tasks_to_be_done, tasks_project_id: tasks_project_id, - ldap: ldap, - blocking_refresh: blocking_refresh + ldap: ldap } members = emails.map do |email| @@ -62,16 +60,14 @@ module Members access_level, current_user: nil, expires_at: nil, - ldap: nil, - blocking_refresh: nil + ldap: nil ) add_members(source, [invitee], access_level, current_user: current_user, expires_at: expires_at, - ldap: ldap, - blocking_refresh: blocking_refresh).first + ldap: ldap).first end private @@ -250,8 +246,6 @@ module Members def find_or_build_member @member = builder.new(source, invitee, existing_members).execute - - @member.blocking_refresh = args[:blocking_refresh] end def ldap diff --git a/app/services/merge_requests/export_csv_service.rb b/app/services/merge_requests/export_csv_service.rb index 1f8dec69ef0..96b4cdd0fe5 100644 --- a/app/services/merge_requests/export_csv_service.rb +++ b/app/services/merge_requests/export_csv_service.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true module MergeRequests - class ExportCsvService < Issuable::ExportCsv::BaseService + class ExportCsvService < ExportCsv::BaseService include Gitlab::Routing.url_helpers include GitlabRoutingHelper def email(user) - Notify.merge_requests_csv_email(user, project, csv_data, csv_builder.status).deliver_now + Notify.merge_requests_csv_email(user, resource_parent, csv_data, csv_builder.status).deliver_now end private diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index e1959ec09b5..e057e6aba51 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -160,7 +160,6 @@ module Projects # AuthorizedProjectsWorker but with some delay and lower urgency as a # safety net. @project.group.refresh_members_authorized_projects( - blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY ) else diff --git a/app/services/projects/group_links/create_service.rb b/app/services/projects/group_links/create_service.rb index 72036aaff35..f77bae71d63 100644 --- a/app/services/projects/group_links/create_service.rb +++ b/app/services/projects/group_links/create_service.rb @@ -36,7 +36,6 @@ module Projects # AuthorizedProjectsWorker but with some delay and lower urgency as a # safety net. shared_with_group.refresh_members_authorized_projects( - blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY ) end diff --git a/app/services/projects/group_links/destroy_service.rb b/app/services/projects/group_links/destroy_service.rb index 19df0dc2c73..a2307bfebf0 100644 --- a/app/services/projects/group_links/destroy_service.rb +++ b/app/services/projects/group_links/destroy_service.rb @@ -19,7 +19,6 @@ module Projects # the old approach, we still run AuthorizedProjectsWorker # but with some delay and lower urgency as a safety net. link.group.refresh_members_authorized_projects( - blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY ) end diff --git a/app/services/projects/group_links/update_service.rb b/app/services/projects/group_links/update_service.rb index c271b0a2307..9b2565adaca 100644 --- a/app/services/projects/group_links/update_service.rb +++ b/app/services/projects/group_links/update_service.rb @@ -26,7 +26,6 @@ module Projects # the old approach, we still run AuthorizedProjectsWorker # but with some delay and lower urgency as a safety net. group_link.group.refresh_members_authorized_projects( - blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY ) end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 6fca49aa3d0..ed99c69be07 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -192,7 +192,6 @@ module Projects # the old approach, we still run AuthorizedProjectsWorker # but with some delay and lower urgency as a safety net. UserProjectAccessChangedService.new(user_ids).execute( - blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY ) end diff --git a/app/services/user_project_access_changed_service.rb b/app/services/user_project_access_changed_service.rb index f7178ee9bb6..9f811bb699c 100644 --- a/app/services/user_project_access_changed_service.rb +++ b/app/services/user_project_access_changed_service.rb @@ -12,28 +12,24 @@ class UserProjectAccessChangedService @user_ids = Array.wrap(user_ids) end - def execute(blocking: true, priority: HIGH_PRIORITY) + def execute(priority: HIGH_PRIORITY) return if @user_ids.empty? bulk_args = @user_ids.map { |id| [id] } result = - if blocking - AuthorizedProjectsWorker.bulk_perform_and_wait(bulk_args) - else - case priority - when HIGH_PRIORITY - AuthorizedProjectsWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext - when MEDIUM_PRIORITY - AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker.bulk_perform_in(MEDIUM_DELAY, bulk_args, batch_size: 100, batch_delay: 30.seconds) # rubocop:disable Scalability/BulkPerformWithContext - else - with_related_class_context do - # We wrap the execution in `with_related_class_context`so as to obtain - # the location of the original caller - # in jobs enqueued from within `AuthorizedProjectUpdate::UserRefreshFromReplicaWorker` - AuthorizedProjectUpdate::UserRefreshFromReplicaWorker.bulk_perform_in( # rubocop:disable Scalability/BulkPerformWithContext - DELAY, bulk_args, batch_size: 100, batch_delay: 30.seconds) - end + case priority + when HIGH_PRIORITY + AuthorizedProjectsWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext + when MEDIUM_PRIORITY + AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker.bulk_perform_in(MEDIUM_DELAY, bulk_args, batch_size: 100, batch_delay: 30.seconds) # rubocop:disable Scalability/BulkPerformWithContext + when LOW_PRIORITY + with_related_class_context do + # We wrap the execution in `with_related_class_context`so as to obtain + # the location of the original caller + # in jobs enqueued from within `AuthorizedProjectUpdate::UserRefreshFromReplicaWorker` + AuthorizedProjectUpdate::UserRefreshFromReplicaWorker.bulk_perform_in( # rubocop:disable Scalability/BulkPerformWithContext + DELAY, bulk_args, batch_size: 100, batch_delay: 30.seconds) end end diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 677e2bd6007..712f987a783 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -13,7 +13,7 @@ = render 'shared/new_project_item_vue_select' .top-area - = render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set + = render 'shared/issuable/nav', type: :merge_requests, display_count: !(@no_filters_set || @search_timeout_occurred) = render 'shared/issuable/search_bar', type: :merge_requests, disable_target_branch: true diff --git a/app/views/protected_branches/shared/_branches_list.html.haml b/app/views/protected_branches/shared/_branches_list.html.haml index c35895e000c..8235411d240 100644 --- a/app/views/protected_branches/shared/_branches_list.html.haml +++ b/app/views/protected_branches/shared/_branches_list.html.haml @@ -22,7 +22,7 @@ %th = s_("ProtectedBranch|Allowed to merge") %th - = s_("ProtectedBranch|Allowed to push") + = s_("ProtectedBranch|Allowed to push and merge") %th = s_("ProtectedBranch|Allowed to force push") %span.has-tooltip{ data: { container: 'body' }, title: s_('ProtectedBranch|Allow all users with push access to force push.'), 'aria-hidden': 'true' } diff --git a/app/views/protected_branches/shared/_create_protected_branch.html.haml b/app/views/protected_branches/shared/_create_protected_branch.html.haml index 315daa5e029..109d92af8a7 100644 --- a/app/views/protected_branches/shared/_create_protected_branch.html.haml +++ b/app/views/protected_branches/shared/_create_protected_branch.html.haml @@ -25,7 +25,7 @@ .col-sm-12 = yield :merge_access_levels .form-group.row - = f.label :push_access_levels_attributes, s_("ProtectedBranch|Allowed to push:"), class: 'col-sm-12' + = f.label :push_access_levels_attributes, s_("ProtectedBranch|Allowed to push and merge:"), class: 'col-sm-12' .col-sm-12 = yield :push_access_levels .form-group.row diff --git a/app/workers/concerns/waitable_worker.rb b/app/workers/concerns/waitable_worker.rb index f23e3fb20c2..1fe950b7570 100644 --- a/app/workers/concerns/waitable_worker.rb +++ b/app/workers/concerns/waitable_worker.rb @@ -3,13 +3,6 @@ module WaitableWorker extend ActiveSupport::Concern - class_methods do - # Schedules multiple jobs and waits for them to be completed. - def bulk_perform_and_wait(args_list) - bulk_perform_async(args_list) - end - end - def perform(*args) notify_key = args.pop if Gitlab::JobWaiter.key?(args.last) diff --git a/config/feature_flags/development/optimized_head_tree.yml b/config/feature_flags/development/optimized_head_tree.yml new file mode 100644 index 00000000000..144a1d967dd --- /dev/null +++ b/config/feature_flags/development/optimized_head_tree.yml @@ -0,0 +1,8 @@ +--- +name: optimized_head_tree +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110248 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/389448 +milestone: '15.9' +type: development +group: group::source code +default_enabled: false diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index 41387c655c0..e0ca9774706 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -110,6 +110,7 @@ The user must not be assigned any other role, anywhere in the instance. [a set of permissions](../../user/permissions.md#project-members-permissions). - If your project is public, all users, including those with the Guest role can access your project. +- A user's highest assigned role is updated asynchronously and may take some time to update. NOTE: If a user creates a project, they are assigned the Maintainer or Owner role. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b38fd2f85a9..f2765a5af91 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -7037,10 +7037,10 @@ msgstr "" msgid "BranchRules|Allowed to merge (%{total})" msgstr "" -msgid "BranchRules|Allowed to push" +msgid "BranchRules|Allowed to push and merge" msgstr "" -msgid "BranchRules|Allowed to push (%{total})" +msgid "BranchRules|Allowed to push and merge (%{total})" msgstr "" msgid "BranchRules|An error occurred while fetching branches." @@ -34202,10 +34202,10 @@ msgstr "" msgid "ProtectedBranch|Allowed to merge:" msgstr "" -msgid "ProtectedBranch|Allowed to push" +msgid "ProtectedBranch|Allowed to push and merge" msgstr "" -msgid "ProtectedBranch|Allowed to push:" +msgid "ProtectedBranch|Allowed to push and merge:" msgstr "" msgid "ProtectedBranch|An error occurred while loading branch rules. Please try again." diff --git a/qa/qa/tools/ci/test_results.rb b/qa/qa/tools/ci/test_results.rb deleted file mode 100644 index 635b69f6ca0..00000000000 --- a/qa/qa/tools/ci/test_results.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: true - -module QA - module Tools - module Ci - class TestResults - include Helpers - - def initialize(pipeline_name, test_report_job_name, report_path) - @pipeline_name = pipeline_name - @test_report_job_name = test_report_job_name - @report_path = report_path - end - - # Get test report artifacts from downstream pipeline - # - # @param [String] pipeline_name - # @param [String] test_report_job_name - # @param [String] report_path - # @return [void] - def self.get(pipeline_name, test_report_job_name, report_path) - new(pipeline_name, test_report_job_name, report_path).download_test_results - end - - # Download test results from child pipeline - # - # @return [void] - def download_test_results - logger.info("Fetching test results for '#{pipeline_name}'") - - logger.debug(" fetching pipeline id of '#{pipeline_name}' child pipeline") - downstream_pipeline_id = api_get("#{pipelines_url(pipeline_id)}/bridges") - .find { |bridge| bridge[:name] == pipeline_name } - &.dig(:downstream_pipeline, :id) - return logger.error("Child pipeline '#{pipeline_name}' not found!") unless downstream_pipeline_id - - logger.debug(" fetching job id of test report job") - job_id = api_get("#{pipelines_url(downstream_pipeline_id)}/jobs") - .find { |job| job[:name] == test_report_job_name } - &.fetch(:id) - return logger.error("Test report job '#{test_report_job_name}' not found!") unless job_id - - logger.debug(" fetching test results artifact archive") - response = api_get("/projects/#{project_id}/jobs/#{job_id}/artifacts", raw_response: true) - - logger.info("Extracting test result archive") - system("unzip", "-o", "-d", report_path, response.file.path) - end - - private - - attr_reader :pipeline_name, :test_report_job_name, :report_path - - # Base get pipeline url - # - # @param [Integer] id - # @return [String] - def pipelines_url(id) - "/projects/#{project_id}/pipelines/#{id}" - end - - # Current pipeline id - # - # @return [String] - def pipeline_id - ENV["CI_PIPELINE_ID"] - end - - # Current project id - # - # @return [String] - def project_id - ENV["CI_PROJECT_ID"] - end - end - end - end -end diff --git a/qa/tasks/ci.rake b/qa/tasks/ci.rake index 84a26e3e555..bfb364aa5ee 100644 --- a/qa/tasks/ci.rake +++ b/qa/tasks/ci.rake @@ -54,11 +54,6 @@ namespace :ci do append_to_file(env_file, "QA_FEATURE_FLAGS='#{feature_flags}'") end - desc "Download test results from downstream pipeline" - task :download_test_results, [:trigger_name, :test_report_job_name, :report_path] do |_, args| - QA::Tools::Ci::TestResults.get(args[:trigger_name], args[:test_report_job_name], args[:report_path]) - end - desc "Export test run metrics to influxdb" task :export_test_metrics, [:glob] do |_, args| raise("Metrics file glob pattern is required") unless args[:glob] diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb index 1b5a8c0807c..ea6aae0fe61 100644 --- a/spec/controllers/dashboard_controller_spec.rb +++ b/spec/controllers/dashboard_controller_spec.rb @@ -69,6 +69,13 @@ RSpec.describe DashboardController, feature_category: :code_review_workflow do expect(response.body).to have_content('Too many results to display. Edit your search or add a filter.') end + + it 'does not display MR counts in nav' do + get :merge_requests, params: { author_id: user.id } + + expect(response.body).to have_content('Open Merged Closed All') + expect(response.body).not_to have_content('Open 0 Merged 0 Closed 0 All 0') + end end it 'logs the exception' do @@ -77,6 +84,19 @@ RSpec.describe DashboardController, feature_category: :code_review_workflow do get :merge_requests, params: { author_id: user.id } end end + + context 'when an ActiveRecord::QueryCanceled is not raised' do + context 'rendering views' do + render_views + + it 'displays MR counts in nav' do + get :merge_requests, params: { author_id: user.id } + + expect(response.body).to have_content('Open 0 Merged 0 Closed 0 All 0') + expect(response.body).not_to have_content('Open Merged Closed All') + end + end + end end end diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb index 4758986b47c..860322075e2 100644 --- a/spec/factories/ci/runners.rb +++ b/spec/factories/ci/runners.rb @@ -58,6 +58,10 @@ FactoryBot.define do end end + trait :created_in_ui do + legacy_registered { false } + end + trait :without_projects do # we use that to create invalid runner: # the one without projects diff --git a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js index a0ec2069ca8..7fc240e520b 100644 --- a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js +++ b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js @@ -39,6 +39,7 @@ import { I18N_GROUP_TYPE, I18N_PROJECT_TYPE, INSTANCE_TYPE, + JOBS_ROUTE_PATH, PARAM_KEY_PAUSED, PARAM_KEY_STATUS, PARAM_KEY_TAG, @@ -282,11 +283,14 @@ describe('AdminRunnersApp', () => { it('Shows job status and links to jobs', () => { const badge = wrapper - .find('tr [data-testid="td-summary"]') + .find('tr [data-testid="td-status"]') .findComponent(RunnerJobStatusBadge); expect(badge.props('jobStatus')).toBe(mockRunners[0].jobExecutionStatus); - expect(badge.attributes('href')).toBe(`http://localhost/admin/runners/${id}#/jobs`); + + const badgeHref = new URL(badge.attributes('href')); + expect(badgeHref.pathname).toBe(`/admin/runners/${id}`); + expect(badgeHref.hash).toBe(`#${JOBS_ROUTE_PATH}`); }); it('When runner is paused or unpaused, some data is refetched', async () => { diff --git a/spec/frontend/ci/runner/components/cells/runner_status_cell_spec.js b/spec/frontend/ci/runner/components/cells/runner_status_cell_spec.js index 2fb824a8fa5..1ff60ff1a9d 100644 --- a/spec/frontend/ci/runner/components/cells/runner_status_cell_spec.js +++ b/spec/frontend/ci/runner/components/cells/runner_status_cell_spec.js @@ -10,6 +10,7 @@ import { INSTANCE_TYPE, STATUS_ONLINE, STATUS_OFFLINE, + JOB_STATUS_IDLE, } from '~/ci/runner/constants'; describe('RunnerStatusCell', () => { @@ -18,16 +19,18 @@ describe('RunnerStatusCell', () => { const findStatusBadge = () => wrapper.findComponent(RunnerStatusBadge); const findPausedBadge = () => wrapper.findComponent(RunnerPausedBadge); - const createComponent = ({ runner = {} } = {}) => { + const createComponent = ({ runner = {}, ...options } = {}) => { wrapper = mount(RunnerStatusCell, { propsData: { runner: { runnerType: INSTANCE_TYPE, active: true, status: STATUS_ONLINE, + jobExecutionStatus: JOB_STATUS_IDLE, ...runner, }, }, + ...options, }); }; @@ -74,4 +77,14 @@ describe('RunnerStatusCell', () => { expect(wrapper.text()).toBe(''); }); + + it('Displays "runner-job-status-badge" slot', () => { + createComponent({ + scopedSlots: { + 'runner-job-status-badge': ({ runner }) => `Job status ${runner.jobExecutionStatus}`, + }, + }); + + expect(wrapper.text()).toContain(`Job status ${JOB_STATUS_IDLE}`); + }); }); diff --git a/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js b/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js index 10280c77303..1711df42491 100644 --- a/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js +++ b/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js @@ -3,7 +3,6 @@ import { mountExtended } from 'helpers/vue_test_utils_helper'; import RunnerSummaryCell from '~/ci/runner/components/cells/runner_summary_cell.vue'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import RunnerTags from '~/ci/runner/components/runner_tags.vue'; -import RunnerJobStatusBadge from '~/ci/runner/components/runner_job_status_badge.vue'; import RunnerSummaryField from '~/ci/runner/components/cells/runner_summary_field.vue'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; @@ -22,7 +21,6 @@ describe('RunnerTypeCell', () => { let wrapper; const findLockIcon = () => wrapper.findByTestId('lock-icon'); - const findRunnerJobStatusBadge = () => wrapper.findComponent(RunnerJobStatusBadge); const findRunnerTags = () => wrapper.findComponent(RunnerTags); const findRunnerSummaryField = (icon) => wrapper.findAllComponents(RunnerSummaryField).filter((w) => w.props('icon') === icon) @@ -95,10 +93,6 @@ describe('RunnerTypeCell', () => { expect(wrapper.text()).toContain(I18N_NO_DESCRIPTION); }); - it('Displays job execution status', () => { - expect(findRunnerJobStatusBadge().props('jobStatus')).toBe(mockRunner.jobExecutionStatus); - }); - it('Displays last contact', () => { createComponent({ contactedAt: '2022-01-02', @@ -166,14 +160,14 @@ describe('RunnerTypeCell', () => { expect(findRunnerTags().props('tagList')).toEqual(['shell', 'linux']); }); - it.each(['runner-name', 'runner-job-status-badge'])('Displays a custom "%s" slot', (slotName) => { + it('Displays a custom runner-name slot', () => { const slotContent = 'My custom runner name'; createComponent( {}, { slots: { - [slotName]: slotContent, + 'runner-name': slotContent, }, }, ); diff --git a/spec/frontend/ci/runner/components/runner_details_tabs_spec.js b/spec/frontend/ci/runner/components/runner_details_tabs_spec.js index a9a7dfd4e8f..a59c5a21377 100644 --- a/spec/frontend/ci/runner/components/runner_details_tabs_spec.js +++ b/spec/frontend/ci/runner/components/runner_details_tabs_spec.js @@ -5,7 +5,7 @@ import VueApollo from 'vue-apollo'; import setWindowLocation from 'helpers/set_window_location_helper'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import { I18N_DETAILS, I18N_JOBS } from '~/ci/runner/constants'; +import { JOBS_ROUTE_PATH, I18N_DETAILS, I18N_JOBS } from '~/ci/runner/constants'; import RunnerDetailsTabs from '~/ci/runner/components/runner_details_tabs.vue'; import RunnerDetails from '~/ci/runner/components/runner_details.vue'; @@ -59,7 +59,7 @@ describe('RunnerDetailsTabs', () => { }); it('shows runner jobs', async () => { - setWindowLocation('#/jobs'); + setWindowLocation(`#${JOBS_ROUTE_PATH}`); await createComponent({ mountFn: mountExtended }); diff --git a/spec/frontend/ci/runner/components/runner_job_status_badge_spec.js b/spec/frontend/ci/runner/components/runner_job_status_badge_spec.js index 015bebf40e3..c4476d01386 100644 --- a/spec/frontend/ci/runner/components/runner_job_status_badge_spec.js +++ b/spec/frontend/ci/runner/components/runner_job_status_badge_spec.js @@ -23,16 +23,25 @@ describe('RunnerTypeBadge', () => { }; it.each` - jobStatus | classes | text - ${JOB_STATUS_RUNNING} | ${['gl-mr-3', 'gl-bg-transparent!', 'gl-text-blue-600!', 'gl-border', 'gl-border-blue-600!']} | ${I18N_JOB_STATUS_RUNNING} - ${JOB_STATUS_IDLE} | ${['gl-mr-3', 'gl-bg-transparent!', 'gl-text-gray-700!', 'gl-border', 'gl-border-gray-500!']} | ${I18N_JOB_STATUS_IDLE} + jobStatus | classes | text + ${JOB_STATUS_RUNNING} | ${['gl-text-blue-600!', 'gl-border-blue-600!']} | ${I18N_JOB_STATUS_RUNNING} + ${JOB_STATUS_IDLE} | ${['gl-text-gray-700!', 'gl-border-gray-500!']} | ${I18N_JOB_STATUS_IDLE} `( 'renders $jobStatus job status with "$text" text and styles', ({ jobStatus, classes, text }) => { createComponent({ props: { jobStatus } }); - expect(findBadge().props()).toMatchObject({ size: 'sm', variant: 'muted' }); - expect(findBadge().classes().sort()).toEqual(classes.sort()); + expect(findBadge().props()).toMatchObject({ size: 'md', variant: 'muted' }); + expect(findBadge().classes().sort()).toEqual( + [ + ...classes, + 'gl-border', + 'gl-display-inline-block', + 'gl-max-w-full', + 'gl-text-truncate', + 'gl-bg-transparent!', + ].sort(), + ); expect(findBadge().text()).toBe(text); }, ); diff --git a/spec/frontend/ci/runner/components/runner_list_spec.js b/spec/frontend/ci/runner/components/runner_list_spec.js index 1267d045623..2e5d1dbd063 100644 --- a/spec/frontend/ci/runner/components/runner_list_spec.js +++ b/spec/frontend/ci/runner/components/runner_list_spec.js @@ -177,30 +177,30 @@ describe('RunnerList', () => { }); describe('Scoped cell slots', () => { - it('Render #runner-name slot in "summary" cell', () => { + it('Render #runner-job-status-badge slot in "status" cell', () => { createComponent( { - scopedSlots: { 'runner-name': ({ runner }) => `Summary: ${runner.id}` }, + scopedSlots: { + 'runner-job-status-badge': ({ runner }) => `Job status ${runner.jobExecutionStatus}`, + }, }, mountExtended, ); - expect(findCell({ fieldKey: 'summary' }).text()).toContain(`Summary: ${mockRunners[0].id}`); + expect(findCell({ fieldKey: 'status' }).text()).toContain( + `Job status ${mockRunners[0].jobExecutionStatus}`, + ); }); - it('Render #runner-job-status-badge slot in "summary" cell', () => { + it('Render #runner-name slot in "summary" cell', () => { createComponent( { - scopedSlots: { - 'runner-job-status-badge': ({ runner }) => `Job status ${runner.jobExecutionStatus}`, - }, + scopedSlots: { 'runner-name': ({ runner }) => `Summary: ${runner.id}` }, }, mountExtended, ); - expect(findCell({ fieldKey: 'summary' }).text()).toContain( - `Job status ${mockRunners[0].jobExecutionStatus}`, - ); + expect(findCell({ fieldKey: 'summary' }).text()).toContain(`Summary: ${mockRunners[0].id}`); }); it('Render #runner-actions-cell slot in "actions" cell', () => { diff --git a/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js b/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js index 3e07523eed6..39ea5cade28 100644 --- a/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js +++ b/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js @@ -25,6 +25,7 @@ import RunnerActionsCell from '~/ci/runner/components/cells/runner_actions_cell. import RegistrationDropdown from '~/ci/runner/components/registration/registration_dropdown.vue'; import RunnerPagination from '~/ci/runner/components/runner_pagination.vue'; import RunnerMembershipToggle from '~/ci/runner/components/runner_membership_toggle.vue'; +import RunnerJobStatusBadge from '~/ci/runner/components/runner_job_status_badge.vue'; import { CREATED_ASC, @@ -35,6 +36,7 @@ import { I18N_STATUS_STALE, INSTANCE_TYPE, GROUP_TYPE, + JOBS_ROUTE_PATH, PARAM_KEY_PAUSED, PARAM_KEY_STATUS, PARAM_KEY_TAG, @@ -253,7 +255,7 @@ describe('GroupRunnersApp', () => { let showToast; const { webUrl, editUrl, node } = mockGroupRunnersEdges[0]; - const { id: graphqlId, shortSha } = node; + const { id: graphqlId, shortSha, jobExecutionStatus } = node; const id = getIdFromGraphQLId(graphqlId); const COUNT_QUERIES = 6; // Smart queries that display a filtered count of runners const FILTERED_COUNT_QUERIES = 6; // Smart queries that display a count of runners in tabs and single stats @@ -263,6 +265,13 @@ describe('GroupRunnersApp', () => { showToast = jest.spyOn(wrapper.vm.$root.$toast, 'show'); }); + it('Shows job status and links to jobs', () => { + const badge = findRunnerRow(id).findByTestId('td-status').findComponent(RunnerJobStatusBadge); + + expect(badge.props('jobStatus')).toBe(jobExecutionStatus); + expect(badge.attributes('href')).toBe(`${webUrl}#${JOBS_ROUTE_PATH}`); + }); + it('view link is displayed correctly', () => { const viewLink = findRunnerRow(id).findByTestId('td-summary').findComponent(GlLink); diff --git a/spec/frontend/issues/dashboard/components/issues_dashboard_app_spec.js b/spec/frontend/issues/dashboard/components/issues_dashboard_app_spec.js index aea90a26d7f..db1986d1037 100644 --- a/spec/frontend/issues/dashboard/components/issues_dashboard_app_spec.js +++ b/spec/frontend/issues/dashboard/components/issues_dashboard_app_spec.js @@ -28,9 +28,12 @@ import { scrollUp } from '~/lib/utils/scroll_utils'; import { TOKEN_TYPE_ASSIGNEE, TOKEN_TYPE_AUTHOR, + TOKEN_TYPE_CONFIDENTIAL, TOKEN_TYPE_LABEL, TOKEN_TYPE_MILESTONE, TOKEN_TYPE_MY_REACTION, + TOKEN_TYPE_SEARCH_WITHIN, + TOKEN_TYPE_TYPE, } from '~/vue_shared/components/filtered_search_bar/constants'; import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue'; import { IssuableStates } from '~/vue_shared/issuable/list/constants'; @@ -355,9 +358,12 @@ describe('IssuesDashboardApp component', () => { expect(findIssuableList().props('searchTokens')).toMatchObject([ { type: TOKEN_TYPE_ASSIGNEE, preloadedUsers }, { type: TOKEN_TYPE_AUTHOR, preloadedUsers }, + { type: TOKEN_TYPE_CONFIDENTIAL }, { type: TOKEN_TYPE_LABEL }, { type: TOKEN_TYPE_MILESTONE }, { type: TOKEN_TYPE_MY_REACTION }, + { type: TOKEN_TYPE_SEARCH_WITHIN }, + { type: TOKEN_TYPE_TYPE }, ]); }); }); diff --git a/spec/lib/banzai/color_parser_spec.rb b/spec/lib/banzai/color_parser_spec.rb index 3914aee2d4c..5647a81675e 100644 --- a/spec/lib/banzai/color_parser_spec.rb +++ b/spec/lib/banzai/color_parser_spec.rb @@ -2,7 +2,7 @@ require 'fast_spec_helper' -RSpec.describe Banzai::ColorParser do +RSpec.describe Banzai::ColorParser, feature_category: :team_planning do describe '.parse' do context 'HEX format' do [ diff --git a/spec/lib/banzai/commit_renderer_spec.rb b/spec/lib/banzai/commit_renderer_spec.rb index a10dd6eb3a2..35e0e20582d 100644 --- a/spec/lib/banzai/commit_renderer_spec.rb +++ b/spec/lib/banzai/commit_renderer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::CommitRenderer do +RSpec.describe Banzai::CommitRenderer, feature_category: :source_code_management do describe '.render', :clean_gitlab_redis_cache do it 'renders a commit description and title' do user = build(:user) diff --git a/spec/lib/banzai/cross_project_reference_spec.rb b/spec/lib/banzai/cross_project_reference_spec.rb index 8748a910003..1c861068f16 100644 --- a/spec/lib/banzai/cross_project_reference_spec.rb +++ b/spec/lib/banzai/cross_project_reference_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::CrossProjectReference do +RSpec.describe Banzai::CrossProjectReference, feature_category: :team_planning do let(:including_class) { Class.new.include(described_class).new } let(:reference_cache) { Banzai::Filter::References::ReferenceCache.new(including_class, {}, {}) } diff --git a/spec/lib/banzai/filter/absolute_link_filter_spec.rb b/spec/lib/banzai/filter/absolute_link_filter_spec.rb index 0c159e8bac8..3e7678e3f9a 100644 --- a/spec/lib/banzai/filter/absolute_link_filter_spec.rb +++ b/spec/lib/banzai/filter/absolute_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::AbsoluteLinkFilter do +RSpec.describe Banzai::Filter::AbsoluteLinkFilter, feature_category: :team_planning do def filter(doc, context = {}) described_class.call(doc, context) end diff --git a/spec/lib/banzai/filter/ascii_doc_post_processing_filter_spec.rb b/spec/lib/banzai/filter/ascii_doc_post_processing_filter_spec.rb index 7af22ea7db1..3bd48bdd6f7 100644 --- a/spec/lib/banzai/filter/ascii_doc_post_processing_filter_spec.rb +++ b/spec/lib/banzai/filter/ascii_doc_post_processing_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::AsciiDocPostProcessingFilter do +RSpec.describe Banzai::Filter::AsciiDocPostProcessingFilter, feature_category: :wiki do include FilterSpecHelper it "adds class for elements with data-math-style" do diff --git a/spec/lib/banzai/filter/ascii_doc_sanitization_filter_spec.rb b/spec/lib/banzai/filter/ascii_doc_sanitization_filter_spec.rb index 272b4386ec8..1a76b58bc43 100644 --- a/spec/lib/banzai/filter/ascii_doc_sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/ascii_doc_sanitization_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::AsciiDocSanitizationFilter do +RSpec.describe Banzai::Filter::AsciiDocSanitizationFilter, feature_category: :wiki do include FilterSpecHelper it 'preserves footnotes refs' do diff --git a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb index 81aa8d35ebc..004c70c28f1 100644 --- a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb +++ b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::AssetProxyFilter do +RSpec.describe Banzai::Filter::AssetProxyFilter, feature_category: :team_planning do include FilterSpecHelper def image(path) diff --git a/spec/lib/banzai/filter/audio_link_filter_spec.rb b/spec/lib/banzai/filter/audio_link_filter_spec.rb index 71e069eb29f..38d1ed40a84 100644 --- a/spec/lib/banzai/filter/audio_link_filter_spec.rb +++ b/spec/lib/banzai/filter/audio_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::AudioLinkFilter do +RSpec.describe Banzai::Filter::AudioLinkFilter, feature_category: :team_planning do def filter(doc, contexts = {}) contexts.reverse_merge!({ project: project diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb index 75108130602..2c75377ec42 100644 --- a/spec/lib/banzai/filter/autolink_filter_spec.rb +++ b/spec/lib/banzai/filter/autolink_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::AutolinkFilter do +RSpec.describe Banzai::Filter::AutolinkFilter, feature_category: :team_planning do include FilterSpecHelper let(:link) { 'http://about.gitlab.com/' } diff --git a/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb index 5712ed7da1f..a0846f2b388 100644 --- a/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb +++ b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::BlockquoteFenceFilter do +RSpec.describe Banzai::Filter::BlockquoteFenceFilter, feature_category: :team_planning do include FilterSpecHelper it 'converts blockquote fences to blockquote lines' do diff --git a/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb b/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb index c581750d2a9..fc88c5539ca 100644 --- a/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb +++ b/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::BroadcastMessagePlaceholdersFilter do +RSpec.describe Banzai::Filter::BroadcastMessagePlaceholdersFilter, feature_category: :team_planning do include FilterSpecHelper subject { filter(text, current_user: user, broadcast_message_placeholders: true).to_html } diff --git a/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb b/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb index 67b480f8973..3b054862a26 100644 --- a/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::BroadcastMessageSanitizationFilter do +RSpec.describe Banzai::Filter::BroadcastMessageSanitizationFilter, feature_category: :team_planning do include FilterSpecHelper it_behaves_like 'default allowlist' diff --git a/spec/lib/banzai/filter/color_filter_spec.rb b/spec/lib/banzai/filter/color_filter_spec.rb index dced3671323..9a3f765b869 100644 --- a/spec/lib/banzai/filter/color_filter_spec.rb +++ b/spec/lib/banzai/filter/color_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::ColorFilter, lib: true do +RSpec.describe Banzai::Filter::ColorFilter, feature_category: :team_planning, lib: true do include FilterSpecHelper let(:color) { '#F00' } diff --git a/spec/lib/banzai/filter/custom_emoji_filter_spec.rb b/spec/lib/banzai/filter/custom_emoji_filter_spec.rb index 6e29b910a6c..7fd25eac81b 100644 --- a/spec/lib/banzai/filter/custom_emoji_filter_spec.rb +++ b/spec/lib/banzai/filter/custom_emoji_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::CustomEmojiFilter do +RSpec.describe Banzai::Filter::CustomEmojiFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:group) { create(:group) } diff --git a/spec/lib/banzai/filter/emoji_filter_spec.rb b/spec/lib/banzai/filter/emoji_filter_spec.rb index d621f63211b..1950b0f8bfe 100644 --- a/spec/lib/banzai/filter/emoji_filter_spec.rb +++ b/spec/lib/banzai/filter/emoji_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::EmojiFilter do +RSpec.describe Banzai::Filter::EmojiFilter, feature_category: :team_planning do include FilterSpecHelper it_behaves_like 'emoji filter' do diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb index 036817834d5..3f72896939d 100644 --- a/spec/lib/banzai/filter/external_link_filter_spec.rb +++ b/spec/lib/banzai/filter/external_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.shared_examples 'an external link with rel attribute' do +RSpec.shared_examples 'an external link with rel attribute', feature_category: :team_planning do it 'adds rel="nofollow" to external links' do expect(doc.at_css('a')).to have_attribute('rel') expect(doc.at_css('a')['rel']).to include 'nofollow' diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb index 26bca571fdc..4b765191449 100644 --- a/spec/lib/banzai/filter/footnote_filter_spec.rb +++ b/spec/lib/banzai/filter/footnote_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::FootnoteFilter do +RSpec.describe Banzai::Filter::FootnoteFilter, feature_category: :team_planning do include FilterSpecHelper using RSpec::Parameterized::TableSyntax diff --git a/spec/lib/banzai/filter/front_matter_filter_spec.rb b/spec/lib/banzai/filter/front_matter_filter_spec.rb index f3543ab9582..b15f3ad2cd6 100644 --- a/spec/lib/banzai/filter/front_matter_filter_spec.rb +++ b/spec/lib/banzai/filter/front_matter_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::FrontMatterFilter do +RSpec.describe Banzai::Filter::FrontMatterFilter, feature_category: :team_planning do include FilterSpecHelper it 'allows for `encoding:` before the front matter' do @@ -114,7 +114,7 @@ RSpec.describe Banzai::Filter::FrontMatterFilter do foo: :foo_symbol - --- + --- # Header diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb index 23626576c0c..f30262ef9df 100644 --- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb +++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::GollumTagsFilter do +RSpec.describe Banzai::Filter::GollumTagsFilter, feature_category: :wiki do include FilterSpecHelper let(:project) { create(:project) } diff --git a/spec/lib/banzai/filter/html_entity_filter_spec.rb b/spec/lib/banzai/filter/html_entity_filter_spec.rb index d88fa21cde7..6de3fa50a1a 100644 --- a/spec/lib/banzai/filter/html_entity_filter_spec.rb +++ b/spec/lib/banzai/filter/html_entity_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::HtmlEntityFilter do +RSpec.describe Banzai::Filter::HtmlEntityFilter, feature_category: :team_planning do include FilterSpecHelper let(:unescaped) { 'foo <strike attr="foo">&&&</strike>' } diff --git a/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb b/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb index 5b32be0ea62..c5bcfe1f384 100644 --- a/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb +++ b/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::ImageLazyLoadFilter do +RSpec.describe Banzai::Filter::ImageLazyLoadFilter, feature_category: :team_planning do include FilterSpecHelper def image(path) diff --git a/spec/lib/banzai/filter/image_link_filter_spec.rb b/spec/lib/banzai/filter/image_link_filter_spec.rb index 78d68697ac7..2d496c447e1 100644 --- a/spec/lib/banzai/filter/image_link_filter_spec.rb +++ b/spec/lib/banzai/filter/image_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::ImageLinkFilter do +RSpec.describe Banzai::Filter::ImageLinkFilter, feature_category: :team_planning do include FilterSpecHelper let(:path) { '/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg' } diff --git a/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb b/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb index a11fe203541..1fdb29b688e 100644 --- a/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb +++ b/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::IssuableReferenceExpansionFilter do +RSpec.describe Banzai::Filter::IssuableReferenceExpansionFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:user) { create(:user) } diff --git a/spec/lib/banzai/filter/jira_import/adf_to_commonmark_filter_spec.rb b/spec/lib/banzai/filter/jira_import/adf_to_commonmark_filter_spec.rb index 287b5774048..5f971372dcc 100644 --- a/spec/lib/banzai/filter/jira_import/adf_to_commonmark_filter_spec.rb +++ b/spec/lib/banzai/filter/jira_import/adf_to_commonmark_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::JiraImport::AdfToCommonmarkFilter do +RSpec.describe Banzai::Filter::JiraImport::AdfToCommonmarkFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:fixtures_path) { 'lib/kramdown/atlassian_document_format' } diff --git a/spec/lib/banzai/filter/kroki_filter_spec.rb b/spec/lib/banzai/filter/kroki_filter_spec.rb index 3f4f3aafdd6..a528c5835b2 100644 --- a/spec/lib/banzai/filter/kroki_filter_spec.rb +++ b/spec/lib/banzai/filter/kroki_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::KrokiFilter do +RSpec.describe Banzai::Filter::KrokiFilter, feature_category: :team_planning do include FilterSpecHelper it 'replaces nomnoml pre tag with img tag if kroki is enabled' do diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb index e3c8d121587..c79cd58255d 100644 --- a/spec/lib/banzai/filter/markdown_filter_spec.rb +++ b/spec/lib/banzai/filter/markdown_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::MarkdownFilter do +RSpec.describe Banzai::Filter::MarkdownFilter, feature_category: :team_planning do include FilterSpecHelper describe 'markdown engine from context' do diff --git a/spec/lib/banzai/filter/mermaid_filter_spec.rb b/spec/lib/banzai/filter/mermaid_filter_spec.rb index c9bfcffe98f..de558a0774d 100644 --- a/spec/lib/banzai/filter/mermaid_filter_spec.rb +++ b/spec/lib/banzai/filter/mermaid_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::MermaidFilter do +RSpec.describe Banzai::Filter::MermaidFilter, feature_category: :team_planning do include FilterSpecHelper it 'adds `js-render-mermaid` class to the `code` tag' do diff --git a/spec/lib/banzai/filter/normalize_source_filter_spec.rb b/spec/lib/banzai/filter/normalize_source_filter_spec.rb index 8eaeec0e7b0..e267674e3b0 100644 --- a/spec/lib/banzai/filter/normalize_source_filter_spec.rb +++ b/spec/lib/banzai/filter/normalize_source_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::NormalizeSourceFilter do +RSpec.describe Banzai::Filter::NormalizeSourceFilter, feature_category: :team_planning do include FilterSpecHelper it 'removes the UTF8 BOM from the beginning of the text' do diff --git a/spec/lib/banzai/filter/output_safety_spec.rb b/spec/lib/banzai/filter/output_safety_spec.rb index 8186935f4b2..ec10306e8a8 100644 --- a/spec/lib/banzai/filter/output_safety_spec.rb +++ b/spec/lib/banzai/filter/output_safety_spec.rb @@ -2,7 +2,7 @@ require 'fast_spec_helper' -RSpec.describe Banzai::Filter::OutputSafety do +RSpec.describe Banzai::Filter::OutputSafety, feature_category: :team_planning do subject do Class.new do include Banzai::Filter::OutputSafety diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb index 4373af90cde..a1eabc23327 100644 --- a/spec/lib/banzai/filter/plantuml_filter_spec.rb +++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::PlantumlFilter do +RSpec.describe Banzai::Filter::PlantumlFilter, feature_category: :team_planning do include FilterSpecHelper it 'replaces plantuml pre tag with img tag' do diff --git a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb index a2f34d42814..1d45b692374 100644 --- a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb +++ b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::ReferenceRedactorFilter do +RSpec.describe Banzai::Filter::ReferenceRedactorFilter, feature_category: :team_planning do include FilterSpecHelper it 'ignores non-GFM links' do diff --git a/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb b/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb index 3cb3ebc42a6..a8e08530fde 100644 --- a/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::AbstractReferenceFilter do +RSpec.describe Banzai::Filter::References::AbstractReferenceFilter, feature_category: :team_planning do let_it_be(:project) { create(:project) } let(:doc) { Nokogiri::HTML.fragment('') } diff --git a/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb b/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb index c1fdee48f12..6ebf6c3cd1d 100644 --- a/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::AlertReferenceFilter do +RSpec.describe Banzai::Filter::References::AlertReferenceFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb index b235de06b30..594a24fa279 100644 --- a/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::CommitRangeReferenceFilter do +RSpec.describe Banzai::Filter::References::CommitRangeReferenceFilter, feature_category: :source_code_management do include FilterSpecHelper let(:project) { create(:project, :public, :repository) } diff --git a/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb b/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb index c368a852ea9..73e3bf41ee9 100644 --- a/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::CommitReferenceFilter do +RSpec.describe Banzai::Filter::References::CommitReferenceFilter, feature_category: :source_code_management do include FilterSpecHelper let(:project) { create(:project, :public, :repository) } diff --git a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb index d616aabea45..08de9700cad 100644 --- a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::DesignReferenceFilter do +RSpec.describe Banzai::Filter::References::DesignReferenceFilter, feature_category: :design_management do include FilterSpecHelper include DesignManagementTestHelpers diff --git a/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb index 2e811d35662..d40041d890e 100644 --- a/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter do +RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be_with_refind(:project) { create(:project) } diff --git a/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb b/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb index c64b66f746e..c2f4bf6caa5 100644 --- a/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::FeatureFlagReferenceFilter do +RSpec.describe Banzai::Filter::References::FeatureFlagReferenceFilter, feature_category: :feature_flags do include FilterSpecHelper let_it_be(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb index 32538948b4b..37fdd3ec806 100644 --- a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::IssueReferenceFilter do +RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_category: :team_planning do include FilterSpecHelper include DesignManagementTestHelpers diff --git a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb index d5b9c71b861..f8d223c6611 100644 --- a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'html/pipeline' -RSpec.describe Banzai::Filter::References::LabelReferenceFilter do +RSpec.describe Banzai::Filter::References::LabelReferenceFilter, feature_category: :team_planning do include FilterSpecHelper let(:project) { create(:project, :public, name: 'sample-project') } diff --git a/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb index 42e8cf1c857..9853d6f4093 100644 --- a/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::MergeRequestReferenceFilter do +RSpec.describe Banzai::Filter::References::MergeRequestReferenceFilter, feature_category: :code_review_workflow do include FilterSpecHelper let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb index 98090af06b1..ecd5d1368c9 100644 --- a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter do +RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:parent_group) { create(:group, :public) } diff --git a/spec/lib/banzai/filter/references/project_reference_filter_spec.rb b/spec/lib/banzai/filter/references/project_reference_filter_spec.rb index 0dd52b45f5d..49c71d08364 100644 --- a/spec/lib/banzai/filter/references/project_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/project_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::ProjectReferenceFilter do +RSpec.describe Banzai::Filter::References::ProjectReferenceFilter, feature_category: :team_planning do include FilterSpecHelper def invalidate_reference(reference) diff --git a/spec/lib/banzai/filter/references/reference_cache_spec.rb b/spec/lib/banzai/filter/references/reference_cache_spec.rb index dc43c33a08d..7307daca516 100644 --- a/spec/lib/banzai/filter/references/reference_cache_spec.rb +++ b/spec/lib/banzai/filter/references/reference_cache_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::ReferenceCache do +RSpec.describe Banzai::Filter::References::ReferenceCache, feature_category: :team_planning do let_it_be(:project) { create(:project) } let_it_be(:project2) { create(:project) } let_it_be(:issue1) { create(:issue, project: project) } diff --git a/spec/lib/banzai/filter/references/reference_filter_spec.rb b/spec/lib/banzai/filter/references/reference_filter_spec.rb index 88404f2039d..b55b8fd41fa 100644 --- a/spec/lib/banzai/filter/references/reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::ReferenceFilter do +RSpec.describe Banzai::Filter::References::ReferenceFilter, feature_category: :team_planning do let(:project) { build_stubbed(:project) } describe '#each_node' do diff --git a/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb index 2e324669870..32d1cb095d3 100644 --- a/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::SnippetReferenceFilter do +RSpec.describe Banzai::Filter::References::SnippetReferenceFilter, feature_category: :team_planning do include FilterSpecHelper let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/filter/references/user_reference_filter_spec.rb b/spec/lib/banzai/filter/references/user_reference_filter_spec.rb index d61b71c711d..e248f2d9b1c 100644 --- a/spec/lib/banzai/filter/references/user_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/user_reference_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::References::UserReferenceFilter do +RSpec.describe Banzai::Filter::References::UserReferenceFilter, feature_category: :team_planning do include FilterSpecHelper def get_reference(user) diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb index 039ca36af6e..51832e60754 100644 --- a/spec/lib/banzai/filter/sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::SanitizationFilter do +RSpec.describe Banzai::Filter::SanitizationFilter, feature_category: :team_planning do include FilterSpecHelper it_behaves_like 'default allowlist' diff --git a/spec/lib/banzai/filter/spaced_link_filter_spec.rb b/spec/lib/banzai/filter/spaced_link_filter_spec.rb index 820ebeb6945..0d236cf2381 100644 --- a/spec/lib/banzai/filter/spaced_link_filter_spec.rb +++ b/spec/lib/banzai/filter/spaced_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::SpacedLinkFilter do +RSpec.describe Banzai::Filter::SpacedLinkFilter, feature_category: :team_planning do include FilterSpecHelper let(:link) { '[example](page slug)' } diff --git a/spec/lib/banzai/filter/suggestion_filter_spec.rb b/spec/lib/banzai/filter/suggestion_filter_spec.rb index d74bac4898e..e65a9214e76 100644 --- a/spec/lib/banzai/filter/suggestion_filter_spec.rb +++ b/spec/lib/banzai/filter/suggestion_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::SuggestionFilter do +RSpec.describe Banzai::Filter::SuggestionFilter, feature_category: :team_planning do include FilterSpecHelper let(:input) { %(<pre class="code highlight js-syntax-highlight language-suggestion"><code>foo\n</code></pre>) } diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb index b4be26ef8d2..22f1716bc1a 100644 --- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb +++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::SyntaxHighlightFilter do +RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_planning do include FilterSpecHelper shared_examples "XSS prevention" do |lang| diff --git a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb index 91c644cb16a..26c949128da 100644 --- a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb +++ b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::TableOfContentsFilter do +RSpec.describe Banzai::Filter::TableOfContentsFilter, feature_category: :team_planning do include FilterSpecHelper def header(level, text) diff --git a/spec/lib/banzai/filter/table_of_contents_tag_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_tag_filter_spec.rb index 082e5c92e53..322225b38a9 100644 --- a/spec/lib/banzai/filter/table_of_contents_tag_filter_spec.rb +++ b/spec/lib/banzai/filter/table_of_contents_tag_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::TableOfContentsTagFilter do +RSpec.describe Banzai::Filter::TableOfContentsTagFilter, feature_category: :team_planning do include FilterSpecHelper context 'table of contents' do diff --git a/spec/lib/banzai/filter/task_list_filter_spec.rb b/spec/lib/banzai/filter/task_list_filter_spec.rb index 920904b0f29..3eef6761153 100644 --- a/spec/lib/banzai/filter/task_list_filter_spec.rb +++ b/spec/lib/banzai/filter/task_list_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::TaskListFilter do +RSpec.describe Banzai::Filter::TaskListFilter, feature_category: :team_planning do include FilterSpecHelper it 'adds `<task-button></task-button>` to every list item' do diff --git a/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb b/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb index 95d2e54459d..066f59758f0 100644 --- a/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb +++ b/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::TimeoutHtmlPipelineFilter do +RSpec.describe Banzai::Filter::TimeoutHtmlPipelineFilter, feature_category: :team_planning do include FilterSpecHelper it_behaves_like 'filter timeout' do diff --git a/spec/lib/banzai/filter/truncate_source_filter_spec.rb b/spec/lib/banzai/filter/truncate_source_filter_spec.rb index 8970aa1d382..8ca6a1affdd 100644 --- a/spec/lib/banzai/filter/truncate_source_filter_spec.rb +++ b/spec/lib/banzai/filter/truncate_source_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::TruncateSourceFilter do +RSpec.describe Banzai::Filter::TruncateSourceFilter, feature_category: :team_planning do include FilterSpecHelper let(:short_text) { 'foo' * 10 } diff --git a/spec/lib/banzai/filter/truncate_visible_filter_spec.rb b/spec/lib/banzai/filter/truncate_visible_filter_spec.rb index 8daaed05264..404b23a886f 100644 --- a/spec/lib/banzai/filter/truncate_visible_filter_spec.rb +++ b/spec/lib/banzai/filter/truncate_visible_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::TruncateVisibleFilter do +RSpec.describe Banzai::Filter::TruncateVisibleFilter, feature_category: :team_planning do include FilterSpecHelper let_it_be(:project) { build(:project, :repository) } diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb index eb45a8149c3..71656b6dc94 100644 --- a/spec/lib/banzai/filter/upload_link_filter_spec.rb +++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::UploadLinkFilter do +RSpec.describe Banzai::Filter::UploadLinkFilter, feature_category: :team_planning do def filter(doc, contexts = {}) contexts.reverse_merge!( project: project, diff --git a/spec/lib/banzai/filter/video_link_filter_spec.rb b/spec/lib/banzai/filter/video_link_filter_spec.rb index a0b0ba309f5..a53b8285bf0 100644 --- a/spec/lib/banzai/filter/video_link_filter_spec.rb +++ b/spec/lib/banzai/filter/video_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::VideoLinkFilter do +RSpec.describe Banzai::Filter::VideoLinkFilter, feature_category: :team_planning do def filter(doc, contexts = {}) contexts.reverse_merge!({ project: project diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb index 9807e385a5a..ace3aea5346 100644 --- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb +++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Filter::WikiLinkFilter do +RSpec.describe Banzai::Filter::WikiLinkFilter, feature_category: :wiki do include FilterSpecHelper let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") } diff --git a/spec/lib/banzai/filter_array_spec.rb b/spec/lib/banzai/filter_array_spec.rb index f341d5d51a0..bb457568bee 100644 --- a/spec/lib/banzai/filter_array_spec.rb +++ b/spec/lib/banzai/filter_array_spec.rb @@ -2,7 +2,7 @@ require 'fast_spec_helper' -RSpec.describe Banzai::FilterArray do +RSpec.describe Banzai::FilterArray, feature_category: :team_planning do describe '#insert_after' do it 'inserts an element after a provided element' do filters = described_class.new(%w(a b c)) diff --git a/spec/lib/banzai/issuable_extractor_spec.rb b/spec/lib/banzai/issuable_extractor_spec.rb index 8fec9691d7f..b2c869bd066 100644 --- a/spec/lib/banzai/issuable_extractor_spec.rb +++ b/spec/lib/banzai/issuable_extractor_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::IssuableExtractor do +RSpec.describe Banzai::IssuableExtractor, feature_category: :team_planning do let(:project) { create(:project) } let(:user) { create(:user) } let(:extractor) { described_class.new(Banzai::RenderContext.new(project, user)) } diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index 8f69480c65f..b2f7db24e38 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ObjectRenderer do +RSpec.describe Banzai::ObjectRenderer, feature_category: :team_planning do let(:project) { create(:project, :repository) } let(:user) { project.first_owner } let(:renderer) do diff --git a/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb b/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb index ad4256c2045..9f1af821d11 100644 --- a/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::BroadcastMessagePipeline do +RSpec.describe Banzai::Pipeline::BroadcastMessagePipeline, feature_category: :team_planning do let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, group: group) } diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb index be553433e9e..fa25612a06e 100644 --- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::DescriptionPipeline do +RSpec.describe Banzai::Pipeline::DescriptionPipeline, feature_category: :team_planning do let_it_be(:project) { create(:project) } def parse(html) diff --git a/spec/lib/banzai/pipeline/email_pipeline_spec.rb b/spec/lib/banzai/pipeline/email_pipeline_spec.rb index c7a0b9fefa1..4d2dca84b1b 100644 --- a/spec/lib/banzai/pipeline/email_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/email_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::EmailPipeline do +RSpec.describe Banzai::Pipeline::EmailPipeline, feature_category: :team_planning do describe '.filters' do it 'returns the expected type' do expect(described_class.filters).to be_kind_of(Banzai::FilterArray) diff --git a/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb b/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb index 8103846d4f7..6ecd7f56dec 100644 --- a/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::EmojiPipeline do +RSpec.describe Banzai::Pipeline::EmojiPipeline, feature_category: :team_planning do let(:emoji) { TanukiEmoji.find_by_alpha_code('100') } def parse(text) diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb index f67f13b3862..d0b85a1d043 100644 --- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::GfmPipeline do +RSpec.describe Banzai::Pipeline::GfmPipeline, feature_category: :team_planning do describe 'integration between parsing regular and external issue references' do let(:project) { create(:project, :with_redmine_integration, :public) } diff --git a/spec/lib/banzai/pipeline/jira_import/adf_commonmark_pipeline_spec.rb b/spec/lib/banzai/pipeline/jira_import/adf_commonmark_pipeline_spec.rb index 74005adf673..f579b9e1883 100644 --- a/spec/lib/banzai/pipeline/jira_import/adf_commonmark_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/jira_import/adf_commonmark_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::JiraImport::AdfCommonmarkPipeline do +RSpec.describe Banzai::Pipeline::JiraImport::AdfCommonmarkPipeline, feature_category: :team_planning do let_it_be(:fixtures_path) { 'lib/kramdown/atlassian_document_format' } it 'converts text in Atlassian Document Format' do diff --git a/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb b/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb index e8df395564a..072d77f4112 100644 --- a/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/post_process_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::PostProcessPipeline do +RSpec.describe Banzai::Pipeline::PostProcessPipeline, feature_category: :team_planning do subject { described_class.call(doc, context) } let_it_be(:project) { create(:project, :public, :repository) } diff --git a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb index 303d0fcb6c2..55575d4cf84 100644 --- a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::PreProcessPipeline do +RSpec.describe Banzai::Pipeline::PreProcessPipeline, feature_category: :team_planning do it 'pre-processes the source text' do markdown = <<~MD \xEF\xBB\xBF--- diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 59f5e4a6900..837ea2d7bc0 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Pipeline::WikiPipeline do +RSpec.describe Banzai::Pipeline::WikiPipeline, feature_category: :wiki do let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") } let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) } let_it_be(:wiki) { ProjectWiki.new(project, nil) } diff --git a/spec/lib/banzai/pipeline_spec.rb b/spec/lib/banzai/pipeline_spec.rb index b2c970e4394..c1199654cd6 100644 --- a/spec/lib/banzai/pipeline_spec.rb +++ b/spec/lib/banzai/pipeline_spec.rb @@ -2,7 +2,7 @@ require 'fast_spec_helper' -RSpec.describe Banzai::Pipeline do +RSpec.describe Banzai::Pipeline, feature_category: :team_planning do describe '.[]' do subject { described_class[name] } diff --git a/spec/lib/banzai/querying_spec.rb b/spec/lib/banzai/querying_spec.rb index fc7aaa94954..8f95816b073 100644 --- a/spec/lib/banzai/querying_spec.rb +++ b/spec/lib/banzai/querying_spec.rb @@ -2,7 +2,7 @@ require 'fast_spec_helper' -RSpec.describe Banzai::Querying do +RSpec.describe Banzai::Querying, feature_category: :team_planning do describe '.css' do it 'optimizes queries for elements with classes' do document = double(:document) diff --git a/spec/lib/banzai/reference_parser/alert_parser_spec.rb b/spec/lib/banzai/reference_parser/alert_parser_spec.rb index 0a9499fe6e4..33d7a7130dd 100644 --- a/spec/lib/banzai/reference_parser/alert_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/alert_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::AlertParser do +RSpec.describe Banzai::ReferenceParser::AlertParser, feature_category: :team_planning do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb index 61751b69842..bc7a93a7cde 100644 --- a/spec/lib/banzai/reference_parser/base_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::BaseParser do +RSpec.describe Banzai::ReferenceParser::BaseParser, feature_category: :team_planning do include ReferenceParserHelpers let(:user) { create(:user) } diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb index 3569a1019f0..081bfa26fb2 100644 --- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::CommitParser do +RSpec.describe Banzai::ReferenceParser::CommitParser, feature_category: :source_code_management do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb index 172347fc421..e058793c659 100644 --- a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::CommitRangeParser do +RSpec.describe Banzai::ReferenceParser::CommitRangeParser, feature_category: :source_code_management do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/design_parser_spec.rb b/spec/lib/banzai/reference_parser/design_parser_spec.rb index a9cb2952c26..c490cf5b36d 100644 --- a/spec/lib/banzai/reference_parser/design_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/design_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::DesignParser do +RSpec.describe Banzai::ReferenceParser::DesignParser, feature_category: :design_management do include ReferenceParserHelpers include DesignManagementTestHelpers diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb index 0c1b98e5ec3..1b2c9792cf7 100644 --- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::ExternalIssueParser do +RSpec.describe Banzai::ReferenceParser::ExternalIssueParser, feature_category: :team_planning do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb b/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb index 288eb9ae360..ba71949ee44 100644 --- a/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::FeatureFlagParser do +RSpec.describe Banzai::ReferenceParser::FeatureFlagParser, feature_category: :feature_flags do include ReferenceParserHelpers subject { described_class.new(Banzai::RenderContext.new(project, user)) } diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb index c180a42c91e..2efdb928b6f 100644 --- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::IssueParser do +RSpec.describe Banzai::ReferenceParser::IssueParser, feature_category: :team_planning do include ReferenceParserHelpers let_it_be(:group) { create(:group, :public) } diff --git a/spec/lib/banzai/reference_parser/label_parser_spec.rb b/spec/lib/banzai/reference_parser/label_parser_spec.rb index 8f287e15b37..e27af57f15d 100644 --- a/spec/lib/banzai/reference_parser/label_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/label_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::LabelParser do +RSpec.describe Banzai::ReferenceParser::LabelParser, feature_category: :team_planning do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/mentioned_group_parser_spec.rb b/spec/lib/banzai/reference_parser/mentioned_group_parser_spec.rb index 576e629d271..c5302d52270 100644 --- a/spec/lib/banzai/reference_parser/mentioned_group_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/mentioned_group_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::MentionedGroupParser do +RSpec.describe Banzai::ReferenceParser::MentionedGroupParser, feature_category: :team_planning do include ReferenceParserHelpers let(:group) { create(:group, :private) } diff --git a/spec/lib/banzai/reference_parser/mentioned_project_parser_spec.rb b/spec/lib/banzai/reference_parser/mentioned_project_parser_spec.rb index 983407addce..242a1720f39 100644 --- a/spec/lib/banzai/reference_parser/mentioned_project_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/mentioned_project_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::MentionedProjectParser do +RSpec.describe Banzai::ReferenceParser::MentionedProjectParser, feature_category: :team_planning do include ReferenceParserHelpers let(:group) { create(:group, :private) } diff --git a/spec/lib/banzai/reference_parser/mentioned_user_parser_spec.rb b/spec/lib/banzai/reference_parser/mentioned_user_parser_spec.rb index f117d796dad..14a5bf04752 100644 --- a/spec/lib/banzai/reference_parser/mentioned_user_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/mentioned_user_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::MentionedUserParser do +RSpec.describe Banzai::ReferenceParser::MentionedUserParser, feature_category: :team_planning do include ReferenceParserHelpers let(:group) { create(:group, :private) } diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb index 3fbda7f3239..eead5019217 100644 --- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::MergeRequestParser do +RSpec.describe Banzai::ReferenceParser::MergeRequestParser, feature_category: :code_review_workflow do include ReferenceParserHelpers let(:group) { create(:group, :public) } diff --git a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb index 95f71154e38..1e7a492cb35 100644 --- a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::MilestoneParser do +RSpec.describe Banzai::ReferenceParser::MilestoneParser, feature_category: :team_planning do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/project_parser_spec.rb b/spec/lib/banzai/reference_parser/project_parser_spec.rb index 2c0b6c417b0..90a3660a0e3 100644 --- a/spec/lib/banzai/reference_parser/project_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/project_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::ProjectParser do +RSpec.describe Banzai::ReferenceParser::ProjectParser, feature_category: :team_planning do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb index e8ef4e7f6e3..8f4148be2dc 100644 --- a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::SnippetParser do +RSpec.describe Banzai::ReferenceParser::SnippetParser, feature_category: :team_planning do include ReferenceParserHelpers let(:project) { create(:project, :public) } diff --git a/spec/lib/banzai/reference_parser/user_parser_spec.rb b/spec/lib/banzai/reference_parser/user_parser_spec.rb index d4f4339cf17..179e6e73fa3 100644 --- a/spec/lib/banzai/reference_parser/user_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/user_parser_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceParser::UserParser do +RSpec.describe Banzai::ReferenceParser::UserParser, feature_category: :team_planning do include ReferenceParserHelpers let(:group) { create(:group) } diff --git a/spec/lib/banzai/reference_redactor_spec.rb b/spec/lib/banzai/reference_redactor_spec.rb index 344b8988296..8a8f3ce586a 100644 --- a/spec/lib/banzai/reference_redactor_spec.rb +++ b/spec/lib/banzai/reference_redactor_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::ReferenceRedactor do +RSpec.describe Banzai::ReferenceRedactor, feature_category: :team_planning do let(:user) { create(:user) } let(:project) { build(:project) } let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } diff --git a/spec/lib/banzai/render_context_spec.rb b/spec/lib/banzai/render_context_spec.rb index 4b5c2c5a7df..76423b5805c 100644 --- a/spec/lib/banzai/render_context_spec.rb +++ b/spec/lib/banzai/render_context_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::RenderContext do +RSpec.describe Banzai::RenderContext, feature_category: :team_planning do let(:document) { Nokogiri::HTML.fragment('<p>hello</p>') } describe '#project_for_node' do diff --git a/spec/lib/banzai/renderer_spec.rb b/spec/lib/banzai/renderer_spec.rb index 705f44baf16..8c9d8d51d5f 100644 --- a/spec/lib/banzai/renderer_spec.rb +++ b/spec/lib/banzai/renderer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Banzai::Renderer do +RSpec.describe Banzai::Renderer, feature_category: :team_planning do let(:renderer) { described_class } def fake_object(fresh:) diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 7b79b4c8a6d..681f1b57a1a 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -1737,6 +1737,22 @@ RSpec.describe Ci::Runner, feature_category: :runner do end end + describe '#token' do + subject(:token) { runner.token } + + context 'when runner is registered' do + let(:runner) { create(:ci_runner) } + + it { is_expected.not_to start_with('glrt-') } + end + + context 'when runner is created in UI' do + let(:runner) { create(:ci_runner, :created_in_ui) } + + it { is_expected.to start_with('glrt-') } + end + end + describe '#token_expires_at', :freeze_time do shared_examples 'expiring token' do |interval:| it 'expires' do diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index c5e28337139..58a986fd099 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -9,7 +9,7 @@ feature_category: :kubernetes_management do it_behaves_like 'having unique enum values' - subject { build(:cluster) } + subject(:cluster) { build(:cluster) } it { is_expected.to include_module(HasEnvironmentScope) } it { is_expected.to belong_to(:user) } @@ -36,14 +36,6 @@ feature_category: :kubernetes_management do it { is_expected.to delegate_method(:status).to(:provider) } it { is_expected.to delegate_method(:status_reason).to(:provider) } - it { is_expected.to delegate_method(:on_creation?).to(:provider) } - it { is_expected.to delegate_method(:knative_pre_installed?).to(:provider) } - it { is_expected.to delegate_method(:active?).to(:platform_kubernetes).with_prefix } - it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix } - it { is_expected.to delegate_method(:available?).to(:application_helm).with_prefix } - it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix } - it { is_expected.to delegate_method(:available?).to(:application_knative).with_prefix } - it { is_expected.to delegate_method(:available?).to(:integration_prometheus).with_prefix } it { is_expected.to delegate_method(:external_ip).to(:application_ingress).with_prefix } it { is_expected.to delegate_method(:external_hostname).to(:application_ingress).with_prefix } @@ -1418,4 +1410,218 @@ feature_category: :kubernetes_management do end end end + + describe '#on_creation?' do + subject(:on_creation?) { cluster.on_creation? } + + before do + allow(cluster).to receive(:provider).and_return(provider) + end + + context 'without provider' do + let(:provider) {} + + it { is_expected.to eq(false) } + end + + context 'with provider' do + let(:provider) { instance_double(Clusters::Providers::Gcp, on_creation?: on_creation?) } + + before do + allow(cluster).to receive(:provider).and_return(provider) + end + + context 'with on_creation? set to true' do + let(:on_creation?) { true } + + it { is_expected.to eq(true) } + end + + context 'with on_creation? set to false' do + let(:on_creation?) { false } + + it { is_expected.to eq(false) } + end + end + end + + describe '#knative_pre_installed?' do + subject(:knative_pre_installed?) { cluster.knative_pre_installed? } + + before do + allow(cluster).to receive(:provider).and_return(provider) + end + + context 'without provider' do + let(:provider) {} + + it { is_expected.to eq(false) } + end + + context 'with provider' do + let(:provider) { instance_double(Clusters::Providers::Aws, knative_pre_installed?: knative_pre_installed?) } + + context 'with knative_pre_installed? set to true' do + let(:knative_pre_installed?) { true } + + it { is_expected.to eq(true) } + end + + context 'with knative_pre_installed? set to false' do + let(:knative_pre_installed?) { false } + + it { is_expected.to eq(false) } + end + end + end + + describe '#platform_kubernetes_active?' do + subject(:platform_kubernetes_active?) { cluster.platform_kubernetes_active? } + + before do + allow(cluster).to receive(:platform_kubernetes).and_return(platform_kubernetes) + end + + context 'without platform_kubernetes' do + let(:platform_kubernetes) {} + + it { is_expected.to eq(false) } + end + + context 'with platform_kubernetes' do + let(:platform_kubernetes) { instance_double(Clusters::Platforms::Kubernetes, active?: active?) } + + context 'with active? set to true' do + let(:active?) { true } + + it { is_expected.to eq(true) } + end + + context 'with active? set to false' do + let(:active?) { false } + + it { is_expected.to eq(false) } + end + end + end + + describe '#platform_kubernetes_rbac?' do + subject(:platform_kubernetes_rbac?) { cluster.platform_kubernetes_rbac? } + + before do + allow(cluster).to receive(:platform_kubernetes).and_return(platform_kubernetes) + end + + context 'without platform_kubernetes' do + let(:platform_kubernetes) {} + + it { is_expected.to eq(false) } + end + + context 'with platform_kubernetes' do + let(:platform_kubernetes) { instance_double(Clusters::Platforms::Kubernetes, rbac?: rbac?) } + + context 'with rbac? set to true' do + let(:rbac?) { true } + + it { is_expected.to eq(true) } + end + + context 'with rbac? set to false' do + let(:rbac?) { false } + + it { is_expected.to eq(false) } + end + end + end + + describe '#application_helm_available?' do + subject(:application_helm_available?) { cluster.application_helm_available? } + + before do + allow(cluster).to receive(:application_helm).and_return(application_helm) + end + + context 'without application_helm' do + let(:application_helm) {} + + it { is_expected.to eq(false) } + end + + context 'with application_helm' do + let(:application_helm) { instance_double(Clusters::Applications::Helm, available?: available?) } + + context 'with available? set to true' do + let(:available?) { true } + + it { is_expected.to eq(true) } + end + + context 'with available? set to false' do + let(:available?) { false } + + it { is_expected.to eq(false) } + end + end + end + + describe '#application_ingress_available?' do + subject(:application_ingress_available?) { cluster.application_ingress_available? } + + before do + allow(cluster).to receive(:application_ingress).and_return(application_ingress) + end + + context 'without application_ingress' do + let(:application_ingress) {} + + it { is_expected.to eq(false) } + end + + context 'with application_ingress' do + let(:application_ingress) { instance_double(Clusters::Applications::Ingress, available?: available?) } + + context 'with available? set to true' do + let(:available?) { true } + + it { is_expected.to eq(true) } + end + + context 'with available? set to false' do + let(:available?) { false } + + it { is_expected.to eq(false) } + end + end + end + + describe '#application_knative_available?' do + subject(:application_knative_available?) { cluster.application_knative_available? } + + before do + allow(cluster).to receive(:application_knative).and_return(application_knative) + end + + context 'without application_knative' do + let(:application_knative) {} + + it { is_expected.to eq(false) } + end + + context 'with application_knative' do + let(:application_knative) { instance_double(Clusters::Applications::Knative, available?: available?) } + + context 'with available? set to true' do + let(:available?) { true } + + it { is_expected.to eq(true) } + end + + context 'with available? set to false' do + let(:available?) { false } + + it { is_expected.to eq(false) } + end + end + end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 4605c086763..7e4354221fa 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -1006,23 +1006,15 @@ RSpec.describe Group, feature_category: :subgroups do describe '#add_user' do let(:user) { create(:user) } - it 'adds the user with a blocking refresh by default' do + it 'adds the user' do expect_next_instance_of(GroupMember) do |member| - expect(member).to receive(:refresh_member_authorized_projects).with(blocking: true) + expect(member).to receive(:refresh_member_authorized_projects).and_call_original end group.add_member(user, GroupMember::MAINTAINER) expect(group.group_members.maintainers.map(&:user)).to include(user) end - - it 'passes the blocking refresh value to member' do - expect_next_instance_of(GroupMember) do |member| - expect(member).to receive(:refresh_member_authorized_projects).with(blocking: false) - end - - group.add_member(user, GroupMember::MAINTAINER, blocking_refresh: false) - end end describe '#add_users' do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 4b28f619d94..e1a08a74ac0 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -891,18 +891,8 @@ RSpec.describe Member do expect(user.authorized_projects).not_to include(project) end - it 'successfully completes a blocking refresh', :delete do - expect(member).to receive(:refresh_member_authorized_projects).with(blocking: true).and_call_original - - member.accept_invite!(user) - - expect(user.authorized_projects.reload).to include(project) - end - - it 'successfully completes a non-blocking refresh', :delete, :sidekiq_inline do - member.blocking_refresh = false - - expect(member).to receive(:refresh_member_authorized_projects).with(blocking: false).and_call_original + it 'successfully completes a refresh', :delete, :sidekiq_inline do + expect(member).to receive(:refresh_member_authorized_projects).and_call_original member.accept_invite!(user) diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index 4ac7ce95b84..c416e63b915 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -253,17 +253,13 @@ RSpec.describe GroupMember do let(:action) { group.members.find_by(user: user).destroy! } - it 'changes access level', :sidekiq_inline do + it 'changes access level' do expect { action }.to change { user.can?(:guest_access, project_a) }.from(true).to(false) .and change { user.can?(:guest_access, project_b) }.from(true).to(false) .and change { user.can?(:guest_access, project_c) }.from(true).to(false) end - it 'schedules an AuthorizedProjectsWorker job to recalculate authorizations' do - expect(AuthorizedProjectsWorker).to receive(:bulk_perform_async).with([[user.id]]) - - action - end + it_behaves_like 'calls AuthorizedProjectsWorker inline to recalculate authorizations' end end end diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index d573fde5a74..5edd9469ea7 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -200,7 +200,8 @@ RSpec.describe ProjectMember do end it 'refreshes the authorization without calling AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker' do - expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).not_to receive(:bulk_perform_and_wait) + # this is inline with the overridden behaviour in stubbed_member.rb + expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).not_to receive(:new) project.destroy! end @@ -215,8 +216,9 @@ RSpec.describe ProjectMember do expect(project.authorized_users).not_to include(user) end - it 'refreshes the authorization without calling UserProjectAccessChangedService' do - expect(UserProjectAccessChangedService).not_to receive(:new) + it 'refreshes the authorization without calling `AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker`' do + # this is inline with the overridden behaviour in stubbed_member.rb + expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).not_to receive(:new) user.destroy! end @@ -224,7 +226,8 @@ RSpec.describe ProjectMember do context 'when importing' do it 'does not refresh' do - expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).not_to receive(:bulk_perform_and_wait) + # this is inline with the overridden behaviour in stubbed_member.rb + expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).not_to receive(:new) member = build(:project_member, project: project) member.importing = true @@ -294,16 +297,11 @@ RSpec.describe ProjectMember do project.add_member(user, Gitlab::Access::GUEST) end - it 'changes access level', :sidekiq_inline do + it 'changes access level' do expect { action }.to change { user.can?(:guest_access, project) }.from(true).to(false) end - it 'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker to recalculate authorizations' do - expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).to receive(:perform_async).with(project.id, user.id) - - action - end - + it_behaves_like 'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker inline to recalculate authorizations' it_behaves_like 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations' end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index f1528ac4de3..e9de636bb0d 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2775,14 +2775,36 @@ RSpec.describe Repository, feature_category: :source_code_management do it 'returns a Tree' do expect(repository.head_tree).to be_an_instance_of(Tree) end + + context 'when feature flag "optimized_head_tree" is disabled' do + before do + stub_feature_flags(optimized_head_tree: false) + end + + it 'returns a Tree' do + expect(repository.head_tree).to be_an_instance_of(Tree) + end + end end context 'with a non-existing repository' do it 'returns nil' do - expect(repository).to receive(:head_commit).and_return(nil) + expect(repository).to receive(:root_ref).and_return(nil) expect(repository.head_tree).to be_nil end + + context 'when feature flag "optimized_head_tree" is disabled' do + before do + stub_feature_flags(optimized_head_tree: false) + end + + it 'returns nil' do + expect(repository).to receive(:head_commit).and_return(nil) + + expect(repository.head_tree).to be_nil + end + end end end @@ -2795,16 +2817,33 @@ RSpec.describe Repository, feature_category: :source_code_management do let(:pagination_params) { nil } context 'using a non-existing repository' do - before do - allow(repository).to receive(:head_commit).and_return(nil) - end + context 'when feature flag "optimized_head_tree" is enabled' do + before do + allow(repository).to receive(:root_ref).and_return(nil) + end - it { is_expected.to be_nil } + it { is_expected.to be_nil } - context 'when path is defined' do - let(:path) { 'README.md' } + context 'when path is defined' do + let(:path) { 'README.md' } + + it { is_expected.to be_nil } + end + end + + context 'when feature flag "optimized_head_tree" is disabled' do + before do + stub_feature_flags(optimized_head_tree: false) + allow(repository).to receive(:head_commit).and_return(nil) + end it { is_expected.to be_nil } + + context 'when path is defined' do + let(:path) { 'README.md' } + + it { is_expected.to be_nil } + end end end diff --git a/spec/services/authorized_project_update/project_access_changed_service_spec.rb b/spec/services/authorized_project_update/project_access_changed_service_spec.rb index 11621055a47..da428bece20 100644 --- a/spec/services/authorized_project_update/project_access_changed_service_spec.rb +++ b/spec/services/authorized_project_update/project_access_changed_service_spec.rb @@ -4,18 +4,11 @@ require 'spec_helper' RSpec.describe AuthorizedProjectUpdate::ProjectAccessChangedService do describe '#execute' do - it 'schedules the project IDs' do - expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to receive(:bulk_perform_and_wait) - .with([[1], [2]]) - - described_class.new([1, 2]).execute - end - - it 'permits non-blocking operation' do + it 'executes projects_authorizations refresh' do expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to receive(:bulk_perform_async) .with([[1], [2]]) - described_class.new([1, 2]).execute(blocking: false) + described_class.new([1, 2]).execute end end end diff --git a/spec/services/ci/runners/register_runner_service_spec.rb b/spec/services/ci/runners/register_runner_service_spec.rb index 47d399cb19a..c67040e45eb 100644 --- a/spec/services/ci/runners/register_runner_service_spec.rb +++ b/spec/services/ci/runners/register_runner_service_spec.rb @@ -47,6 +47,7 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute', feature_categor expect(runner.run_untagged).to be true expect(runner.active).to be true expect(runner.token).not_to eq(registration_token) + expect(runner.token).not_to start_with(::Ci::Runner::CREATED_RUNNER_TOKEN_PREFIX) expect(runner).to be_instance_type end diff --git a/spec/services/export_csv/base_service_spec.rb b/spec/services/export_csv/base_service_spec.rb new file mode 100644 index 00000000000..e2b4d4829af --- /dev/null +++ b/spec/services/export_csv/base_service_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ExportCsv::BaseService, feature_category: :importers do + let_it_be(:issue) { create(:issue) } + let_it_be(:relation) { Issue.all } + let_it_be(:resource_parent) { issue.project } + + subject { described_class.new(relation, resource_parent) } + + describe '#email' do + it 'raises NotImplementedError' do + user = create(:user) + + expect { subject.email(user) }.to raise_error(NotImplementedError) + end + end + + describe '#header_to_value_hash' do + it 'raises NotImplementedError' do + expect { subject.send(:header_to_value_hash) }.to raise_error(NotImplementedError) + end + end + + describe '#associations_to_preload' do + it 'return []' do + expect(subject.send(:associations_to_preload)).to eq([]) + end + end +end diff --git a/spec/services/groups/group_links/destroy_service_spec.rb b/spec/services/groups/group_links/destroy_service_spec.rb index 03de7175edd..a570c28cf8b 100644 --- a/spec/services/groups/group_links/destroy_service_spec.rb +++ b/spec/services/groups/group_links/destroy_service_spec.rb @@ -70,8 +70,8 @@ RSpec.describe Groups::GroupLinks::DestroyService, '#execute' do it 'updates project authorization once per group' do expect(GroupGroupLink).to receive(:delete).and_call_original - expect(group).to receive(:refresh_members_authorized_projects).with(direct_members_only: true, blocking: false).once - expect(another_group).to receive(:refresh_members_authorized_projects).with(direct_members_only: true, blocking: false).once + expect(group).to receive(:refresh_members_authorized_projects).with(direct_members_only: true).once + expect(another_group).to receive(:refresh_members_authorized_projects).with(direct_members_only: true).once subject.execute(links) end diff --git a/spec/services/issues/export_csv_service_spec.rb b/spec/services/issues/export_csv_service_spec.rb index d3359447fd8..f5ff4ed3f9e 100644 --- a/spec/services/issues/export_csv_service_spec.rb +++ b/spec/services/issues/export_csv_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Issues::ExportCsvService, :with_license do +RSpec.describe Issues::ExportCsvService, :with_license, feature_category: :importers do let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, :public, group: group) } diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb index d8a8d5881bf..9570aa1b612 100644 --- a/spec/services/members/destroy_service_spec.rb +++ b/spec/services/members/destroy_service_spec.rb @@ -111,26 +111,6 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do subject(:destroy_member) { service_object.execute(member_to_delete, **opts) } - shared_examples_for 'deletes the member without using a lock' do - it 'does not try to perform the delete within a lock' do - # `UpdateHighestRole` concern also uses locks to peform work - # whenever a Member is committed, so that needs to be accounted for. - lock_key_for_update_highest_role = "update_highest_role:#{member_to_delete.user_id}" - expect(Gitlab::ExclusiveLease) - .to receive(:new).with(lock_key_for_update_highest_role, timeout: 10.minutes.to_i).and_call_original - - # We do not use any locks for member deletion process. - expect(Gitlab::ExclusiveLease) - .not_to receive(:new).with(lock_key, timeout: timeout) - - destroy_member - end - - it 'destroys the membership' do - expect { destroy_member }.to change { entity.members.count }.by(-1) - end - end - context 'for group members' do before do group.add_owner(current_user) @@ -171,13 +151,70 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do context 'deleting group members that are not owners' do let!(:member_to_delete) { group.add_developer(member_user) } - it_behaves_like 'deletes the member without using a lock' do - let(:entity) { group } + it 'does not try to perform the deletion of the member within a lock' do + # We need to account for other places involved in the Member deletion process that + # uses ExclusiveLease. + + # 1. `UpdateHighestRole` concern uses locks to peform work + # whenever a Member is committed, so that needs to be accounted for. + lock_key_for_update_highest_role = "update_highest_role:#{member_to_delete.user_id}" + + expect(Gitlab::ExclusiveLease) + .to receive(:new).with(lock_key_for_update_highest_role, timeout: 10.minutes.to_i).and_call_original + + # 2. `Users::RefreshAuthorizedProjectsService` also uses locks to perform work, + # whenever a user's authorizations has to be refreshed, so that needs to be accounted for as well. + lock_key_for_authorizations_refresh = "refresh_authorized_projects:#{member_to_delete.user_id}" + + expect(Gitlab::ExclusiveLease) + .to receive(:new).with(lock_key_for_authorizations_refresh, timeout: 1.minute.to_i).and_call_original + + # We do not use any locks for the member deletion process, from within this service. + expect(Gitlab::ExclusiveLease) + .not_to receive(:new).with(lock_key, timeout: timeout) + + destroy_member + end + + it 'destroys the membership' do + expect { destroy_member }.to change { group.members.count }.by(-1) end end end context 'for project members' do + shared_examples_for 'deletes the project member without using a lock' do + it 'does not try to perform the deletion of a project member within a lock' do + # We need to account for other places involved in the Member deletion process that + # uses ExclusiveLease. + + # 1. `UpdateHighestRole` concern uses locks to peform work + # whenever a Member is committed, so that needs to be accounted for. + lock_key_for_update_highest_role = "update_highest_role:#{member_to_delete.user_id}" + + expect(Gitlab::ExclusiveLease) + .to receive(:new).with(lock_key_for_update_highest_role, timeout: 10.minutes.to_i).and_call_original + + # 2. `AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker` also uses locks to perform work, + # whenever a user's authorizations has to be refreshed, so that needs to be accounted for as well. + lock_key_for_authorizations_refresh = + "authorized_project_update/project_recalculate_worker/projects/#{member_to_delete.project.id}" + + expect(Gitlab::ExclusiveLease) + .to receive(:new).with(lock_key_for_authorizations_refresh, timeout: 10.seconds).and_call_original + + # We do not use any locks for the member deletion process, from within this service. + expect(Gitlab::ExclusiveLease) + .not_to receive(:new).with(lock_key, timeout: timeout) + + destroy_member + end + + it 'destroys the membership' do + expect { destroy_member }.to change { entity.members.count }.by(-1) + end + end + before do group_project.add_owner(current_user) end @@ -186,16 +223,16 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do context 'deleting project owners' do let!(:member_to_delete) { entity.add_owner(member_user) } - it_behaves_like 'deletes the member without using a lock' do + it_behaves_like 'deletes the project member without using a lock' do let(:entity) { group_project } end end end - context 'deleting project memebrs that are not owners' do + context 'deleting project members that are not owners' do let!(:member_to_delete) { group_project.add_developer(member_user) } - it_behaves_like 'deletes the member without using a lock' do + it_behaves_like 'deletes the project member without using a lock' do let(:entity) { group_project } end end diff --git a/spec/services/merge_requests/export_csv_service_spec.rb b/spec/services/merge_requests/export_csv_service_spec.rb index 97217e979a5..2f0036845e7 100644 --- a/spec/services/merge_requests/export_csv_service_spec.rb +++ b/spec/services/merge_requests/export_csv_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::ExportCsvService do +RSpec.describe MergeRequests::ExportCsvService, feature_category: :importers do let_it_be(:merge_request) { create(:merge_request) } let(:csv) { CSV.parse(subject.csv_data, headers: true).first } @@ -113,5 +113,21 @@ RSpec.describe MergeRequests::ExportCsvService do end end end + + describe '#email' do + let_it_be(:user) { create(:user) } + + it 'emails csv' do + expect { subject.email(user) }.to change { ActionMailer::Base.deliveries.count } + end + + it 'renders with a target filesize' do + expect_next_instance_of(CsvBuilder) do |csv_builder| + expect(csv_builder).to receive(:render).with(described_class::TARGET_FILESIZE).once + end + + subject.email(user) + end + end end end diff --git a/spec/services/user_project_access_changed_service_spec.rb b/spec/services/user_project_access_changed_service_spec.rb index be4f205afb5..9aa7dcf09bc 100644 --- a/spec/services/user_project_access_changed_service_spec.rb +++ b/spec/services/user_project_access_changed_service_spec.rb @@ -4,18 +4,11 @@ require 'spec_helper' RSpec.describe UserProjectAccessChangedService do describe '#execute' do - it 'schedules the user IDs' do - expect(AuthorizedProjectsWorker).to receive(:bulk_perform_and_wait) - .with([[1], [2]]) - - described_class.new([1, 2]).execute - end - - it 'permits non-blocking operation' do + it 'permits high-priority operation' do expect(AuthorizedProjectsWorker).to receive(:bulk_perform_async) .with([[1], [2]]) - described_class.new([1, 2]).execute(blocking: false) + described_class.new([1, 2]).execute end it 'permits low-priority operation' do @@ -27,8 +20,7 @@ RSpec.describe UserProjectAccessChangedService do ) ) - described_class.new([1, 2]).execute(blocking: false, - priority: described_class::LOW_PRIORITY) + described_class.new([1, 2]).execute(priority: described_class::LOW_PRIORITY) end it 'permits medium-priority operation' do @@ -40,14 +32,12 @@ RSpec.describe UserProjectAccessChangedService do ) ) - described_class.new([1, 2]).execute(blocking: false, - priority: described_class::MEDIUM_PRIORITY) + described_class.new([1, 2]).execute(priority: described_class::MEDIUM_PRIORITY) end it 'sets the current caller_id as related_class in the context of all the enqueued jobs' do Gitlab::ApplicationContext.with_context(caller_id: 'Foo') do - described_class.new([1, 2]).execute(blocking: false, - priority: described_class::LOW_PRIORITY) + described_class.new([1, 2]).execute(priority: described_class::LOW_PRIORITY) end expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker.jobs).to all( @@ -60,7 +50,7 @@ RSpec.describe UserProjectAccessChangedService do let(:service) { UserProjectAccessChangedService.new([1, 2]) } before do - expect(AuthorizedProjectsWorker).to receive(:bulk_perform_and_wait) + expect(AuthorizedProjectsWorker).to receive(:bulk_perform_async) .with([[1], [2]]) .and_return(10) end @@ -79,7 +69,7 @@ RSpec.describe UserProjectAccessChangedService do service = UserProjectAccessChangedService.new([1, 2, 3, 4, 5]) - allow(AuthorizedProjectsWorker).to receive(:bulk_perform_and_wait) + allow(AuthorizedProjectsWorker).to receive(:bulk_perform_async) .with([[1], [2], [3], [4], [5]]) .and_return(10) diff --git a/spec/support/helpers/stubbed_member.rb b/spec/support/helpers/stubbed_member.rb index 27420c9b709..d61cdea5354 100644 --- a/spec/support/helpers/stubbed_member.rb +++ b/spec/support/helpers/stubbed_member.rb @@ -11,9 +11,7 @@ module StubbedMember module Member private - def refresh_member_authorized_projects(blocking:) - return super unless blocking - + def refresh_member_authorized_projects AuthorizedProjectsWorker.new.perform(user_id) end end @@ -21,7 +19,7 @@ module StubbedMember module ProjectMember private - def blocking_project_authorizations_refresh + def execute_project_authorizations_refresh AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.new.perform(project.id, user.id) end end diff --git a/spec/workers/concerns/waitable_worker_spec.rb b/spec/workers/concerns/waitable_worker_spec.rb index 1449c327052..737424ffd8c 100644 --- a/spec/workers/concerns/waitable_worker_spec.rb +++ b/spec/workers/concerns/waitable_worker_spec.rb @@ -22,38 +22,6 @@ RSpec.describe WaitableWorker do subject(:job) { worker.new } - describe '.bulk_perform_and_wait' do - context '1 job' do - it 'runs the jobs asynchronously' do - arguments = [[1]] - - expect(worker).to receive(:bulk_perform_async).with(arguments) - - worker.bulk_perform_and_wait(arguments) - end - end - - context 'between 2 and 3 jobs' do - it 'runs the jobs asynchronously' do - arguments = [[1], [2], [3]] - - expect(worker).to receive(:bulk_perform_async).with(arguments) - - worker.bulk_perform_and_wait(arguments) - end - end - - context '>= 4 jobs' do - it 'runs jobs using sidekiq' do - arguments = 1.upto(5).map { |i| [i] } - - expect(worker).to receive(:bulk_perform_async).with(arguments) - - worker.bulk_perform_and_wait(arguments) - end - end - end - describe '#perform' do shared_examples 'perform' do it 'notifies the JobWaiter when done if the key is provided' do |