Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
dd9af4e967
commit
413c6d807b
|
@ -97,6 +97,8 @@ rules:
|
|||
- error
|
||||
- selector: ImportSpecifier[imported.name='GlSkeletonLoading']
|
||||
message: 'Migrate to GlSkeletonLoader, or import GlDeprecatedSkeletonLoading.'
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/360551
|
||||
vue/multi-word-component-names: off
|
||||
overrides:
|
||||
- files:
|
||||
- '{,ee/,jh/}spec/frontend*/**/*'
|
||||
|
|
|
@ -122,7 +122,7 @@ export default {
|
|||
<div>
|
||||
<h3>{{ $options.i18n.yAxisTitle }}</h3>
|
||||
<gl-alert v-if="loadingError" variant="danger" :dismissible="false" class="gl-mt-3">
|
||||
{{ this.$options.i18n.loadUserChartError }}
|
||||
{{ $options.i18n.loadUserChartError }}
|
||||
</gl-alert>
|
||||
<chart-skeleton-loader v-else-if="isLoading" />
|
||||
<gl-alert v-else-if="!chartUserData.length" variant="info" :dismissible="false" class="gl-mt-3">
|
||||
|
|
|
@ -137,7 +137,7 @@ export default {
|
|||
v-model="freezeStartCron"
|
||||
class="gl-font-monospace!"
|
||||
data-qa-selector="deploy_freeze_start_field"
|
||||
:placeholder="this.$options.translations.cronPlaceholder"
|
||||
:placeholder="$options.translations.cronPlaceholder"
|
||||
:state="freezeStartCronState"
|
||||
trim
|
||||
/>
|
||||
|
@ -154,7 +154,7 @@ export default {
|
|||
v-model="freezeEndCron"
|
||||
class="gl-font-monospace!"
|
||||
data-qa-selector="deploy_freeze_end_field"
|
||||
:placeholder="this.$options.translations.cronPlaceholder"
|
||||
:placeholder="$options.translations.cronPlaceholder"
|
||||
:state="freezeEndCronState"
|
||||
trim
|
||||
/>
|
||||
|
|
|
@ -146,7 +146,7 @@ export default {
|
|||
{{ tableData.autoStop.title }}
|
||||
</div>
|
||||
</div>
|
||||
<template v-for="(model, i) in sortedEnvironments" :model="model">
|
||||
<template v-for="(model, i) in sortedEnvironments">
|
||||
<environment-item
|
||||
:key="`environment-item-${i}`"
|
||||
:model="model"
|
||||
|
|
|
@ -254,7 +254,7 @@ export default {
|
|||
data-testid="integrated-disabled-alert"
|
||||
@dismiss="isAlertDismissed = true"
|
||||
>
|
||||
<gl-sprintf :message="this.$options.i18n.integratedErrorTrackingDisabledText">
|
||||
<gl-sprintf :message="$options.i18n.integratedErrorTrackingDisabledText">
|
||||
<template #epicLink="{ content }">
|
||||
<gl-link :href="$options.epicLink" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
|
|
|
@ -152,7 +152,7 @@ export default {
|
|||
<template>
|
||||
<div>
|
||||
<gl-alert v-if="showIntegratedTrackingDisabledAlert" variant="danger" @dismiss="dismissAlert">
|
||||
<gl-sprintf :message="this.$options.i18n.integratedErrorTrackingDisabledText">
|
||||
<gl-sprintf :message="$options.i18n.integratedErrorTrackingDisabledText">
|
||||
<template #epicLink="{ content }">
|
||||
<gl-link :href="$options.epicLink" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
|
|
|
@ -116,7 +116,7 @@ export default {
|
|||
<div
|
||||
class="item-path-area item-path-id d-flex align-items-center mr-2 mt-2 mt-xl-0 ml-xl-2"
|
||||
>
|
||||
<gl-tooltip :target="() => this.$refs.iconElement">
|
||||
<gl-tooltip :target="() => $refs.iconElement">
|
||||
<span v-safe-html="stateTitle"></span>
|
||||
</gl-tooltip>
|
||||
<span v-gl-tooltip :title="itemPath" class="path-id-text d-inline-block">{{
|
||||
|
|
|
@ -187,7 +187,7 @@ export default {
|
|||
ref="searchBox"
|
||||
v-model.trim="searchQuery"
|
||||
class="gl-m-3"
|
||||
:placeholder="this.$options.translations.searchMilestones"
|
||||
:placeholder="$options.translations.searchMilestones"
|
||||
@input="onSearchBoxInput"
|
||||
@keydown.enter.prevent="onSearchBoxEnter"
|
||||
/>
|
||||
|
|
|
@ -76,7 +76,7 @@ export default {
|
|||
@click="handleClickCta"
|
||||
>
|
||||
<gl-emoji data-name="rocket" />
|
||||
{{ this.$options.i18n.ctaText }}
|
||||
{{ $options.i18n.ctaText }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</gl-popover>
|
||||
|
|
|
@ -338,9 +338,9 @@ export default {
|
|||
<slot
|
||||
v-else
|
||||
name="value"
|
||||
:attributeTitle="attributeTitle"
|
||||
:attributeUrl="attributeUrl"
|
||||
:currentAttribute="currentAttribute"
|
||||
:attribute-title="attributeTitle"
|
||||
:attribute-url="attributeUrl"
|
||||
:current-attribute="currentAttribute"
|
||||
>
|
||||
<gl-link
|
||||
v-gl-tooltip="tooltipText"
|
||||
|
@ -388,9 +388,9 @@ export default {
|
|||
<slot
|
||||
v-else
|
||||
name="list"
|
||||
:attributesList="attributesList"
|
||||
:isAttributeChecked="isAttributeChecked"
|
||||
:updateAttribute="updateAttribute"
|
||||
:attributes-list="attributesList"
|
||||
:is-attribute-checked="isAttributeChecked"
|
||||
:update-attribute="updateAttribute"
|
||||
>
|
||||
<gl-dropdown-item
|
||||
v-for="attrItem in attributesList"
|
||||
|
|
|
@ -217,7 +217,7 @@ export default {
|
|||
<slot
|
||||
:is-approving="isApproving"
|
||||
:approve-with-auth="approveWithAuth"
|
||||
:hasApproval-auth-error="hasApprovalAuthError"
|
||||
:has-approval-auth-error="hasApprovalAuthError"
|
||||
></slot>
|
||||
</template>
|
||||
</div>
|
||||
|
|
|
@ -29,7 +29,7 @@ export default {
|
|||
</template>
|
||||
|
||||
<template #default="{ listItem, query }">
|
||||
<slot :listItem="listItem" :query="query"></slot>
|
||||
<slot :list-item="listItem" :query="query"></slot>
|
||||
</template>
|
||||
</gl-paginated-list>
|
||||
</template>
|
||||
|
|
|
@ -42,6 +42,6 @@ export default {
|
|||
:class="cssClass"
|
||||
:title="tooltipTitle(time)"
|
||||
:datetime="time"
|
||||
><slot :timeAgo="timeAgo">{{ timeAgo }}</slot></time
|
||||
><slot :time-ago="timeAgo">{{ timeAgo }}</slot></time
|
||||
>
|
||||
</template>
|
||||
|
|
|
@ -160,7 +160,7 @@ export default {
|
|||
>
|
||||
<gl-icon name="upload" :size="iconStyles.size" :class="iconStyles.class" />
|
||||
<p class="gl-mb-0" data-testid="upload-text">
|
||||
<slot name="upload-text" :openFileUpload="openFileUpload">
|
||||
<slot name="upload-text" :open-file-upload="openFileUpload">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
singleFileSelection
|
||||
|
|
|
@ -174,7 +174,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
private
|
||||
|
||||
def certificate_based_clusters_enabled?
|
||||
Feature.enabled?(:certificate_based_clusters, clusterable, default_enabled: :yaml, type: :ops)
|
||||
Feature.enabled?(:certificate_based_clusters, clusterable.clusterable_namespace, default_enabled: :yaml, type: :ops)
|
||||
end
|
||||
|
||||
def ensure_feature_enabled!
|
||||
|
|
|
@ -61,7 +61,7 @@ class Import::GiteaController < Import::GithubController
|
|||
|
||||
override :client
|
||||
def client
|
||||
@client ||= Gitlab::LegacyGithubImport::Client.new(session[access_token_key], client_options)
|
||||
@client ||= Gitlab::LegacyGithubImport::Client.new(session[access_token_key], **client_options)
|
||||
end
|
||||
|
||||
override :client_options
|
||||
|
|
|
@ -468,7 +468,7 @@ module ApplicationSettingsHelper
|
|||
def instance_clusters_enabled?
|
||||
clusterable = Clusters::Instance.new
|
||||
|
||||
Feature.enabled?(:certificate_based_clusters, clusterable, default_enabled: :yaml, type: :ops) &&
|
||||
Feature.enabled?(:certificate_based_clusters, default_enabled: :yaml, type: :ops) &&
|
||||
can?(current_user, :read_cluster, clusterable)
|
||||
end
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ module ClustersHelper
|
|||
can_add_cluster: clusterable.can_add_cluster?.to_s,
|
||||
can_admin_cluster: clusterable.can_admin_cluster?.to_s,
|
||||
display_cluster_agents: display_cluster_agents?(clusterable).to_s,
|
||||
certificate_based_clusters_enabled: Feature.enabled?(:certificate_based_clusters, clusterable, default_enabled: :yaml, type: :ops).to_s,
|
||||
certificate_based_clusters_enabled: Feature.enabled?(:certificate_based_clusters, clusterable.clusterable_namespace, default_enabled: :yaml, type: :ops).to_s,
|
||||
default_branch_name: default_branch_name(clusterable),
|
||||
project_path: clusterable_project_path(clusterable),
|
||||
kas_address: Gitlab::Kas.external_url,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
module DeploymentPlatform
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
def deployment_platform(environment: nil)
|
||||
return if Feature.disabled?(:certificate_based_clusters, default_enabled: :yaml, type: :ops)
|
||||
return if Feature.disabled?(:certificate_based_clusters, self.namespace, default_enabled: :yaml, type: :ops)
|
||||
|
||||
@deployment_platform ||= {}
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated
|
|||
.fabricate!
|
||||
end
|
||||
|
||||
def clusterable_namespace
|
||||
return clusterable.namespace if clusterable.is_a?(Project)
|
||||
return clusterable if clusterable.is_a?(Group)
|
||||
end
|
||||
|
||||
def can_add_cluster?
|
||||
can?(current_user, :add_cluster, clusterable)
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
= _('Variables can be:')
|
||||
%ul
|
||||
%li
|
||||
= html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
= html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or protected tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
%li
|
||||
= html_escape(_('%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
= link_to _('Learn more.'), help_page_path('ci/variables/index', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
= _('Variables can be:')
|
||||
%ul
|
||||
%li
|
||||
= html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
= html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or protected tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
%li
|
||||
= html_escape(_('%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
= link_to _('Learn more.'), help_page_path('ci/variables/index', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
|
||||
|
|
|
@ -2,31 +2,6 @@
|
|||
- import_url = Gitlab::UrlSanitizer.new(f.object.import_url)
|
||||
|
||||
.import-url-data
|
||||
.form-group
|
||||
= f.label :import_url, class: 'label-bold' do
|
||||
%span
|
||||
= _('Git repository URL')
|
||||
= f.text_field :import_url, value: import_url.sanitized_url,
|
||||
autocomplete: 'off', class: 'form-control gl-form-input', placeholder: 'https://gitlab.company.com/group/project.git', required: true
|
||||
= render Pajamas::AlertComponent.new(variant: :danger,
|
||||
alert_class: 'gl-mt-3 js-import-url-error hide',
|
||||
dismissible: false,
|
||||
close_button_class: 'js-close-2fa-enabled-success-alert') do
|
||||
.gl-alert-body
|
||||
= s_('Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials.')
|
||||
.row
|
||||
.form-group.col-md-6
|
||||
= f.label :import_url_user, class: 'label-bold' do
|
||||
%span
|
||||
= _('Username (optional)')
|
||||
= f.text_field :import_url_user, value: import_url.user, class: 'form-control gl-form-input', required: false, autocomplete: 'new-password'
|
||||
|
||||
.form-group.col-md-6
|
||||
= f.label :import_url_password, class: 'label-bold' do
|
||||
%span
|
||||
= _('Password (optional)')
|
||||
= f.password_field :import_url_password, class: 'form-control gl-form-input', required: false, autocomplete: 'new-password'
|
||||
|
||||
.info-well.prepend-top-20
|
||||
.well-segment
|
||||
%ul
|
||||
|
@ -40,5 +15,28 @@
|
|||
%li
|
||||
= import_svn_message(ci_cd_only)
|
||||
= render_if_exists 'shared/ci_cd_only_link', ci_cd_only: ci_cd_only
|
||||
.form-group
|
||||
= f.label :import_url, class: 'label-bold' do
|
||||
%span
|
||||
= _('Git repository URL')
|
||||
= f.text_field :import_url, value: import_url.sanitized_url,
|
||||
autocomplete: 'off', class: 'form-control gl-form-input', placeholder: 'https://gitlab.company.com/group/project.git', required: true
|
||||
= render Pajamas::AlertComponent.new(variant: :danger,
|
||||
alert_class: 'gl-mt-3 js-import-url-error hide',
|
||||
dismissible: false,
|
||||
close_button_class: 'js-close-2fa-enabled-success-alert') do
|
||||
.gl-alert-body
|
||||
= s_('Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials.')
|
||||
= render_if_exists 'shared/ee/import_form', f: f, ci_cd_only: ci_cd_only
|
||||
.row
|
||||
.form-group.col-md-6
|
||||
= f.label :import_url_user, class: 'label-bold' do
|
||||
%span
|
||||
= _('Username (optional)')
|
||||
= f.text_field :import_url_user, value: import_url.user, class: 'form-control gl-form-input', required: false, autocomplete: 'new-password'
|
||||
|
||||
= render_if_exists 'shared/ee/import_form', f: f, ci_cd_only: ci_cd_only
|
||||
.form-group.col-md-6
|
||||
= f.label :import_url_password, class: 'label-bold' do
|
||||
%span
|
||||
= _('Password (optional)')
|
||||
= f.password_field :import_url_password, class: 'form-control gl-form-input', required: false, autocomplete: 'new-password'
|
||||
|
|
|
@ -3114,7 +3114,7 @@
|
|||
:worker_name: WebHooks::DestroyWorker
|
||||
:feature_category: :integrations
|
||||
:has_external_dependencies:
|
||||
:urgency: :low
|
||||
:urgency: :high
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
|
|
|
@ -7,7 +7,7 @@ module WebHooks
|
|||
data_consistency :always
|
||||
sidekiq_options retry: 3
|
||||
feature_category :integrations
|
||||
urgency :low
|
||||
urgency :high
|
||||
|
||||
idempotent!
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: ci_minutes_cost_factor_for_all_public_projects
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85357
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359094
|
||||
milestone: '15.0'
|
||||
type: development
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
|
@ -21,7 +21,10 @@ Marginalia::Comment.components = [:application, :correlation_id, :jid, :endpoint
|
|||
# we've seen it slow things down.
|
||||
if Rails.env.development?
|
||||
Marginalia::Comment.components << :line
|
||||
Marginalia::Comment.lines_to_ignore = Regexp.union(Gitlab::BacktraceCleaner::IGNORE_BACKTRACES + %w(lib/ruby/gems/ lib/gem_extensions/ lib/ruby/))
|
||||
Marginalia::Comment.lines_to_ignore = Regexp.union(
|
||||
Gitlab::BacktraceCleaner::IGNORE_BACKTRACES + %w[
|
||||
lib/ruby/gems/ lib/gem_extensions/ lib/ruby/ lib/gitlab/marginalia/ gems/
|
||||
])
|
||||
end
|
||||
|
||||
Gitlab::Marginalia.set_application_name
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
- name: "SaaS certificate-based integration with Kubernetes"
|
||||
announcement_milestone: "14.5"
|
||||
announcement_date: "2021-11-15"
|
||||
removal_milestone: "15.0"
|
||||
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
|
||||
removal_milestone: "15.6"
|
||||
removal_date: "2022-11-22" # the date of the milestone release when this feature is planned to be removed
|
||||
breaking_change: true
|
||||
body: |
|
||||
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0.
|
||||
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace. The integrations are expected to be switched off completely on GitLab SaaS around 2022 November 22.
|
||||
|
||||
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
|
||||
[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
- name: "Self-managed certificate-based integration with Kubernetes"
|
||||
announcement_milestone: "14.5"
|
||||
announcement_date: "2021-11-15"
|
||||
removal_milestone: "15.6"
|
||||
removal_date: "2022-11-22" # the date of the milestone release when this feature is planned to be removed
|
||||
removal_milestone: "16.0"
|
||||
removal_date: "2023-05-22" # the date of the milestone release when this feature is planned to be removed
|
||||
breaking_change: true
|
||||
body: |
|
||||
The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
|
||||
|
||||
As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
|
||||
|
||||
In GitLab 15.6 we will remove both the feature, and its related code. Until the final removal in 15.6, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
|
||||
In GitLab 16.0 we will remove both the feature and its related code. Until the final removal in 16.0, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
|
||||
|
||||
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
|
||||
[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
|
||||
|
|
|
@ -1227,6 +1227,16 @@ where `password` is a public access key with the `api` scope enabled.
|
|||
POST /projects
|
||||
```
|
||||
|
||||
Example request:
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your-token>" \
|
||||
--header "Content-Type: application/json" --data '{
|
||||
"name": "new_project", "description": "New Project", "path": "new_project",
|
||||
"namespace_id": "42", "initialize_with_readme": "true"}' \
|
||||
--url 'https://gitlab.example.com/api/v4/projects/'
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|-------------------------------------------------------------|---------|------------------------|-------------|
|
||||
| `name` | string | **{check-circle}** Yes (if path isn't provided) | The name of the new project. Equals path if not provided. |
|
||||
|
@ -1253,8 +1263,8 @@ POST /projects
|
|||
| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
|
||||
| `forking_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
|
||||
| `group_with_project_templates_id` **(PREMIUM)** | integer | **{dotted-circle}** No | For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true. |
|
||||
| `import_url` | string | **{dotted-circle}** No | URL to import repository from. |
|
||||
| `initialize_with_readme` | boolean | **{dotted-circle}** No | `false` by default. |
|
||||
| `import_url` | string | **{dotted-circle}** No | URL to import repository from. When this isn't empty, you must not set `initialize_with_readme` to `true`. Doing so might result in the [following error](https://gitlab.com/gitlab-org/gitlab/-/issues/360266): `not a git repository`. |
|
||||
| `initialize_with_readme` | boolean | **{dotted-circle}** No | Whether to create a Git repository with just a `README.md` file. Default is `false`. When this is true, you must not pass `import_url` or other attributes of this endpoint which specify alternative contents for the repository. Doing so might result in the [following error](https://gitlab.com/gitlab-org/gitlab/-/issues/360266): `not a git repository`. |
|
||||
| `issues_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
|
||||
| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
|
||||
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
|
||||
|
|
|
@ -9,11 +9,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
When you use SaaS runners on macOS:
|
||||
|
||||
- Each of your jobs runs in a newly provisioned VM, which is dedicated to the specific job.
|
||||
- The VM is active only for the duration of the job and immediately deleted.
|
||||
- The VM is active only for the duration of the job and immediately deleted. This means that any changes that your job makes to the virtual machine will not be available to a subsequent job.
|
||||
- The virtual machine where your job runs has `sudo` access with no password.
|
||||
|
||||
NOTE:
|
||||
Each time you run a job that requires tooling or dependencies not available in the base image, those items must be added to the newly provisioned build VM. That process will likely increase the total job duration.
|
||||
|
||||
## VM types
|
||||
|
||||
The virtual machine where your job runs has `sudo` access with no password.
|
||||
GitLab SaaS provides macOS build machines on Apple servers with Intel x86-64 processors.
|
||||
The expectation is that virtual machines running on the Apple M1 chip will be available in the second half of 2022.
|
||||
|
||||
For the [Beta](../../../../policy/alpha-beta-support.md#beta-features), there is only one available machine type, `gbc-macos-large`.
|
||||
|
||||
| Instance type | vCPUS | Memory (GB) |
|
||||
|
@ -22,23 +28,34 @@ For the [Beta](../../../../policy/alpha-beta-support.md#beta-features), there is
|
|||
|
||||
## VM images
|
||||
|
||||
### Image update policy
|
||||
|
||||
GitLab expects to release new images based on this cadence:
|
||||
|
||||
macOS updates:
|
||||
|
||||
- **For new OS versions:** When Apple releases a new macOS version to developers (like macOS `12`), GitLab will plan to release an image based on the OS within the next 30 business days. The image is considered `beta` and the contents of the image (including tool versions) are subject to change until the first patch release (`12.1`). The long-term name will not include `beta` (for example, `macos-12-xcode-13`), so customers are moved automatically out of beta over time. GitLab will try to minimize breaking changes between the first two minor versions but makes no guarantees. Tooling often gets critical bug fixes after the first public release of an OS version.
|
||||
|
||||
- **After the first patch release (`12.1`):**
|
||||
- The image moves to `maintenance` mode. The tools GitLab builds into the image with Homebrew and asdf are frozen. GitLab continues making Xcode updates, security updates, and any non-breaking changes deemed necessary.
|
||||
- The image for the previous OS version (`11`) moves to `frozen` mode. GitLab then does only unavoidable changes: security updates, runner version upgrades, and setting the production password.
|
||||
|
||||
Both macOS and Xcode follow a yearly release cadence. As time goes on, GitLab increments their versions synchronously (meaning we build macOS 11 with Xcode 12, macOS 12 with Xcode 13, and so on).
|
||||
|
||||
### Available images
|
||||
|
||||
You can execute your build on one of the following images.
|
||||
You specify this image in your `.gitlab-ci.yml` file.
|
||||
|
||||
Each image is running a specific version of macOS and Xcode.
|
||||
|
||||
| VM image | Included software |
|
||||
|---------------------------|--------------------|
|
||||
| macos-10.13-xcode-7 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
|
||||
| macos-10.13-xcode-8 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
|
||||
| macos-10.13-xcode-9 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
|
||||
| macos-10.14-xcode-10 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
|
||||
| macos-10.15-xcode-11 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
|
||||
| macos-11-xcode-12 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
|
||||
| macos-11-xcode-13 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml>
|
||||
|
||||
### Image update policy
|
||||
|
||||
- Support for new macOS versions is planned.
|
||||
- Additional details on the support policy and image update release process are documented
|
||||
[in this project](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/55bf59c8fa88712960afff2bf6ecc5daa879a8f5/docs/overview.md#os-images).
|
||||
| VM image | Status | Included software |
|
||||
|---------------------------|--------|--------------------|
|
||||
| `macos-10.13-xcode-7` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
|
||||
| `macos-10.13-xcode-8` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
|
||||
| `macos-10.13-xcode-9` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
|
||||
| `macos-10.14-xcode-10` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
|
||||
| `macos-10.15-xcode-11` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
|
||||
| `macos-11-xcode-12` | `frozen` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
|
||||
| `macos-12-xcode-13` | `maintenance` | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/monterey.yml> |
|
||||
| (none, awaiting macOS 13) | `beta` | |
|
||||
|
|
|
@ -1,319 +1,11 @@
|
|||
---
|
||||
type: reference, dev
|
||||
stage: Enablement
|
||||
group: Database
|
||||
info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
|
||||
redirect_to: 'database/batched_background_migrations.md'
|
||||
remove_date: '2022-07-26'
|
||||
---
|
||||
|
||||
# Batched background migrations
|
||||
This document was moved to [another location](database/batched_background_migrations.md).
|
||||
|
||||
Batched Background Migrations should be used to perform data migrations whenever a
|
||||
migration exceeds [the time limits](migration_style_guide.md#how-long-a-migration-should-take)
|
||||
in our guidelines. For example, you can use batched background
|
||||
migrations to migrate data that's stored in a single JSON column
|
||||
to a separate table instead.
|
||||
|
||||
## When to use batched background migrations
|
||||
|
||||
Use a batched background migration when you migrate _data_ in tables containing
|
||||
so many rows that the process would exceed
|
||||
[the time limits in our guidelines](migration_style_guide.md#how-long-a-migration-should-take)
|
||||
if performed using a regular Rails migration.
|
||||
|
||||
- Batched background migrations should be used when migrating data in
|
||||
[high-traffic tables](migration_style_guide.md#high-traffic-tables).
|
||||
- Batched background migrations may also be used when executing numerous single-row queries
|
||||
for every item on a large dataset. Typically, for single-record patterns, runtime is
|
||||
largely dependent on the size of the dataset. Split the dataset accordingly,
|
||||
and put it into background migrations.
|
||||
- Don't use batched background migrations to perform schema migrations.
|
||||
|
||||
Background migrations can help when:
|
||||
|
||||
- Migrating events from one table to multiple separate tables.
|
||||
- Populating one column based on JSON stored in another column.
|
||||
- Migrating data that depends on the output of external services. (For example, an API.)
|
||||
|
||||
NOTE:
|
||||
If the batched background migration is part of an important upgrade, it must be announced
|
||||
in the release post. Discuss with your Project Manager if you're unsure if the migration falls
|
||||
into this category.
|
||||
|
||||
## Isolation
|
||||
|
||||
Batched background migrations must be isolated and can not use application code. (For example,
|
||||
models defined in `app/models`.). Because these migrations can take a long time to
|
||||
run, it's possible for new versions to deploy while the migrations are still running.
|
||||
|
||||
## Idempotence
|
||||
|
||||
Batched background migrations are executed in a context of a Sidekiq process.
|
||||
The usual Sidekiq rules apply, especially the rule that jobs should be small
|
||||
and idempotent. Make sure that in case that your migration job is retried, data
|
||||
integrity is guaranteed.
|
||||
|
||||
See [Sidekiq best practices guidelines](https://github.com/mperham/sidekiq/wiki/Best-Practices)
|
||||
for more details.
|
||||
|
||||
## Batched background migrations for EE-only features
|
||||
|
||||
All the background migration classes for EE-only features should be present in GitLab CE.
|
||||
For this purpose, create an empty class for GitLab CE, and extend it for GitLab EE
|
||||
as explained in the guidelines for
|
||||
[implementing Enterprise Edition features](ee_features.md#code-in-libgitlabbackground_migration).
|
||||
|
||||
Batched Background migrations are simple classes that define a `perform` method. A
|
||||
Sidekiq worker then executes such a class, passing any arguments to it. All
|
||||
migration classes must be defined in the namespace
|
||||
`Gitlab::BackgroundMigration`. Place the files in the directory
|
||||
`lib/gitlab/background_migration/`.
|
||||
|
||||
## Queueing
|
||||
|
||||
Queueing a batched background migration should be done in a post-deployment
|
||||
migration. Use this `queue_batched_background_migration` example, queueing the
|
||||
migration to be executed in batches. Replace the class name and arguments with the values
|
||||
from your migration:
|
||||
|
||||
```ruby
|
||||
queue_batched_background_migration(
|
||||
JOB_CLASS_NAME,
|
||||
TABLE_NAME,
|
||||
JOB_ARGUMENTS,
|
||||
JOB_INTERVAL
|
||||
)
|
||||
```
|
||||
|
||||
Make sure the newly-created data is either migrated, or
|
||||
saved in both the old and new version upon creation. Removals in
|
||||
turn can be handled by defining foreign keys with cascading deletes.
|
||||
|
||||
### Requeuing batched background migrations
|
||||
|
||||
If one of the batched background migrations contains a bug that is fixed in a patch
|
||||
release, you must requeue the batched background migration so the migration
|
||||
repeats on systems that already performed the initial migration.
|
||||
|
||||
When you requeue the batched background migration, turn the original
|
||||
queuing into a no-op by clearing up the `#up` and `#down` methods of the
|
||||
migration performing the requeuing. Otherwise, the batched background migration is
|
||||
queued multiple times on systems that are upgrading multiple patch releases at
|
||||
once.
|
||||
|
||||
When you start the second post-deployment migration, delete the
|
||||
previously batched migration with the provided code:
|
||||
|
||||
```ruby
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION_NAME, TABLE_NAME, COLUMN, JOB_ARGUMENTS)
|
||||
.delete_all
|
||||
```
|
||||
|
||||
## Cleaning up
|
||||
|
||||
NOTE:
|
||||
Cleaning up any remaining background migrations must be done in either a major
|
||||
or minor release. You must not do this in a patch release.
|
||||
|
||||
Because background migrations can take a long time, you can't immediately clean
|
||||
things up after queueing them. For example, you can't drop a column used in the
|
||||
migration process, as jobs would fail. You must add a separate _post-deployment_
|
||||
migration in a future release that finishes any remaining
|
||||
jobs before cleaning things up. (For example, removing a column.)
|
||||
|
||||
To migrate the data from column `foo` (containing a big JSON blob) to column `bar`
|
||||
(containing a string), you would:
|
||||
|
||||
1. Release A:
|
||||
1. Create a migration class that performs the migration for a row with a given ID.
|
||||
1. Update new rows using one of these techniques:
|
||||
- Create a new trigger for simple copy operations that don't need application logic.
|
||||
- Handle this operation in the model/service as the records are created or updated.
|
||||
- Create a new custom background job that updates the records.
|
||||
1. Queue the batched background migration for all existing rows in a post-deployment migration.
|
||||
1. Release B:
|
||||
1. Add a post-deployment migration that checks if the batched background migration is completed.
|
||||
1. Deploy code so that the application starts using the new column and stops to update new records.
|
||||
1. Remove the old column.
|
||||
|
||||
Bump to the [import/export version](../user/project/settings/import_export.md) may
|
||||
be required, if importing a project from a prior version of GitLab requires the
|
||||
data to be in the new format.
|
||||
|
||||
## Example
|
||||
|
||||
The table `integrations` has a field called `properties`, stored in JSON. For all rows,
|
||||
extract the `url` key from this JSON object and store it in the `integrations.url`
|
||||
column. Millions of integrations exist, and parsing JSON is slow, so you can't
|
||||
do this work in a regular migration.
|
||||
|
||||
1. Start by defining our migration class:
|
||||
|
||||
```ruby
|
||||
class Gitlab::BackgroundMigration::ExtractIntegrationsUrl
|
||||
class Integration < ActiveRecord::Base
|
||||
self.table_name = 'integrations'
|
||||
end
|
||||
|
||||
def perform(start_id, end_id)
|
||||
Integration.where(id: start_id..end_id).each do |integration|
|
||||
json = JSON.load(integration.properties)
|
||||
|
||||
integration.update(url: json['url']) if json['url']
|
||||
rescue JSON::ParserError
|
||||
# If the JSON is invalid we don't want to keep the job around forever,
|
||||
# instead we'll just leave the "url" field to whatever the default value
|
||||
# is.
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
NOTE:
|
||||
To get a `connection` in the batched background migration,use an inheritance
|
||||
relation using the following base class `Gitlab::BackgroundMigration::BaseJob`.
|
||||
For example: `class Gitlab::BackgroundMigration::ExtractIntegrationsUrl < Gitlab::BackgroundMigration::BaseJob`
|
||||
|
||||
1. Add a new trigger to the database to update newly created and updated integrations,
|
||||
similar to this example:
|
||||
|
||||
```ruby
|
||||
execute(<<~SQL)
|
||||
CREATE OR REPLACE FUNCTION example() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW."url" := NEW.properties -> "url"
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
SQL
|
||||
```
|
||||
|
||||
1. Create a post-deployment migration that queues the migration for existing data:
|
||||
|
||||
```ruby
|
||||
class QueueExtractIntegrationsUrl < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
MIGRATION = 'ExtractIntegrationsUrl'
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:integrations,
|
||||
:id,
|
||||
job_interval: DELAY_INTERVAL
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :integrations, :id, []).delete_all
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
After deployment, our application:
|
||||
- Continues using the data as before.
|
||||
- Ensures that both existing and new data are migrated.
|
||||
|
||||
1. In the next release, remove the trigger. We must also add a new post-deployment migration
|
||||
that checks that the batched background migration is completed. For example:
|
||||
|
||||
```ruby
|
||||
class FinalizeExtractIntegrationsUrlJobs < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'ExtractIntegrationsUrl'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: MIGRATION,
|
||||
table_name: :integrations,
|
||||
column_name: :id,
|
||||
job_arguments: []
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
If the application does not depend on the data being 100% migrated (for
|
||||
instance, the data is advisory, and not mission-critical), then you can skip this
|
||||
final step. This step confirms that the migration is completed, and all of the rows were migrated.
|
||||
|
||||
After the batched migration is completed, you can safely remove the `integrations.properties` column.
|
||||
|
||||
## Testing
|
||||
|
||||
Writing tests is required for:
|
||||
|
||||
- The batched background migrations' queueing migration.
|
||||
- The batched background migration itself.
|
||||
- A cleanup migration.
|
||||
|
||||
The `:migration` and `schema: :latest` RSpec tags are automatically set for
|
||||
background migration specs. Refer to the
|
||||
[Testing Rails migrations](testing_guide/testing_migrations_guide.md#testing-a-non-activerecordmigration-class)
|
||||
style guide.
|
||||
|
||||
Remember that `before` and `after` RSpec hooks
|
||||
migrate your database down and up. These hooks can result in other batched background
|
||||
migrations being called. Using `spy` test doubles with
|
||||
`have_received` is encouraged, instead of using regular test doubles, because
|
||||
your expectations defined in a `it` block can conflict with what is
|
||||
called in RSpec hooks. Refer to [issue #35351](https://gitlab.com/gitlab-org/gitlab/-/issues/18839)
|
||||
for more details.
|
||||
|
||||
## Best practices
|
||||
|
||||
1. Know how much data you're dealing with.
|
||||
1. Make sure the batched background migration jobs are idempotent.
|
||||
1. Confirm the tests you write are not false positives.
|
||||
1. If the data being migrated is critical and cannot be lost, the
|
||||
clean-up migration must also check the final state of the data before completing.
|
||||
1. Discuss the numbers with a database specialist. The migration may add
|
||||
more pressure on DB than you expect. Measure on staging,
|
||||
or ask someone to measure on production.
|
||||
1. Know how much time is required to run the batched background migration.
|
||||
|
||||
## Additional tips and strategies
|
||||
|
||||
### Viewing failure error logs
|
||||
|
||||
You can view failures in two ways:
|
||||
|
||||
- Via GitLab logs:
|
||||
1. After running a batched background migration, if any jobs fail,
|
||||
view the logs in [Kibana](https://log.gprd.gitlab.net/goto/5f06a57f768c6025e1c65aefb4075694).
|
||||
View the production Sidekiq log and filter for:
|
||||
|
||||
- `json.new_state: failed`
|
||||
- `json.job_class_name: <Batched Background Migration job class name>`
|
||||
- `json.job_arguments: <Batched Background Migration job class arguments>`
|
||||
|
||||
1. Review the `json.exception_class` and `json.exception_message` values to help
|
||||
understand why the jobs failed.
|
||||
|
||||
1. Remember the retry mechanism. Having a failure does not mean the job failed.
|
||||
Always check the last status of the job.
|
||||
|
||||
- Via database:
|
||||
|
||||
1. Get the batched background migration `CLASS_NAME`.
|
||||
1. Execute the following query in the PostgreSQL console:
|
||||
|
||||
```sql
|
||||
SELECT migration.id, migration.job_class_name, transition_logs.exception_class, transition_logs.exception_message
|
||||
FROM batched_background_migrations as migration
|
||||
INNER JOIN batched_background_migration_jobs as jobs
|
||||
ON jobs.batched_background_migration_id = migration.id
|
||||
INNER JOIN batched_background_migration_job_transition_logs as transition_logs
|
||||
ON transition_logs.batched_background_migration_job_id = jobs.id
|
||||
WHERE transition_logs.next_status = '2' AND migration.job_class_name = "CLASS_NAME";
|
||||
```
|
||||
<!-- This redirect file can be deleted after <2022-07-26>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
|
@ -68,10 +68,72 @@ In this example, the change to ignore the column went into release 12.5.
|
|||
|
||||
Continuing our example, dropping the column goes into a _post-deployment_ migration in release 12.6:
|
||||
|
||||
```ruby
|
||||
remove_column :user, :updated_at
|
||||
Start by creating the **post-deployment migration**:
|
||||
|
||||
```shell
|
||||
bundle exec rails g post_deployment_migration remove_users_updated_at_column
|
||||
```
|
||||
|
||||
There are two scenarios that you need to consider
|
||||
to write a migration that removes a column:
|
||||
|
||||
#### A. The removed column has no indexes or constraints that belong to it
|
||||
|
||||
In this case, a **transactional migration** can be used. Something as simple as:
|
||||
|
||||
```ruby
|
||||
class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[2.0]
|
||||
def up
|
||||
remove_column :users, :updated_at
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :users, :updated_at, :datetime
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
You can consider [enabling lock retries](
|
||||
https://docs.gitlab.com/ee/development/migration_style_guide.html#usage-with-transactional-migrations
|
||||
) when you run a migration on big tables, because it might take some time to
|
||||
acquire a lock on this table.
|
||||
|
||||
#### B. The removed column has an index or constraint that belongs to it
|
||||
|
||||
If the `down` method requires adding back any dropped indexes or constraints, that cannot
|
||||
be done within a transactional migration, then the migration would look like this:
|
||||
|
||||
```ruby
|
||||
class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
remove_column :users, :updated_at
|
||||
end
|
||||
|
||||
def down
|
||||
unless column_exists?(:users, :updated_at)
|
||||
add_column :users, :updated_at, :datetime
|
||||
end
|
||||
|
||||
# Make sure to add back any indexes or constraints,
|
||||
# that were dropped in the `up` method. For example:
|
||||
add_concurrent_index(:users, :updated_at)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
In the `down` method, we check to see if the column already exists before adding it again.
|
||||
We do this because the migration is non-transactional and might have failed while it was running.
|
||||
|
||||
The [`disable_ddl_transaction!`](
|
||||
https://docs.gitlab.com/ee/development/migration_style_guide.html#usage-with-non-transactional-migrations-disable_ddl_transaction
|
||||
) is used to disable the transaction that wraps the whole migration.
|
||||
|
||||
You can refer to the page [Migration Style Guide](
|
||||
https://docs.gitlab.com/ee/development/migration_style_guide.html
|
||||
) for more information about database migrations.
|
||||
|
||||
### Step 3: Removing the ignore rule (release M+2)
|
||||
|
||||
With the next release, in this example 12.7, we set up another merge request to remove the ignore rule.
|
||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
# Background migrations
|
||||
|
||||
WARNING:
|
||||
Background migrations are strongly discouraged in favor of the new [batched background migrations framework](../batched_background_migrations.md).
|
||||
Background migrations are strongly discouraged in favor of the new [batched background migrations framework](batched_background_migrations.md).
|
||||
Please check that documentation and determine if that framework suits your needs and fall back
|
||||
to these only if required.
|
||||
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
---
|
||||
type: reference, dev
|
||||
stage: Enablement
|
||||
group: Database
|
||||
info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
|
||||
---
|
||||
|
||||
# Batched background migrations
|
||||
|
||||
Batched Background Migrations should be used to perform data migrations whenever a
|
||||
migration exceeds [the time limits](../migration_style_guide.md#how-long-a-migration-should-take)
|
||||
in our guidelines. For example, you can use batched background
|
||||
migrations to migrate data that's stored in a single JSON column
|
||||
to a separate table instead.
|
||||
|
||||
## When to use batched background migrations
|
||||
|
||||
Use a batched background migration when you migrate _data_ in tables containing
|
||||
so many rows that the process would exceed
|
||||
[the time limits in our guidelines](../migration_style_guide.md#how-long-a-migration-should-take)
|
||||
if performed using a regular Rails migration.
|
||||
|
||||
- Batched background migrations should be used when migrating data in
|
||||
[high-traffic tables](../migration_style_guide.md#high-traffic-tables).
|
||||
- Batched background migrations may also be used when executing numerous single-row queries
|
||||
for every item on a large dataset. Typically, for single-record patterns, runtime is
|
||||
largely dependent on the size of the dataset. Split the dataset accordingly,
|
||||
and put it into background migrations.
|
||||
- Don't use batched background migrations to perform schema migrations.
|
||||
|
||||
Background migrations can help when:
|
||||
|
||||
- Migrating events from one table to multiple separate tables.
|
||||
- Populating one column based on JSON stored in another column.
|
||||
- Migrating data that depends on the output of external services. (For example, an API.)
|
||||
|
||||
NOTE:
|
||||
If the batched background migration is part of an important upgrade, it must be announced
|
||||
in the release post. Discuss with your Project Manager if you're unsure if the migration falls
|
||||
into this category.
|
||||
|
||||
## Isolation
|
||||
|
||||
Batched background migrations must be isolated and can not use application code. (For example,
|
||||
models defined in `app/models`.). Because these migrations can take a long time to
|
||||
run, it's possible for new versions to deploy while the migrations are still running.
|
||||
|
||||
## Idempotence
|
||||
|
||||
Batched background migrations are executed in a context of a Sidekiq process.
|
||||
The usual Sidekiq rules apply, especially the rule that jobs should be small
|
||||
and idempotent. Make sure that in case that your migration job is retried, data
|
||||
integrity is guaranteed.
|
||||
|
||||
See [Sidekiq best practices guidelines](https://github.com/mperham/sidekiq/wiki/Best-Practices)
|
||||
for more details.
|
||||
|
||||
## Batched background migrations for EE-only features
|
||||
|
||||
All the background migration classes for EE-only features should be present in GitLab CE.
|
||||
For this purpose, create an empty class for GitLab CE, and extend it for GitLab EE
|
||||
as explained in the guidelines for
|
||||
[implementing Enterprise Edition features](../ee_features.md#code-in-libgitlabbackground_migration).
|
||||
|
||||
Batched Background migrations are simple classes that define a `perform` method. A
|
||||
Sidekiq worker then executes such a class, passing any arguments to it. All
|
||||
migration classes must be defined in the namespace
|
||||
`Gitlab::BackgroundMigration`. Place the files in the directory
|
||||
`lib/gitlab/background_migration/`.
|
||||
|
||||
## Queueing
|
||||
|
||||
Queueing a batched background migration should be done in a post-deployment
|
||||
migration. Use this `queue_batched_background_migration` example, queueing the
|
||||
migration to be executed in batches. Replace the class name and arguments with the values
|
||||
from your migration:
|
||||
|
||||
```ruby
|
||||
queue_batched_background_migration(
|
||||
JOB_CLASS_NAME,
|
||||
TABLE_NAME,
|
||||
JOB_ARGUMENTS,
|
||||
JOB_INTERVAL
|
||||
)
|
||||
```
|
||||
|
||||
Make sure the newly-created data is either migrated, or
|
||||
saved in both the old and new version upon creation. Removals in
|
||||
turn can be handled by defining foreign keys with cascading deletes.
|
||||
|
||||
### Requeuing batched background migrations
|
||||
|
||||
If one of the batched background migrations contains a bug that is fixed in a patch
|
||||
release, you must requeue the batched background migration so the migration
|
||||
repeats on systems that already performed the initial migration.
|
||||
|
||||
When you requeue the batched background migration, turn the original
|
||||
queuing into a no-op by clearing up the `#up` and `#down` methods of the
|
||||
migration performing the requeuing. Otherwise, the batched background migration is
|
||||
queued multiple times on systems that are upgrading multiple patch releases at
|
||||
once.
|
||||
|
||||
When you start the second post-deployment migration, delete the
|
||||
previously batched migration with the provided code:
|
||||
|
||||
```ruby
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION_NAME, TABLE_NAME, COLUMN, JOB_ARGUMENTS)
|
||||
.delete_all
|
||||
```
|
||||
|
||||
## Cleaning up
|
||||
|
||||
NOTE:
|
||||
Cleaning up any remaining background migrations must be done in either a major
|
||||
or minor release. You must not do this in a patch release.
|
||||
|
||||
Because background migrations can take a long time, you can't immediately clean
|
||||
things up after queueing them. For example, you can't drop a column used in the
|
||||
migration process, as jobs would fail. You must add a separate _post-deployment_
|
||||
migration in a future release that finishes any remaining
|
||||
jobs before cleaning things up. (For example, removing a column.)
|
||||
|
||||
To migrate the data from column `foo` (containing a big JSON blob) to column `bar`
|
||||
(containing a string), you would:
|
||||
|
||||
1. Release A:
|
||||
1. Create a migration class that performs the migration for a row with a given ID.
|
||||
1. Update new rows using one of these techniques:
|
||||
- Create a new trigger for simple copy operations that don't need application logic.
|
||||
- Handle this operation in the model/service as the records are created or updated.
|
||||
- Create a new custom background job that updates the records.
|
||||
1. Queue the batched background migration for all existing rows in a post-deployment migration.
|
||||
1. Release B:
|
||||
1. Add a post-deployment migration that checks if the batched background migration is completed.
|
||||
1. Deploy code so that the application starts using the new column and stops to update new records.
|
||||
1. Remove the old column.
|
||||
|
||||
Bump to the [import/export version](../../user/project/settings/import_export.md) may
|
||||
be required, if importing a project from a prior version of GitLab requires the
|
||||
data to be in the new format.
|
||||
|
||||
## Example
|
||||
|
||||
The table `integrations` has a field called `properties`, stored in JSON. For all rows,
|
||||
extract the `url` key from this JSON object and store it in the `integrations.url`
|
||||
column. Millions of integrations exist, and parsing JSON is slow, so you can't
|
||||
do this work in a regular migration.
|
||||
|
||||
1. Start by defining our migration class:
|
||||
|
||||
```ruby
|
||||
class Gitlab::BackgroundMigration::ExtractIntegrationsUrl
|
||||
class Integration < ActiveRecord::Base
|
||||
self.table_name = 'integrations'
|
||||
end
|
||||
|
||||
def perform(start_id, end_id)
|
||||
Integration.where(id: start_id..end_id).each do |integration|
|
||||
json = JSON.load(integration.properties)
|
||||
|
||||
integration.update(url: json['url']) if json['url']
|
||||
rescue JSON::ParserError
|
||||
# If the JSON is invalid we don't want to keep the job around forever,
|
||||
# instead we'll just leave the "url" field to whatever the default value
|
||||
# is.
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
NOTE:
|
||||
To get a `connection` in the batched background migration,use an inheritance
|
||||
relation using the following base class `Gitlab::BackgroundMigration::BaseJob`.
|
||||
For example: `class Gitlab::BackgroundMigration::ExtractIntegrationsUrl < Gitlab::BackgroundMigration::BaseJob`
|
||||
|
||||
1. Add a new trigger to the database to update newly created and updated integrations,
|
||||
similar to this example:
|
||||
|
||||
```ruby
|
||||
execute(<<~SQL)
|
||||
CREATE OR REPLACE FUNCTION example() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW."url" := NEW.properties -> "url"
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
SQL
|
||||
```
|
||||
|
||||
1. Create a post-deployment migration that queues the migration for existing data:
|
||||
|
||||
```ruby
|
||||
class QueueExtractIntegrationsUrl < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
MIGRATION = 'ExtractIntegrationsUrl'
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:integrations,
|
||||
:id,
|
||||
job_interval: DELAY_INTERVAL
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :integrations, :id, []).delete_all
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
After deployment, our application:
|
||||
- Continues using the data as before.
|
||||
- Ensures that both existing and new data are migrated.
|
||||
|
||||
1. In the next release, remove the trigger. We must also add a new post-deployment migration
|
||||
that checks that the batched background migration is completed. For example:
|
||||
|
||||
```ruby
|
||||
class FinalizeExtractIntegrationsUrlJobs < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'ExtractIntegrationsUrl'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: MIGRATION,
|
||||
table_name: :integrations,
|
||||
column_name: :id,
|
||||
job_arguments: []
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
If the application does not depend on the data being 100% migrated (for
|
||||
instance, the data is advisory, and not mission-critical), then you can skip this
|
||||
final step. This step confirms that the migration is completed, and all of the rows were migrated.
|
||||
|
||||
After the batched migration is completed, you can safely remove the `integrations.properties` column.
|
||||
|
||||
## Testing
|
||||
|
||||
Writing tests is required for:
|
||||
|
||||
- The batched background migrations' queueing migration.
|
||||
- The batched background migration itself.
|
||||
- A cleanup migration.
|
||||
|
||||
The `:migration` and `schema: :latest` RSpec tags are automatically set for
|
||||
background migration specs. Refer to the
|
||||
[Testing Rails migrations](../testing_guide/testing_migrations_guide.md#testing-a-non-activerecordmigration-class)
|
||||
style guide.
|
||||
|
||||
Remember that `before` and `after` RSpec hooks
|
||||
migrate your database down and up. These hooks can result in other batched background
|
||||
migrations being called. Using `spy` test doubles with
|
||||
`have_received` is encouraged, instead of using regular test doubles, because
|
||||
your expectations defined in a `it` block can conflict with what is
|
||||
called in RSpec hooks. Refer to [issue #35351](https://gitlab.com/gitlab-org/gitlab/-/issues/18839)
|
||||
for more details.
|
||||
|
||||
## Best practices
|
||||
|
||||
1. Know how much data you're dealing with.
|
||||
1. Make sure the batched background migration jobs are idempotent.
|
||||
1. Confirm the tests you write are not false positives.
|
||||
1. If the data being migrated is critical and cannot be lost, the
|
||||
clean-up migration must also check the final state of the data before completing.
|
||||
1. Discuss the numbers with a database specialist. The migration may add
|
||||
more pressure on DB than you expect. Measure on staging,
|
||||
or ask someone to measure on production.
|
||||
1. Know how much time is required to run the batched background migration.
|
||||
|
||||
## Additional tips and strategies
|
||||
|
||||
### Viewing failure error logs
|
||||
|
||||
You can view failures in two ways:
|
||||
|
||||
- Via GitLab logs:
|
||||
1. After running a batched background migration, if any jobs fail,
|
||||
view the logs in [Kibana](https://log.gprd.gitlab.net/goto/5f06a57f768c6025e1c65aefb4075694).
|
||||
View the production Sidekiq log and filter for:
|
||||
|
||||
- `json.new_state: failed`
|
||||
- `json.job_class_name: <Batched Background Migration job class name>`
|
||||
- `json.job_arguments: <Batched Background Migration job class arguments>`
|
||||
|
||||
1. Review the `json.exception_class` and `json.exception_message` values to help
|
||||
understand why the jobs failed.
|
||||
|
||||
1. Remember the retry mechanism. Having a failure does not mean the job failed.
|
||||
Always check the last status of the job.
|
||||
|
||||
- Via database:
|
||||
|
||||
1. Get the batched background migration `CLASS_NAME`.
|
||||
1. Execute the following query in the PostgreSQL console:
|
||||
|
||||
```sql
|
||||
SELECT migration.id, migration.job_class_name, transition_logs.exception_class, transition_logs.exception_message
|
||||
FROM batched_background_migrations as migration
|
||||
INNER JOIN batched_background_migration_jobs as jobs
|
||||
ON jobs.batched_background_migration_id = migration.id
|
||||
INNER JOIN batched_background_migration_job_transition_logs as transition_logs
|
||||
ON transition_logs.batched_background_migration_job_id = jobs.id
|
||||
WHERE transition_logs.next_status = '2' AND migration.job_class_name = "CLASS_NAME";
|
||||
```
|
|
@ -1271,7 +1271,7 @@ This sensitive data must be handled carefully to avoid leaks which could lead to
|
|||
- Never commit credentials to repositories.
|
||||
- The [Gitleaks Git hook](https://gitlab.com/gitlab-com/gl-security/security-research/gitleaks-endpoint-installer) is recommended for preventing credentials from being committed.
|
||||
- Never log credentials under any circumstance. Issue [#353857](https://gitlab.com/gitlab-org/gitlab/-/issues/353857) is an example of credential leaks through log file.
|
||||
- When credentials are required in a CI/CD job, use [masked variables](../ci/variables/index.md#mask-a-cicd-variable) to help prevent accidental exposure in the job logs. Be aware that when [debug logging](../ci/variables/index.md#debug-logging) is enabled, all masked CI/CD variables are visible in job logs. Also consider using [protected variables](../ci/variables/index.md#protect-a-cicd-variable) when possible so that sensitive CI/CD variables are only available to pipelines running on protected branches or tags.
|
||||
- When credentials are required in a CI/CD job, use [masked variables](../ci/variables/index.md#mask-a-cicd-variable) to help prevent accidental exposure in the job logs. Be aware that when [debug logging](../ci/variables/index.md#debug-logging) is enabled, all masked CI/CD variables are visible in job logs. Also consider using [protected variables](../ci/variables/index.md#protect-a-cicd-variable) when possible so that sensitive CI/CD variables are only available to pipelines running on protected branches or protected tags.
|
||||
- Proper scanners must be enabled depending on what data those credentials are protecting. See the [Application Security Inventory Policy](https://about.gitlab.com/handbook/engineering/security/security-engineering-and-research/application-security/inventory.html#policies) and our [Data Classification Standards](https://about.gitlab.com/handbook/engineering/security/data-classification-standard.html#data-classification-standards).
|
||||
- To store and/or share credentials between teams, refer to [1Password for Teams](https://about.gitlab.com/handbook/security/#1password-for-teams) and follow [the 1Password Guidelines](https://about.gitlab.com/handbook/security/#1password-guidelines).
|
||||
- If you need to share a secret with a team member, use 1Password. Do not share a secret over email, Slack, or other service on the Internet.
|
||||
|
|
|
@ -1341,12 +1341,12 @@ When checking if a runner is `paused`, API users are advised to check the boolea
|
|||
### SaaS certificate-based integration with Kubernetes
|
||||
|
||||
WARNING:
|
||||
This feature will be changed or removed in 15.0
|
||||
This feature will be changed or removed in 15.6
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0.
|
||||
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace. The integrations are expected to be switched off completely on GitLab SaaS around 2022 November 22.
|
||||
|
||||
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
|
||||
[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
|
||||
|
@ -1355,12 +1355,12 @@ For updates and details about this deprecation, follow [this epic](https://gitla
|
|||
|
||||
GitLab self-managed customers can still use the feature [with a feature flag](https://docs.gitlab.com/ee/update/deprecations.html#self-managed-certificate-based-integration-with-kubernetes).
|
||||
|
||||
**Planned removal milestone: 15.0 (2022-05-22)**
|
||||
**Planned removal milestone: 15.6 (2022-11-22)**
|
||||
|
||||
### Self-managed certificate-based integration with Kubernetes
|
||||
|
||||
WARNING:
|
||||
This feature will be changed or removed in 15.6
|
||||
This feature will be changed or removed in 16.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
@ -1369,14 +1369,14 @@ The certificate-based integration with Kubernetes [will be deprecated and remove
|
|||
|
||||
As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
|
||||
|
||||
In GitLab 15.6 we will remove both the feature, and its related code. Until the final removal in 15.6, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
|
||||
In GitLab 16.0 we will remove both the feature and its related code. Until the final removal in 16.0, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
|
||||
|
||||
For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend you use the
|
||||
[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
|
||||
|
||||
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
|
||||
|
||||
**Planned removal milestone: 15.6 (2022-11-22)**
|
||||
**Planned removal milestone: 16.0 (2023-05-22)**
|
||||
|
||||
### Support for SLES 12 SP2
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ module API
|
|||
end
|
||||
|
||||
def ensure_feature_enabled!
|
||||
not_found! unless Feature.enabled?(:certificate_based_clusters, clusterable_instance, default_enabled: :yaml, type: :ops)
|
||||
not_found! unless Feature.enabled?(:certificate_based_clusters, default_enabled: :yaml, type: :ops)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ module API
|
|||
@client ||= if Feature.enabled?(:remove_legacy_github_client)
|
||||
Gitlab::GithubImport::Client.new(params[:personal_access_token], host: params[:github_hostname])
|
||||
else
|
||||
Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], client_options)
|
||||
Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], **client_options)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ module API
|
|||
end
|
||||
|
||||
def ensure_feature_enabled!
|
||||
not_found! unless Feature.enabled?(:certificate_based_clusters, user_project, default_enabled: :yaml, type: :ops)
|
||||
not_found! unless Feature.enabled?(:certificate_based_clusters, user_project.namespace, default_enabled: :yaml, type: :ops)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,6 @@ module Sidebars
|
|||
override :render?
|
||||
def render?
|
||||
clusterable = context.group
|
||||
|
||||
Feature.enabled?(:certificate_based_clusters, clusterable, default_enabled: :yaml, type: :ops) &&
|
||||
can?(context.current_user, :read_cluster, clusterable)
|
||||
end
|
||||
|
|
|
@ -501,7 +501,7 @@ msgstr ""
|
|||
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
|
||||
msgstr ""
|
||||
|
||||
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
|
||||
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or protected tags."
|
||||
msgstr ""
|
||||
|
||||
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
|
||||
|
@ -14224,9 +14224,7 @@ msgid "Enterprise"
|
|||
msgstr ""
|
||||
|
||||
msgid "Environment"
|
||||
msgid_plural "Environments"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr ""
|
||||
|
||||
msgid "Environment does not have deployments"
|
||||
msgstr ""
|
||||
|
@ -25101,9 +25099,6 @@ msgstr ""
|
|||
msgid "NetworkPolicies|Create policy"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Delete policy"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25113,9 +25108,6 @@ msgstr ""
|
|||
msgid "NetworkPolicies|Deny all traffic"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Edit policy"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Environment does not have deployment platform"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25131,9 +25123,6 @@ msgstr ""
|
|||
msgid "NetworkPolicies|Kubernetes error: %{error}"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Network"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Network Policies can be used to limit which network traffic is allowed between containers inside the cluster."
|
||||
msgstr ""
|
||||
|
||||
|
@ -25149,9 +25138,6 @@ msgstr ""
|
|||
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Policy definition"
|
||||
msgstr ""
|
||||
|
||||
msgid "NetworkPolicies|Rule mode"
|
||||
msgstr ""
|
||||
|
||||
|
@ -33632,6 +33618,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|All policies"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Allow up to 10 minutes for any policy changes to take effect."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -33653,6 +33642,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Create security policy"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Define this policy's location, conditions and actions."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Description"
|
||||
msgstr ""
|
||||
|
||||
|
@ -33725,6 +33717,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Policies"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policies created in this project are applied through a background job that runs once every 10 minutes."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy Type"
|
||||
msgstr ""
|
||||
|
||||
|
@ -33734,6 +33729,9 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy definition"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Policy description"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
|
||||
"@gitlab/eslint-plugin": "12.0.1",
|
||||
"@gitlab/eslint-plugin": "12.1.0",
|
||||
"@gitlab/stylelint-config": "4.0.0",
|
||||
"@graphql-eslint/eslint-plugin": "3.10.2",
|
||||
"@testing-library/dom": "^7.16.2",
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Resource
|
||||
class Job < Base
|
||||
attr_accessor :id, :name, :project
|
||||
|
||||
attributes :id,
|
||||
:project
|
||||
|
||||
def fabricate_via_api!
|
||||
resource_web_url(api_get)
|
||||
rescue ResourceNotFoundError
|
||||
super
|
||||
end
|
||||
|
||||
def artifacts
|
||||
parse_body(api_get_from(api_get_path))[:artifacts]
|
||||
end
|
||||
|
||||
def api_get_path
|
||||
"/projects/#{project.id}/jobs/#{id}"
|
||||
end
|
||||
|
||||
def api_post_path
|
||||
end
|
||||
|
||||
def api_post_body
|
||||
{
|
||||
artifacts: artifacts
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -190,6 +190,10 @@ module QA
|
|||
"#{api_get_path}/pipeline_schedules"
|
||||
end
|
||||
|
||||
def api_jobs_path
|
||||
"#{api_get_path}/jobs"
|
||||
end
|
||||
|
||||
def api_issues_path
|
||||
"#{api_get_path}/issues"
|
||||
end
|
||||
|
@ -354,6 +358,15 @@ module QA
|
|||
auto_paginated_response(request_url(api_pipelines_path, per_page: '100'), attempts: attempts)
|
||||
end
|
||||
|
||||
def jobs
|
||||
response = get(request_url(api_jobs_path))
|
||||
parse_body(response)
|
||||
end
|
||||
|
||||
def job_by_name(job_name)
|
||||
jobs.find { |job| job[:name] == job_name }
|
||||
end
|
||||
|
||||
def issues(auto_paginate: false, attempts: 0)
|
||||
return parse_body(api_get_from(api_issues_path)) unless auto_paginate
|
||||
|
||||
|
|
101
yarn.lock
101
yarn.lock
|
@ -936,10 +936,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.7.tgz#1ee6f838cc4410a1d797770934df91d90df8179e"
|
||||
integrity sha512-c6ySRK/Ma7lxwpIVbSAF3P+xiTLrNTGTLRx4/pHK111AdFxwgUwrYF6aVZFXvmG65jHOJHoa0eQQ21RW6rm0Rg==
|
||||
|
||||
"@gitlab/eslint-plugin@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-12.0.1.tgz#307486721e51cef223cf03dd2bae6d67d3286237"
|
||||
integrity sha512-YVa6Pegiklu22V7jN/cj77E10L2M0aEN3A4UTzbCH57yQOVwyJC+bG33/eqzq175YFYWwnbkCOB22lBMLDizYQ==
|
||||
"@gitlab/eslint-plugin@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-12.1.0.tgz#e62f2591164895f8cfccb3dd9ac77f3586b6e3d8"
|
||||
integrity sha512-rq+aaF45s3FSzFFoK2BZ7X/uzOIhAWA0rfG4q5SnoecbMuEpPEX2OGZFRh8VOePZLmiylfwyxH0Cv12evzyUtg==
|
||||
dependencies:
|
||||
"@babel/core" "^7.17.0"
|
||||
"@babel/eslint-parser" "^7.17.0"
|
||||
|
@ -951,9 +951,8 @@
|
|||
eslint-plugin-jest "^23.8.2"
|
||||
eslint-plugin-promise "^4.2.1"
|
||||
eslint-plugin-unicorn "^40.1.0"
|
||||
eslint-plugin-vue "^7.5.0"
|
||||
eslint-plugin-vue "^8.5.0"
|
||||
lodash "^4.17.21"
|
||||
vue-eslint-parser "^7.0.0"
|
||||
|
||||
"@gitlab/favicon-overlay@2.0.0":
|
||||
version "2.0.0"
|
||||
|
@ -2480,7 +2479,7 @@ acorn-globals@^6.0.0:
|
|||
acorn "^7.1.1"
|
||||
acorn-walk "^7.1.1"
|
||||
|
||||
acorn-jsx@^5.2.0, acorn-jsx@^5.3.1:
|
||||
acorn-jsx@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
|
||||
integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
|
||||
|
@ -2505,10 +2504,10 @@ acorn@^7.1.1, acorn@^7.4.0:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
acorn@^8.0.4:
|
||||
version "8.6.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895"
|
||||
integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==
|
||||
acorn@^8.0.4, acorn@^8.7.0:
|
||||
version "8.7.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
|
||||
integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
|
||||
|
||||
agent-base@4, agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
|
@ -4745,7 +4744,7 @@ debug@3.1.0:
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.3:
|
||||
debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
|
@ -5447,15 +5446,17 @@ eslint-plugin-unicorn@^40.1.0:
|
|||
semver "^7.3.5"
|
||||
strip-indent "^3.0.0"
|
||||
|
||||
eslint-plugin-vue@^7.5.0:
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.5.0.tgz#cc6d983eb22781fa2440a7573cf39af439bb5725"
|
||||
integrity sha512-QnMMTcyV8PLxBz7QQNAwISSEs6LYk2LJvGlxalXvpCtfKnqo7qcY0aZTIxPe8QOnHd7WCwiMZLOJzg6A03T0Gw==
|
||||
eslint-plugin-vue@^8.5.0:
|
||||
version "8.7.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz#f13c53547a0c9d64588a675cc5ecc6ccaf63703f"
|
||||
integrity sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==
|
||||
dependencies:
|
||||
eslint-utils "^2.1.0"
|
||||
eslint-utils "^3.0.0"
|
||||
natural-compare "^1.4.0"
|
||||
semver "^7.3.2"
|
||||
vue-eslint-parser "^7.4.1"
|
||||
nth-check "^2.0.1"
|
||||
postcss-selector-parser "^6.0.9"
|
||||
semver "^7.3.5"
|
||||
vue-eslint-parser "^8.0.1"
|
||||
|
||||
eslint-rule-composer@^0.3.0:
|
||||
version "0.3.0"
|
||||
|
@ -5478,6 +5479,14 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1:
|
|||
esrecurse "^4.3.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-scope@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
|
||||
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
|
||||
dependencies:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-utils@^2.0.0, eslint-utils@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
|
||||
|
@ -5502,6 +5511,11 @@ eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
|
||||
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
|
||||
|
||||
eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||
|
||||
eslint@7.32.0:
|
||||
version "7.32.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
|
||||
|
@ -5548,15 +5562,6 @@ eslint@7.32.0:
|
|||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
espree@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
|
||||
integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
|
||||
dependencies:
|
||||
acorn "^7.1.1"
|
||||
acorn-jsx "^5.2.0"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
espree@^7.3.0, espree@^7.3.1:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
|
||||
|
@ -5566,12 +5571,21 @@ espree@^7.3.0, espree@^7.3.1:
|
|||
acorn-jsx "^5.3.1"
|
||||
eslint-visitor-keys "^1.3.0"
|
||||
|
||||
espree@^9.0.0:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
|
||||
integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
|
||||
dependencies:
|
||||
acorn "^8.7.0"
|
||||
acorn-jsx "^5.3.1"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
esprima@^4.0.0, esprima@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
|
||||
esquery@^1.0.1, esquery@^1.4.0:
|
||||
esquery@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
|
||||
integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
|
||||
|
@ -9369,10 +9383,10 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1:
|
|||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
nth-check@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
|
||||
integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==
|
||||
nth-check@^2.0.0, nth-check@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
|
||||
integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
|
||||
|
@ -12688,17 +12702,18 @@ vue-apollo@^3.0.7:
|
|||
serialize-javascript "^4.0.0"
|
||||
throttle-debounce "^2.1.0"
|
||||
|
||||
vue-eslint-parser@^7.0.0, vue-eslint-parser@^7.4.1:
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.4.1.tgz#e4adcf7876a7379758d9056a72235af18a587f92"
|
||||
integrity sha512-AFvhdxpFvliYq1xt/biNBslTHE/zbEvSnr1qfHA/KxRIpErmEDrQZlQnvEexednRHmLfDNOMuDYwZL5xkLzIXQ==
|
||||
vue-eslint-parser@^8.0.1:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz#5d31129a1b3dd89c0069ca0a1c88f970c360bd0d"
|
||||
integrity sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
eslint-scope "^5.0.0"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
espree "^6.2.1"
|
||||
esquery "^1.0.1"
|
||||
lodash "^4.17.15"
|
||||
debug "^4.3.2"
|
||||
eslint-scope "^7.0.0"
|
||||
eslint-visitor-keys "^3.1.0"
|
||||
espree "^9.0.0"
|
||||
esquery "^1.4.0"
|
||||
lodash "^4.17.21"
|
||||
semver "^7.3.5"
|
||||
|
||||
vue-functional-data-merge@^3.1.0:
|
||||
version "3.1.0"
|
||||
|
|
Loading…
Reference in New Issue