diff options
52 files changed, 393 insertions, 223 deletions
diff --git a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js index b9e4c7b68b0..1d54a1b0c04 100644 --- a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js @@ -91,6 +91,7 @@ function renderMermaidEl(el, source) { sandbox: 'allow-scripts', frameBorder: 0, scrolling: 'no', + width: '100%', }); // Add the original source into the DOM @@ -119,7 +120,6 @@ function renderMermaidEl(el, source) { return; } const { h } = event.data; - iframeEl.width = '100%'; iframeEl.height = `${h + BUFFER_IFRAME_HEIGHT}px`; }, false, diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue index fec2e49172e..156029b62b0 100644 --- a/app/assets/javascripts/boards/components/board_content_sidebar.vue +++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue @@ -6,11 +6,12 @@ import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdow import { __, sprintf } from '~/locale'; import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue'; import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue'; -import { ISSUABLE } from '~/boards/constants'; +import { ISSUABLE, INCIDENT } from '~/boards/constants'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue'; import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue'; import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue'; +import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue'; import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue'; import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue'; import SidebarLabelsWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue'; @@ -29,6 +30,7 @@ export default { SidebarSubscriptionsWidget, SidebarDropdownWidget, SidebarTodoWidget, + SidebarSeverity, MountingPortal, SidebarWeightWidget: () => import('ee_component/sidebar/components/weight/sidebar_weight_widget.vue'), @@ -69,9 +71,15 @@ export default { isIssuableSidebar() { return this.sidebarType === ISSUABLE; }, + isIncidentSidebar() { + return this.activeBoardItem.type === INCIDENT; + }, showSidebar() { return this.isIssuableSidebar && this.isSidebarOpen; }, + sidebarTitle() { + return this.isIncidentSidebar ? __('Incident details') : __('Issue details'); + }, fullPath() { return this.activeBoardItem?.referencePath?.split('#')[0] || ''; }, @@ -138,7 +146,7 @@ export default { @close="handleClose" > <template #title> - <h2 class="gl-my-0 gl-font-size-h2 gl-line-height-24">{{ __('Issue details') }}</h2> + <h2 class="gl-my-0 gl-font-size-h2 gl-line-height-24">{{ sidebarTitle }}</h2> </template> <template #header> <sidebar-todo-widget @@ -159,7 +167,7 @@ export default { @assignees-updated="setAssignees" /> <sidebar-dropdown-widget - v-if="epicFeatureAvailable" + v-if="epicFeatureAvailable && !isIncidentSidebar" :iid="activeBoardItem.iid" issuable-attribute="epic" :workspace-path="projectPathForActiveIssue" @@ -178,7 +186,7 @@ export default { /> <template v-if="!glFeatures.iterationCadences"> <sidebar-dropdown-widget - v-if="iterationFeatureAvailable" + v-if="iterationFeatureAvailable && !isIncidentSidebar" :iid="activeBoardItem.iid" issuable-attribute="iteration" :workspace-path="projectPathForActiveIssue" @@ -190,7 +198,7 @@ export default { </template> <template v-else> <iteration-sidebar-dropdown-widget - v-if="iterationFeatureAvailable" + v-if="iterationFeatureAvailable && !isIncidentSidebar" :iid="activeBoardItem.iid" :workspace-path="projectPathForActiveIssue" :attr-workspace-path="groupPathForActiveIssue" @@ -226,8 +234,14 @@ export default { > {{ __('None') }} </sidebar-labels-widget> + <sidebar-severity + v-if="isIncidentSidebar" + :iid="activeBoardItem.iid" + :project-path="fullPath" + :initial-severity="activeBoardItem.severity" + /> <sidebar-weight-widget - v-if="weightFeatureAvailable" + v-if="weightFeatureAvailable && !isIncidentSidebar" :iid="activeBoardItem.iid" :full-path="fullPath" :issuable-type="issuableType" diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js index 851b5eca40d..80559795cf0 100644 --- a/app/assets/javascripts/boards/constants.js +++ b/app/assets/javascripts/boards/constants.js @@ -54,6 +54,7 @@ export const inactiveId = 0; export const ISSUABLE = 'issuable'; export const LIST = 'list'; +export const INCIDENT = 'INCIDENT'; export const flashAnimationDuration = 2000; diff --git a/app/assets/javascripts/boards/graphql/issue.fragment.graphql b/app/assets/javascripts/boards/graphql/issue.fragment.graphql index 314faae89f8..53fe6fdc59e 100644 --- a/app/assets/javascripts/boards/graphql/issue.fragment.graphql +++ b/app/assets/javascripts/boards/graphql/issue.fragment.graphql @@ -1,35 +1,6 @@ -#import "~/graphql_shared/fragments/milestone.fragment.graphql" -#import "~/graphql_shared/fragments/user.fragment.graphql" +#import "~/graphql_shared/fragments/issue.fragment.graphql" -fragment IssueNode on Issue { +fragment Issue on Issue { id - iid - title - referencePath: reference(full: true) - dueDate - timeEstimate - totalTimeSpent - humanTimeEstimate - humanTotalTimeSpent - emailsDisabled - confidential - hidden - webUrl - relativePosition - milestone { - ...MilestoneFragment - } - assignees { - nodes { - ...User - } - } - labels { - nodes { - id - title - color - description - } - } + ...IssueNode } diff --git a/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql index c1a2361a4e8..643d5dcfe4c 100644 --- a/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql +++ b/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql @@ -3,7 +3,7 @@ mutation CreateIssue($input: CreateIssueInput!) { createIssue(input: $input) { issue { - ...IssueNode + ...Issue } errors } diff --git a/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql index 570731ecac6..1658cf09085 100644 --- a/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql +++ b/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql @@ -21,7 +21,7 @@ mutation issueMoveList( } ) { issue { - ...IssueNode + ...Issue } errors } diff --git a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql index 105f2931caa..994ea894be3 100644 --- a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql +++ b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql @@ -22,7 +22,7 @@ query BoardListsEE( issues(first: $first, filters: $filters, after: $after) { edges { node { - ...IssueNode + ...Issue } } pageInfo { @@ -46,7 +46,7 @@ query BoardListsEE( issues(first: $first, filters: $filters, after: $after) { edges { node { - ...IssueNode + ...Issue } } pageInfo { diff --git a/app/assets/javascripts/graphql_shared/fragments/issue.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/issue.fragment.graphql new file mode 100644 index 00000000000..85a28fe1f71 --- /dev/null +++ b/app/assets/javascripts/graphql_shared/fragments/issue.fragment.graphql @@ -0,0 +1,37 @@ +#import "~/graphql_shared/fragments/milestone.fragment.graphql" +#import "~/graphql_shared/fragments/user.fragment.graphql" + +fragment IssueNode on Issue { + id + iid + title + referencePath: reference(full: true) + dueDate + timeEstimate + totalTimeSpent + humanTimeEstimate + humanTotalTimeSpent + emailsDisabled + confidential + hidden + webUrl + relativePosition + type + severity + milestone { + ...MilestoneFragment + } + assignees { + nodes { + ...User + } + } + labels { + nodes { + id + title + color + description + } + } +} diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index be2cb270a19..7a88162f469 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -52,3 +52,5 @@ class Profiles::EmailsController < Profiles::ApplicationController @email = current_user.emails.find(params[:id]) end end + +Profiles::EmailsController.prepend_mod diff --git a/app/services/ci/play_build_service.rb b/app/services/ci/play_build_service.rb index e2673c763f3..2d6b6aeee14 100644 --- a/app/services/ci/play_build_service.rb +++ b/app/services/ci/play_build_service.rb @@ -14,7 +14,10 @@ module Ci AfterRequeueJobService.new(project, current_user).execute(build) end else - Ci::Build.retry(build, current_user) + # Retrying in Ci::PlayBuildService is a legacy process that should be removed. + # Instead, callers should explicitly execute Ci::RetryBuildService. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/347493. + build.retryable? ? Ci::Build.retry(build, current_user) : build end end diff --git a/app/services/emails/confirm_service.rb b/app/services/emails/confirm_service.rb index 38204e011dd..4ceff4e3cfa 100644 --- a/app/services/emails/confirm_service.rb +++ b/app/services/emails/confirm_service.rb @@ -7,3 +7,5 @@ module Emails end end end + +Emails::ConfirmService.prepend_mod diff --git a/config/feature_flags/development/multiple_gpg_signatures.yml b/config/feature_flags/development/multiple_gpg_signatures.yml deleted file mode 100644 index 433309aea58..00000000000 --- a/config/feature_flags/development/multiple_gpg_signatures.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: multiple_gpg_signatures -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74095 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345261 -milestone: '14.5' -type: development -group: group::source code -default_enabled: true diff --git a/db/post_migrate/20220113013319_remove_projects_ci_freeze_periods_project_id_fk.rb b/db/post_migrate/20220113013319_remove_projects_ci_freeze_periods_project_id_fk.rb new file mode 100644 index 00000000000..13cfacdc223 --- /dev/null +++ b/db/post_migrate/20220113013319_remove_projects_ci_freeze_periods_project_id_fk.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class RemoveProjectsCiFreezePeriodsProjectIdFk < Gitlab::Database::Migration[1.0] + disable_ddl_transaction! + + def up + with_lock_retries do + remove_foreign_key_if_exists(:ci_freeze_periods, :projects, name: "fk_2e02bbd1a6") + end + end + + def down + add_concurrent_foreign_key(:ci_freeze_periods, :projects, name: "fk_2e02bbd1a6", column: :project_id, target_column: :id, on_delete: "cascade") + end +end diff --git a/db/post_migrate/20220113014438_remove_projects_ci_resource_groups_project_id_fk.rb b/db/post_migrate/20220113014438_remove_projects_ci_resource_groups_project_id_fk.rb new file mode 100644 index 00000000000..e86dd015493 --- /dev/null +++ b/db/post_migrate/20220113014438_remove_projects_ci_resource_groups_project_id_fk.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class RemoveProjectsCiResourceGroupsProjectIdFk < Gitlab::Database::Migration[1.0] + disable_ddl_transaction! + + def up + with_lock_retries do + remove_foreign_key_if_exists(:ci_resource_groups, :projects, name: "fk_774722d144") + end + end + + def down + add_concurrent_foreign_key(:ci_resource_groups, :projects, name: "fk_774722d144", column: :project_id, target_column: :id, on_delete: "cascade") + end +end diff --git a/db/schema_migrations/20220113013319 b/db/schema_migrations/20220113013319 new file mode 100644 index 00000000000..0dc31b95004 --- /dev/null +++ b/db/schema_migrations/20220113013319 @@ -0,0 +1 @@ +ccfbbbe52b27833453f867c4d7093187d21dbbfebe054b366ff010c54de50974
\ No newline at end of file diff --git a/db/schema_migrations/20220113014438 b/db/schema_migrations/20220113014438 new file mode 100644 index 00000000000..936c801bafe --- /dev/null +++ b/db/schema_migrations/20220113014438 @@ -0,0 +1 @@ +08d8a5a605058598a2f033bbd461518c502fb3da8627240c5d66f887b43f3ac3
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 1af51afd14d..ad66683e670 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -29171,9 +29171,6 @@ ALTER TABLE ONLY agent_group_authorizations ALTER TABLE ONLY deployment_approvals ADD CONSTRAINT fk_2d060dfc73 FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE; -ALTER TABLE ONLY ci_freeze_periods - ADD CONSTRAINT fk_2e02bbd1a6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; - ALTER TABLE ONLY notes ADD CONSTRAINT fk_2e82291620 FOREIGN KEY (review_id) REFERENCES reviews(id) ON DELETE SET NULL; @@ -29369,9 +29366,6 @@ ALTER TABLE ONLY vulnerabilities ALTER TABLE ONLY oauth_openid_requests ADD CONSTRAINT fk_77114b3b09 FOREIGN KEY (access_grant_id) REFERENCES oauth_access_grants(id) ON DELETE CASCADE; -ALTER TABLE ONLY ci_resource_groups - ADD CONSTRAINT fk_774722d144 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; - ALTER TABLE ONLY users ADD CONSTRAINT fk_789cd90b35 FOREIGN KEY (accepted_term_id) REFERENCES application_setting_terms(id) ON DELETE CASCADE; diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md index 7cecc0c30fd..0bdaeaed971 100644 --- a/doc/administration/compliance.md +++ b/doc/administration/compliance.md @@ -54,6 +54,8 @@ identify if problems exist and then drill down into the specifics of those issue - [**Audit events**](audit_events.md) (for instances, groups, and projects): To maintain the integrity of your code, audit events give administrators the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change. +- [**Audit reports**](audit_reports.md) (for instances, groups, and projects): Create and access reports based on the + audit events that have occurred. Use pre-built GitLab reports or the API to build your own. - [**Auditor users**](auditor_users.md) (for instances): Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance. - [**Compliance report**](../user/compliance/compliance_report/index.md) (for groups): Quickly get visibility into the @@ -73,6 +75,8 @@ These features can also help with compliance requirements: - [**Generate reports on permission levels of users**](../user/admin_area/index.md#user-permission-export) (for instances): Administrators can generate a report listing all users' access permissions for groups and projects in the instance. +- [**License compliance**](../user/compliance/license_compliance/index.md) (for projects): Search dependencies for their + licenses. This lets you determine if the licenses of your project's dependencies are compatible with your project's license. - [**Lock project membership to group**](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group) (for groups): Group owners can prevent new members from being added to projects within a group. - [**LDAP group sync**](auth/ldap/ldap_synchronization.md#group-sync) (for instances): Gives administrators the ability diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md index b8ac9061259..a5c60af47b1 100644 --- a/doc/administration/reference_architectures/10k_users.md +++ b/doc/administration/reference_architectures/10k_users.md @@ -2228,17 +2228,16 @@ use Google Cloud's Kubernetes Engine (GKE) and associated machine types, but the and CPU requirements should translate to most other providers. We hope to update this in the future with further specific cloud provider details. -| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory | -|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------| -| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory | -| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory | -| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory | - -<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix --> -<!-- markdownlint-disable MD029 --> -1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. - In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. -<!-- markdownlint-enable MD029 --> +| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory | +|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------| +| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory | +| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory | +| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory | + +- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results) +[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. +- Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. + - In production deployments, there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. Next are the backend components that run on static compute VMs via Omnibus (or External PaaS services where applicable): diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md index 5b9ce14c623..8cc355db951 100644 --- a/doc/administration/reference_architectures/25k_users.md +++ b/doc/administration/reference_architectures/25k_users.md @@ -2226,17 +2226,16 @@ use Google Cloud's Kubernetes Engine (GKE) and associated machine types, but the and CPU requirements should translate to most other providers. We hope to update this in the future with further specific cloud provider details. -| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory | -|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------| -| Webservice | 7 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 223 vCPU, 206.5 GB memory | -| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory | -| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory | - -<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix --> -<!-- markdownlint-disable MD029 --> -1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. - In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. -<!-- markdownlint-enable MD029 --> +| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory | +|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------| +| Webservice | 7 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 223 vCPU, 206.5 GB memory | +| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory | +| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory | + +- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results) +[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. +- Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. + - In production deployments, there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. Next are the backend components that run on static compute VMs via Omnibus (or External PaaS services where applicable): diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md index f72c0877ddb..467c64b8279 100644 --- a/doc/administration/reference_architectures/2k_users.md +++ b/doc/administration/reference_architectures/2k_users.md @@ -1016,17 +1016,16 @@ use Google Cloud's Kubernetes Engine (GKE) and associated machine types, but the and CPU requirements should translate to most other providers. We hope to update this in the future with further specific cloud provider details. -| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory | -|-------------------------------------------------------|-------------------|------------------------|-----------------|-----------------------------| -| Webservice | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | 23.7 vCPU, 16.9 GB memory | -| Sidekiq | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory | -| Supporting services such as NGINX, Prometheus | 2 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | 1.9 vCPU, 5.5 GB memory | - -<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix --> -<!-- markdownlint-disable MD029 --> -1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. - In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. -<!-- markdownlint-enable MD029 --> +| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory | +|-------------------------------------------------------|-------|------------------------|-----------------|-----------------------------| +| Webservice | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | 23.7 vCPU, 16.9 GB memory | +| Sidekiq | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory | +| Supporting services such as NGINX, Prometheus | 2 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | 1.9 vCPU, 5.5 GB memory | + +- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results) +[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. +- Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. + - In production deployments, there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. Next are the backend components that run on static compute VMs via Omnibus (or External PaaS services where applicable): diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md index b6a8c01295e..01d9987739b 100644 --- a/doc/administration/reference_architectures/3k_users.md +++ b/doc/administration/reference_architectures/3k_users.md @@ -2185,17 +2185,16 @@ use Google Cloud's Kubernetes Engine (GKE) and associated machine types, but the and CPU requirements should translate to most other providers. We hope to update this in the future with further specific cloud provider details. -| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory | -|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------| -| Webservice | 2 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 31.8 vCPU, 24.8 GB memory | -| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory | -| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory | - -<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix --> -<!-- markdownlint-disable MD029 --> -1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. - In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. -<!-- markdownlint-enable MD029 --> +| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory | +|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------| +| Webservice | 2 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 31.8 vCPU, 24.8 GB memory | +| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory | +| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory | + +- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results) +[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. +- Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. + - In production deployments, there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. Next are the backend components that run on static compute VMs via Omnibus (or External PaaS services where applicable): diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md index 2e7f3d57114..d5bb9c4ad64 100644 --- a/doc/administration/reference_architectures/50k_users.md +++ b/doc/administration/reference_architectures/50k_users.md @@ -2242,17 +2242,16 @@ use Google Cloud's Kubernetes Engine (GKE) and associated machine types, but the and CPU requirements should translate to most other providers. We hope to update this in the future with further specific cloud provider details. -| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory | -|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------| -| Webservice | 16 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 510 vCPU, 472 GB memory | -| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory | -| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory | - -<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix --> -<!-- markdownlint-disable MD029 --> -1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. - In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. -<!-- markdownlint-enable MD029 --> +| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory | +|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------| +| Webservice | 16 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 510 vCPU, 472 GB memory | +| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory | +| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory | + +- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results) +[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. +- Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. + - In production deployments, there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. Next are the backend components that run on static compute VMs via Omnibus (or External PaaS services where applicable): diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md index 46948350827..33ca4e4899f 100644 --- a/doc/administration/reference_architectures/5k_users.md +++ b/doc/administration/reference_architectures/5k_users.md @@ -2161,17 +2161,16 @@ use Google Cloud's Kubernetes Engine (GKE) and associated machine types, but the and CPU requirements should translate to most other providers. We hope to update this in the future with further specific cloud provider details. -| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory | -|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------| -| Webservice | 5 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 79.5 vCPU, 62 GB memory | -| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory | -| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory | - -<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix --> -<!-- markdownlint-disable MD029 --> -1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. - In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. -<!-- markdownlint-enable MD029 --> +| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory | +|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------| +| Webservice | 5 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 79.5 vCPU, 62 GB memory | +| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory | +| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory | + +- For this setup, we **recommend** and regularly [test](index.md#testing-process-and-results) +[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. +- Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**. + - In production deployments, there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices. Next are the backend components that run on static compute VMs via Omnibus (or External PaaS services where applicable): diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md index 582ffc9dc9c..752b5659d0e 100644 --- a/doc/administration/terraform_state.md +++ b/doc/administration/terraform_state.md @@ -101,6 +101,11 @@ The following settings are: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247042) in GitLab 13.9. +WARNING: +It's not possible to migrate Terraform state files from object storage back to local storage, +so proceed with caution. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/350187) +to change this behavior. + To migrate Terraform state files to object storage, follow the instructions below. - For Omnibus package installations: diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 07542dd73d4..a78744810e7 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -1270,6 +1270,16 @@ registry = Geo::SnippetRepositoryRegistry.find(registry_id) registry.replicator.send(:sync_repository) ``` +## Gitaly + +### Find available and used space + +A Gitaly storage resource can be polled through Rails to determine the available and used space. + +```ruby +Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics +``` + ## Generate Service Ping The [Service Ping Guide](../../development/service_ping/index.md) in our developer documentation diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 258af4c47d0..9de063eec6f 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -1619,10 +1619,12 @@ There can be [risks when disabling released features](../administration/feature_flags.md#risks-when-disabling-released-features). Refer to this feature's version history for more details. -`gitaly-backup` is used by the backup Rake task to create and restore repository backups from Gitaly. +The `gitaly-backup` binary is used by the backup Rake task to create and restore repository backups from Gitaly. `gitaly-backup` replaces the previous backup method that directly calls RPCs on Gitaly from GitLab. -The backup Rake task must be able to find this executable. It can be configured in Omnibus GitLab packages: +The backup Rake task must be able to find this executable. In most cases, you don't need to change +the path to the binary as it should work fine with the default path `/opt/gitlab/embedded/bin/gitaly-backup`. +If you have a specific reason to change the path, it can be configured in Omnibus GitLab packages: 1. Add the following to `/etc/gitlab/gitlab.rb`: diff --git a/doc/user/compliance/index.md b/doc/user/compliance/index.md index 61b65bf254f..7b46886e236 100644 --- a/doc/user/compliance/index.md +++ b/doc/user/compliance/index.md @@ -7,15 +7,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Compliance **(ULTIMATE)** -The compliance tools provided by GitLab let you keep an eye on various aspects of your project. The -following compliance tools are available: - -- [Compliance report](compliance_report/index.md): View recent merge request activity across - all projects in a group. This lets you see if merge requests were approved, and by whom. -- [License Compliance](license_compliance/index.md): Search your project's dependencies for their - licenses. This lets you determine if the licenses of your project's dependencies are compatible - with your project's license. -- [Compliance framework labels](../project/settings/index.md#compliance-frameworks): Label your projects that have unique compliance requirements. -- [Compliance pipelines](../project/settings/index.md#compliance-pipeline-configuration): Ensure that needed compliance jobs are always run for compliance-labeled projects. -- [Audit Events](../../administration/audit_events.md): Get visibility into individual actions that have taken place in your GitLab instance, group, or project. -- [Audit Reports](../../administration/audit_reports.md): Create and access reports based on the audit events that have occurred. Use pre-built GitLab reports or the API to build your own. +The compliance tools provided by GitLab help you keep an eye on various aspects of your project. For more information +on GitLab compliance features for projects, groups, and instances, see +[Compliance features](../../administration/compliance.md). diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md index 56c0963b4a3..b6ec130297e 100644 --- a/doc/user/compliance/license_compliance/index.md +++ b/doc/user/compliance/license_compliance/index.md @@ -5,7 +5,7 @@ group: Composition Analysis info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# License Compliance **(ULTIMATE)** +# License compliance **(ULTIMATE)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5483) in GitLab 11.0. diff --git a/lib/gitlab/database/gitlab_loose_foreign_keys.yml b/lib/gitlab/database/gitlab_loose_foreign_keys.yml index 1c45bfbd0dc..d4175f0e967 100644 --- a/lib/gitlab/database/gitlab_loose_foreign_keys.yml +++ b/lib/gitlab/database/gitlab_loose_foreign_keys.yml @@ -1,3 +1,4 @@ +--- dast_site_profiles_pipelines: - table: ci_pipelines column: ci_pipeline_id @@ -34,10 +35,18 @@ ci_daily_build_group_report_results: - table: namespaces column: group_id on_delete: async_delete +ci_freeze_periods: + - table: projects + column: project_id + on_delete: async_delete ci_pending_builds: - table: namespaces column: namespace_id on_delete: async_delete +ci_resource_groups: + - table: projects + column: project_id + on_delete: async_delete ci_runner_namespaces: - table: namespaces column: namespace_id diff --git a/lib/gitlab/gpg/commit.rb b/lib/gitlab/gpg/commit.rb index 59882e8d4f8..ab7de14b07a 100644 --- a/lib/gitlab/gpg/commit.rb +++ b/lib/gitlab/gpg/commit.rb @@ -102,7 +102,7 @@ module Gitlab end def verification_status(gpg_key) - return :multiple_signatures if multiple_signatures? && Feature.enabled?(:multiple_gpg_signatures, @commit.project, default_enabled: :yaml) + return :multiple_signatures if multiple_signatures? return :unknown_key unless gpg_key return :unverified_key unless gpg_key.verified? return :unverified unless verified_signature&.valid? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 23ecff3f0b6..178dd0a154c 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -18654,6 +18654,9 @@ msgstr "" msgid "Incident Management Limits" msgstr "" +msgid "Incident details" +msgstr "" + msgid "Incident template (optional)." msgstr "" diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb index 6315ef0bd22..4c77c515cfd 100644 --- a/qa/qa/resource/api_fabricator.rb +++ b/qa/qa/resource/api_fabricator.rb @@ -63,6 +63,10 @@ module QA process_api_response(parse_body(response)) end + def api_fabrication_http_method + @api_fabrication_http_method ||= :post + end + private def resource_web_url(resource) @@ -85,6 +89,8 @@ module QA raise ResourceNotFoundError, "Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`." end + @api_fabrication_http_method = :get # rubocop:disable Gitlab/ModuleWithInstanceVariables + response end diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb index 3b10e17e03b..b2b7e3b719f 100644 --- a/qa/qa/resource/base.rb +++ b/qa/qa/resource/base.rb @@ -94,10 +94,20 @@ module QA nil end + fabrication_http_method = if resource.api_fabrication_http_method == :get + if self.include?(Reusable) + "Retrieved for reuse" + else + "Retrieved" + end + else + "Built" + end + Support::FabricationTracker.save_fabrication(:"#{method}_fabrication", fabrication_time) Runtime::Logger.debug do msg = ["==#{'=' * parents.size}>"] - msg << "Built a #{name}" + msg << "#{fabrication_http_method} a #{name}" msg << resource_identifier if resource_identifier msg << "as a dependency of #{parents.last}" if parents.any? msg << "via #{method}" diff --git a/qa/qa/resource/bulk_import_group.rb b/qa/qa/resource/bulk_import_group.rb index e8dc2d291b8..a22529152e1 100644 --- a/qa/qa/resource/bulk_import_group.rb +++ b/qa/qa/resource/bulk_import_group.rb @@ -3,18 +3,21 @@ module QA module Resource class BulkImportGroup < Group - attributes :source_group_path, + attributes :source_group, + :destination_group, :import_id - attribute :destination_group_path do - source_group_path - end - attribute :access_token do api_client.personal_access_token end - alias_method :path, :source_group_path + # In most cases we will want to set path the same as source group + # but it can be set to a custom name as well when imported via API + attribute :destination_group_path do + source_group.path + end + # Can't define path as attribue since @path is set in base class initializer + alias_method :path, :destination_group_path delegate :gitlab_address, to: 'QA::Runtime::Scenario' @@ -51,9 +54,9 @@ module QA entities: [ { source_type: 'group_entity', - source_full_path: source_group_path, + source_full_path: source_group.full_path, destination_name: destination_group_path, - destination_namespace: sandbox.path + destination_namespace: sandbox.full_path } ] } diff --git a/qa/qa/resource/reusable_group.rb b/qa/qa/resource/reusable_group.rb new file mode 100644 index 00000000000..a4bd799e85c --- /dev/null +++ b/qa/qa/resource/reusable_group.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + module Resource + class ReusableGroup < Group + prepend Reusable + + def initialize + super + + @path = "reusable_group" + @description = "QA reusable group" + @reuse_as = :default_group + end + + # Confirms that the group can be reused + # + # @return [nil] returns nil unless an error is raised + def validate_reuse_preconditions + unless reused_path_unique? + raise ResourceReuseError, + "Reusable groups must have the same name. The group reused as #{reuse_as} has the path '#{path}' but it should be '#{self.class.resources[reuse_as].path}'" + end + end + + # Confirms that reuse of the resource did not change it in a way that breaks later reuse. This raises an error if + # the current group path doesn't match the original path. + def validate_reuse + reload! + + if api_resource[:path] != @path + raise ResourceReuseError, "The group now has the path '#{api_resource[:path]}' but it should be '#{path}'" + end + end + + # Checks if the group is being reused with the same path. + # + # @return [Boolean] true if the group's path is different from another group with the same reuse symbol (reuse_as) + def reused_path_unique? + return true unless self.class.resources.key?(reuse_as) + + self.class.resources[reuse_as].path == path + end + + # Overrides QA::Resource::Group#remove_via_api! to log a debug message stating that removal will happen after + # the suite completes rather than now. + # + # @return [nil] + def remove_via_api! + QA::Runtime::Logger.debug("#{self.class.name} - deferring removal until after suite") + end + end + end +end diff --git a/qa/qa/resource/reusable_project.rb b/qa/qa/resource/reusable_project.rb index 6b33bb9d65d..d2dfff8ad56 100644 --- a/qa/qa/resource/reusable_project.rb +++ b/qa/qa/resource/reusable_project.rb @@ -5,6 +5,12 @@ module QA class ReusableProject < Project prepend Reusable + attribute :group do + ReusableGroup.fabricate_via_api! do |resource| + resource.api_client = api_client + end + end + def initialize super diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb index 799a5f7eaf2..704ca4c8b61 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true module QA - # run only base UI validation on staging because test requires top level group creation which is problematic - # on staging environment - RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do + RSpec.describe 'Manage', :requires_admin do describe 'Gitlab migration' do let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } } let(:admin_api_client) { Runtime::API::Client.as_admin } @@ -22,9 +20,18 @@ module QA end end + let(:destination_group) do + Resource::Group.fabricate_via_api! do |group| + group.api_client = api_client + group.sandbox = sandbox + group.path = "destination-group-for-import-#{SecureRandom.hex(4)}" + end + end + let(:source_group) do - Resource::Sandbox.fabricate_via_api! do |group| + Resource::Group.fabricate_via_api! do |group| group.api_client = api_client + group.sandbox = sandbox group.path = "source-group-for-import-#{SecureRandom.hex(4)}" group.avatar = File.new('qa/fixtures/designs/tanuki.jpg', 'r') end @@ -33,8 +40,8 @@ module QA let(:imported_group) do Resource::BulkImportGroup.fabricate_via_api! do |group| group.api_client = api_client - group.sandbox = sandbox - group.source_group_path = source_group.path + group.sandbox = destination_group + group.source_group = source_group end end diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb index fe2e3c76ea3..8a2a382ac45 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb @@ -3,9 +3,7 @@ require_relative 'gitlab_project_migration_common' module QA - # run only base UI validation on staging because test requires top level group creation which is problematic - # on staging environment - RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do + RSpec.describe 'Manage', :requires_admin do describe 'Gitlab migration', quarantine: { only: { job: 'praefect' }, type: :investigating, diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb index 287623aef55..9dce9bff3c1 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb @@ -3,9 +3,7 @@ require_relative 'gitlab_project_migration_common' module QA - # run only base UI validation on staging because test requires top level group creation which is problematic - # on staging environment - RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do + RSpec.describe 'Manage', :requires_admin do describe 'Gitlab migration', quarantine: { only: { job: 'praefect' }, type: :investigating, diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb index b8f4f9d1016..b54cd2ff0fc 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb @@ -3,9 +3,7 @@ require_relative 'gitlab_project_migration_common' module QA - # run only base UI validation on staging because test requires top level group creation which is problematic - # on staging environment - RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do + RSpec.describe 'Manage', :requires_admin do describe 'Gitlab migration', quarantine: { only: { job: 'praefect' }, type: :investigating, diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb index c6f3c9a626f..827ebc1f5e2 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_project_migration_common.rb @@ -20,8 +20,16 @@ module QA end end + let(:destination_group) do + Resource::Group.fabricate_via_api! do |group| + group.api_client = api_client + group.sandbox = sandbox + group.path = "destination-group-for-import-#{SecureRandom.hex(4)}" + end + end + let(:source_group) do - Resource::Sandbox.fabricate_via_api! do |group| + Resource::Group.fabricate_via_api! do |group| group.api_client = api_client group.path = "source-group-for-import-#{SecureRandom.hex(4)}" end @@ -38,8 +46,8 @@ module QA let(:imported_group) do Resource::BulkImportGroup.fabricate_via_api! do |group| group.api_client = api_client - group.sandbox = sandbox - group.source_group_path = source_group.path + group.sandbox = destination_group + group.source_group = source_group end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb index aef843759f1..904f88e8c14 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/gitlab_migration_group_spec.rb @@ -36,7 +36,7 @@ module QA Resource::BulkImportGroup.init do |group| group.api_client = api_client group.sandbox = sandbox - group.source_group_path = source_group.path + group.source_group = source_group end end diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index d1a9ace605a..1d5df505743 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -597,6 +597,11 @@ FactoryBot.define do failure_reason { 13 } end + trait :deployment_rejected do + failed + failure_reason { 22 } + end + trait :with_runner_session do after(:build) do |build| build.build_runner_session(url: 'https://localhost') diff --git a/spec/frontend/boards/components/board_content_sidebar_spec.js b/spec/frontend/boards/components/board_content_sidebar_spec.js index 7b176cea2a3..368c7d561f8 100644 --- a/spec/frontend/boards/components/board_content_sidebar_spec.js +++ b/spec/frontend/boards/components/board_content_sidebar_spec.js @@ -9,6 +9,7 @@ import BoardContentSidebar from '~/boards/components/board_content_sidebar.vue'; import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue'; import { ISSUABLE } from '~/boards/constants'; import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue'; +import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue'; import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue'; import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue'; import SidebarLabelsWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue'; @@ -96,7 +97,7 @@ describe('BoardContentSidebar', () => { }); it('confirms we render MountingPortal', () => { - expect(wrapper.find(MountingPortal).props()).toMatchObject({ + expect(wrapper.findComponent(MountingPortal).props()).toMatchObject({ mountTo: '#js-right-sidebar-portal', append: true, name: 'board-content-sidebar', @@ -141,6 +142,10 @@ describe('BoardContentSidebar', () => { ); }); + it('does not render SidebarSeverity', () => { + expect(wrapper.findComponent(SidebarSeverity).exists()).toBe(false); + }); + describe('when we emit close', () => { let toggleBoardItem; @@ -160,4 +165,17 @@ describe('BoardContentSidebar', () => { }); }); }); + + describe('incident sidebar', () => { + beforeEach(() => { + createStore({ + mockGetters: { activeBoardItem: () => ({ ...mockIssue, epic: null, type: 'INCIDENT' }) }, + }); + createComponent(); + }); + + it('renders SidebarSeverity', () => { + expect(wrapper.findComponent(SidebarSeverity).exists()).toBe(true); + }); + }); }); diff --git a/spec/lib/gitlab/gpg/commit_spec.rb b/spec/lib/gitlab/gpg/commit_spec.rb index 20d5972bd88..9c399e78d80 100644 --- a/spec/lib/gitlab/gpg/commit_spec.rb +++ b/spec/lib/gitlab/gpg/commit_spec.rb @@ -233,30 +233,6 @@ RSpec.describe Gitlab::Gpg::Commit do verification_status: 'multiple_signatures' ) end - - context 'when feature flag is disabled' do - before do - stub_feature_flags(multiple_gpg_signatures: false) - end - - it 'returns an valid signature' do - verified_signature = double('verified-signature', fingerprint: GpgHelpers::User1.fingerprint, valid?: true) - allow(GPGME::Crypto).to receive(:new).and_return(crypto) - allow(crypto).to receive(:verify).and_yield(verified_signature).and_yield(verified_signature) - - signature = described_class.new(commit).signature - - expect(signature).to have_attributes( - commit_sha: commit_sha, - project: project, - gpg_key: gpg_key, - gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid, - gpg_key_user_name: GpgHelpers::User1.names.first, - gpg_key_user_email: GpgHelpers::User1.emails.first, - verification_status: 'verified' - ) - end - end end context 'commit signed with a subkey' do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 9d1fa006cf8..9db6fe0279a 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -2002,6 +2002,16 @@ RSpec.describe Ci::Build do it { is_expected.not_to be_retryable } end + + context 'when build is waiting for deployment approval' do + subject { build_stubbed(:ci_build, :manual, environment: 'production') } + + before do + create(:deployment, :blocked, deployable: subject) + end + + it { is_expected.not_to be_retryable } + end end end diff --git a/spec/models/ci/freeze_period_spec.rb b/spec/models/ci/freeze_period_spec.rb index f7f840c6696..b9bf1657e28 100644 --- a/spec/models/ci/freeze_period_spec.rb +++ b/spec/models/ci/freeze_period_spec.rb @@ -5,6 +5,11 @@ require 'spec_helper' RSpec.describe Ci::FreezePeriod, type: :model do subject { build(:ci_freeze_period) } + it_behaves_like 'cleanup by a loose foreign key' do + let!(:parent) { create(:project) } + let!(:model) { create(:ci_freeze_period, project: parent) } + end + let(:invalid_cron) { '0 0 0 * *' } it { is_expected.to belong_to(:project) } diff --git a/spec/models/ci/resource_group_spec.rb b/spec/models/ci/resource_group_spec.rb index aae16157fbf..76e74f3193c 100644 --- a/spec/models/ci/resource_group_spec.rb +++ b/spec/models/ci/resource_group_spec.rb @@ -3,6 +3,11 @@ require 'spec_helper' RSpec.describe Ci::ResourceGroup do + it_behaves_like 'cleanup by a loose foreign key' do + let!(:parent) { create(:project) } + let!(:model) { create(:ci_resource_group, project: parent) } + end + describe 'validation' do it 'valids when key includes allowed character' do resource_group = build(:ci_resource_group, key: 'test') diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb index 34f77260334..85ef8b60af4 100644 --- a/spec/services/ci/play_build_service_spec.rb +++ b/spec/services/ci/play_build_service_spec.rb @@ -122,7 +122,7 @@ RSpec.describe Ci::PlayBuildService, '#execute' do end context 'when build is not a playable manual action' do - let(:build) { create(:ci_build, when: :manual, pipeline: pipeline) } + let(:build) { create(:ci_build, :success, pipeline: pipeline) } let!(:branch) { create(:protected_branch, :developers_can_merge, name: build.ref, project: project) } it 'duplicates the build' do @@ -138,6 +138,18 @@ RSpec.describe Ci::PlayBuildService, '#execute' do expect(build.user).not_to eq user expect(duplicate.user).to eq user end + + context 'and is not retryable' do + let(:build) { create(:ci_build, :deployment_rejected, pipeline: pipeline) } + + it 'does not duplicate the build' do + expect { service.execute(build) }.not_to change { Ci::Build.count } + end + + it 'does not enqueue the build' do + expect { service.execute(build) }.not_to change { build.status } + end + end end context 'when build is not action' do diff --git a/spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb b/spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb deleted file mode 100644 index 535d078db63..00000000000 --- a/spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -RSpec.shared_examples 'renders registration features prompt' do |disabled_field, feature_title| - it 'renders a placeholder input with registration features message' do - render - - if disabled_field - expect(rendered).to have_field(disabled_field, disabled: true) - end - - expect(rendered).to have_content(s_("RegistrationFeatures|Want to %{feature_title} for free?") % { feature_title: feature_title || s_('RegistrationFeatures|use this feature') }) - expect(rendered).to have_link(s_('RegistrationFeatures|Registration Features Program')) - end -end - -RSpec.shared_examples 'does not render registration features prompt' do |disabled_field, feature_title| - it 'does not render a placeholder input with registration features message' do - render - - if disabled_field - expect(rendered).not_to have_field(disabled_field, disabled: true) - end - - expect(rendered).not_to have_content(s_("RegistrationFeatures|Want to %{feature_title} for free?") % { feature_title: feature_title || s_('RegistrationFeatures|use this feature') }) - expect(rendered).not_to have_link(s_('RegistrationFeatures|Registration Features Program')) - end -end diff --git a/spec/views/groups/edit.html.haml_spec.rb b/spec/views/groups/edit.html.haml_spec.rb index 748fe986d43..eaa909a5da0 100644 --- a/spec/views/groups/edit.html.haml_spec.rb +++ b/spec/views/groups/edit.html.haml_spec.rb @@ -139,7 +139,13 @@ RSpec.describe 'groups/edit.html.haml' do stub_application_setting(usage_ping_enabled: false) end - it_behaves_like 'renders registration features prompt', :group_disabled_ip_restriction_ranges + it 'renders a placeholder input with registration features message' do + render + + expect(rendered).to have_field(:group_disabled_ip_restriction_ranges, disabled: true) + expect(rendered).to have_content(s_("RegistrationFeatures|Want to %{feature_title} for free?") % { feature_title: s_('RegistrationFeatures|use this feature') }) + expect(rendered).to have_link(s_('RegistrationFeatures|Registration Features Program')) + end end context 'with service ping enabled' do @@ -147,7 +153,13 @@ RSpec.describe 'groups/edit.html.haml' do stub_application_setting(usage_ping_enabled: true) end - it_behaves_like 'does not render registration features prompt', :group_disabled_ip_restriction_ranges + it 'does not render a placeholder input with registration features message' do + render + + expect(rendered).not_to have_field(:group_disabled_ip_restriction_ranges, disabled: true) + expect(rendered).not_to have_content(s_("RegistrationFeatures|Want to %{feature_title} for free?") % { feature_title: s_('RegistrationFeatures|use this feature') }) + expect(rendered).not_to have_link(s_('RegistrationFeatures|Registration Features Program')) + end end end end |