Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
907fd5d94e
commit
953eb09e08
|
@ -87,12 +87,6 @@ gemnasium-dependency_scanning:
|
|||
- apk add git-lfs
|
||||
rules: !reference [".reports:rules:gemnasium-dependency_scanning", rules]
|
||||
|
||||
bundler-audit-dependency_scanning:
|
||||
rules: !reference [".reports:rules:bundler-audit-dependency_scanning", rules]
|
||||
|
||||
retire-js-dependency_scanning:
|
||||
rules: !reference [".reports:rules:retire-js-dependency_scanning", rules]
|
||||
|
||||
gemnasium-python-dependency_scanning:
|
||||
rules: !reference [".reports:rules:gemnasium-python-dependency_scanning", rules]
|
||||
|
||||
|
|
|
@ -1480,18 +1480,6 @@
|
|||
when: never
|
||||
- changes: *dependency-patterns
|
||||
|
||||
.reports:rules:bundler-audit-dependency_scanning:
|
||||
rules:
|
||||
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /bundler-audit/ || $DS_DEFAULT_ANALYZERS !~ /bundler-audit/'
|
||||
when: never
|
||||
- changes: *bundler-patterns
|
||||
|
||||
.reports:rules:retire-js-dependency_scanning:
|
||||
rules:
|
||||
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /retire.js/ || $DS_DEFAULT_ANALYZERS !~ /retire.js/'
|
||||
when: never
|
||||
- changes: *nodejs-patterns
|
||||
|
||||
.reports:rules:gemnasium-python-dependency_scanning:
|
||||
rules:
|
||||
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/ || $DS_DEFAULT_ANALYZERS !~ /gemnasium-python/'
|
||||
|
|
|
@ -1 +1 @@
|
|||
3c00908c2743ef03a2d5b7057bf8f87d5b267a75
|
||||
9413ca591ebe30dcb133c86d0ec53f6bc2fc30bb
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
export function generateAgentRegistrationCommand(agentToken, kasAddress) {
|
||||
return `docker run --pull=always --rm \\
|
||||
registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate \\
|
||||
--agent-token=${agentToken} \\
|
||||
--kas-address=${kasAddress} \\
|
||||
--agent-version stable \\
|
||||
--namespace gitlab-kubernetes-agent | kubectl apply -f -`;
|
||||
return `helm repo add gitlab https://charts.gitlab.io
|
||||
helm repo update
|
||||
helm upgrade --install gitlab-agent gitlab/gitlab-agent \\
|
||||
--namespace gitlab-agent \\
|
||||
--create-namespace \\
|
||||
--set config.token=${agentToken} \\
|
||||
--set config.kasAddress=${kasAddress}`;
|
||||
}
|
||||
|
||||
export function getAgentConfigPath(clusterAgentName) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { I18N_AGENT_TOKEN } from '../constants';
|
|||
export default {
|
||||
i18n: I18N_AGENT_TOKEN,
|
||||
advancedInstallPath: helpPagePath('user/clusters/agent/install/index', {
|
||||
anchor: 'advanced-installation',
|
||||
anchor: 'advanced-installation-method',
|
||||
}),
|
||||
components: {
|
||||
GlAlert,
|
||||
|
|
|
@ -96,9 +96,9 @@ export const I18N_AGENT_TOKEN = {
|
|||
),
|
||||
tokenSubtitle: s__('ClusterAgents|The agent uses the token to connect with GitLab.'),
|
||||
|
||||
basicInstallTitle: s__('ClusterAgents|Recommended installation method'),
|
||||
basicInstallTitle: s__('ClusterAgents|Install using Helm (recommended)'),
|
||||
basicInstallBody: s__(
|
||||
'ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included.',
|
||||
'ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included in the command.',
|
||||
),
|
||||
|
||||
advancedInstallTitle: s__('ClusterAgents|Advanced installation methods'),
|
||||
|
|
|
@ -392,19 +392,24 @@ export default {
|
|||
</template>
|
||||
|
||||
<template #cell(title)="{ item }">
|
||||
<div :class="{ 'gl-display-flex gl-align-items-center': item.state === 'closed' }">
|
||||
<div
|
||||
:class="{
|
||||
'gl-display-flex gl-align-items-center gl-max-w-full': item.state === 'closed',
|
||||
}"
|
||||
>
|
||||
<gl-link
|
||||
v-gl-tooltip
|
||||
:title="item.title"
|
||||
data-testid="incident-link"
|
||||
:href="showIncidentLink(item)"
|
||||
class="gl-min-w-0"
|
||||
>
|
||||
{{ item.title }}
|
||||
<tooltip-on-truncate :title="item.title" class="gl-text-truncate gl-display-block">
|
||||
{{ item.title }}
|
||||
</tooltip-on-truncate>
|
||||
</gl-link>
|
||||
<gl-icon
|
||||
v-if="item.state === 'closed'"
|
||||
name="issue-close"
|
||||
class="gl-mx-1 gl-fill-blue-500 gl-flex-shrink-0"
|
||||
class="gl-ml-2 gl-fill-blue-500 gl-flex-shrink-0"
|
||||
:size="16"
|
||||
data-testid="incident-closed"
|
||||
/>
|
||||
|
|
|
@ -100,7 +100,5 @@ export const I18N = {
|
|||
subtitle: s__(
|
||||
"Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD.",
|
||||
),
|
||||
description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'),
|
||||
cta: s__('Pipelines|Use template'),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { GlEmptyState } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import PipelinesCiTemplates from './pipelines_ci_templates.vue';
|
||||
import PipelinesCiTemplates from './empty_state/pipelines_ci_templates.vue';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<script>
|
||||
import { GlAvatar, GlButton } from '@gitlab/ui';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
|
||||
import Tracking from '~/tracking';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlAvatar,
|
||||
GlButton,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
inject: ['pipelineEditorPath', 'suggestedCiTemplates'],
|
||||
data() {
|
||||
const templates = this.suggestedCiTemplates.map(({ name, logo }) => {
|
||||
return {
|
||||
name,
|
||||
logo,
|
||||
link: mergeUrlParams({ template: name }, this.pipelineEditorPath),
|
||||
description: sprintf(this.$options.i18n.description, { name }),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
templates,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
trackEvent(template) {
|
||||
this.track('template_clicked', {
|
||||
label: template,
|
||||
});
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'),
|
||||
cta: s__('Pipelines|Use template'),
|
||||
},
|
||||
AVATAR_SHAPE_OPTION_RECT,
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<ul class="gl-list-style-none gl-pl-0">
|
||||
<li v-for="template in templates" :key="template.name">
|
||||
<div
|
||||
class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-pt-3"
|
||||
>
|
||||
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center">
|
||||
<gl-avatar
|
||||
:src="template.logo"
|
||||
:size="48"
|
||||
class="gl-mr-5 gl-bg-white dark-mode-override"
|
||||
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
|
||||
:alt="template.name"
|
||||
data-testid="template-logo"
|
||||
/>
|
||||
<div class="gl-flex-direction-row">
|
||||
<div class="gl-mb-3">
|
||||
<strong class="gl-text-gray-800" data-testid="template-name">
|
||||
{{ template.name }}
|
||||
</strong>
|
||||
</div>
|
||||
<p class="gl-mb-0 gl-font-sm" data-testid="template-description">
|
||||
{{ template.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<gl-button
|
||||
category="primary"
|
||||
variant="confirm"
|
||||
:href="template.link"
|
||||
data-testid="template-link"
|
||||
@click="trackEvent(template.name)"
|
||||
>
|
||||
{{ $options.i18n.cta }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
|
@ -1,8 +1,6 @@
|
|||
<script>
|
||||
import { GlAvatar, GlButton, GlCard, GlSprintf, GlIcon, GlLink } from '@gitlab/ui';
|
||||
import { GlButton, GlCard, GlSprintf, GlIcon, GlLink } from '@gitlab/ui';
|
||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||
import { sprintf } from '~/locale';
|
||||
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
|
||||
import {
|
||||
STARTER_TEMPLATE_NAME,
|
||||
RUNNERS_AVAILABILITY_SECTION_EXPERIMENT_NAME,
|
||||
|
@ -11,21 +9,22 @@ import {
|
|||
RUNNERS_SETTINGS_BUTTON_CLICKED_EVENT,
|
||||
I18N,
|
||||
} from '~/pipeline_editor/constants';
|
||||
import Tracking from '~/tracking';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import { isExperimentVariant } from '~/experimentation/utils';
|
||||
import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue';
|
||||
import ExperimentTracking from '~/experimentation/experiment_tracking';
|
||||
import { isExperimentVariant } from '~/experimentation/utils';
|
||||
import Tracking from '~/tracking';
|
||||
import CiTemplates from './ci_templates.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlAvatar,
|
||||
GlButton,
|
||||
GlCard,
|
||||
GlSprintf,
|
||||
GlIcon,
|
||||
GlLink,
|
||||
GitlabExperiment,
|
||||
CiTemplates,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
STARTER_TEMPLATE_NAME,
|
||||
|
@ -34,8 +33,7 @@ export default {
|
|||
RUNNERS_DOCUMENTATION_LINK_CLICKED_EVENT,
|
||||
RUNNERS_SETTINGS_BUTTON_CLICKED_EVENT,
|
||||
I18N,
|
||||
AVATAR_SHAPE_OPTION_RECT,
|
||||
inject: ['pipelineEditorPath', 'suggestedCiTemplates'],
|
||||
inject: ['pipelineEditorPath'],
|
||||
props: {
|
||||
ciRunnerSettingsPath: {
|
||||
type: String,
|
||||
|
@ -49,17 +47,7 @@ export default {
|
|||
},
|
||||
},
|
||||
data() {
|
||||
const templates = this.suggestedCiTemplates.map(({ name, logo }) => {
|
||||
return {
|
||||
name,
|
||||
logo,
|
||||
link: mergeUrlParams({ template: name }, this.pipelineEditorPath),
|
||||
description: sprintf(this.$options.I18N.templates.description, { name }),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
templates,
|
||||
gettingStartedTemplateUrl: mergeUrlParams(
|
||||
{ template: STARTER_TEMPLATE_NAME },
|
||||
this.pipelineEditorPath,
|
||||
|
@ -179,43 +167,7 @@ export default {
|
|||
<h2 class="gl-font-lg gl-text-gray-900">{{ $options.I18N.templates.title }}</h2>
|
||||
<p class="gl-text-gray-800 gl-mb-6">{{ $options.I18N.templates.subtitle }}</p>
|
||||
|
||||
<ul class="gl-list-style-none gl-pl-0">
|
||||
<li v-for="template in templates" :key="template.name">
|
||||
<div
|
||||
class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-pt-3"
|
||||
>
|
||||
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center">
|
||||
<gl-avatar
|
||||
:src="template.logo"
|
||||
:size="48"
|
||||
class="gl-mr-5 gl-bg-white dark-mode-override"
|
||||
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
|
||||
:alt="template.name"
|
||||
data-testid="template-logo"
|
||||
/>
|
||||
<div class="gl-flex-direction-row">
|
||||
<div class="gl-mb-3">
|
||||
<strong class="gl-text-gray-800" data-testid="template-name">
|
||||
{{ template.name }}
|
||||
</strong>
|
||||
</div>
|
||||
<p class="gl-mb-0 gl-font-sm" data-testid="template-description">
|
||||
{{ template.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<gl-button
|
||||
category="primary"
|
||||
variant="confirm"
|
||||
:href="template.link"
|
||||
data-testid="template-link"
|
||||
@click="trackEvent(template.name)"
|
||||
>
|
||||
{{ $options.I18N.templates.cta }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<ci-templates />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
|
@ -163,33 +163,6 @@ export default {
|
|||
return undefined;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
/**
|
||||
* GlFilteredSearch currently doesn't emit any event when
|
||||
* tokens are manually removed from search field so we'd
|
||||
* never know when user actually clears all the tokens.
|
||||
* This watcher listens for updates to `filterValue` on
|
||||
* such instances. :(
|
||||
*/
|
||||
filterValue(newValue, oldValue) {
|
||||
const [firstVal] = newValue;
|
||||
if (
|
||||
!this.initialRender &&
|
||||
newValue.length === 1 &&
|
||||
firstVal.type === 'filtered-search-term' &&
|
||||
!firstVal.value.data
|
||||
) {
|
||||
const filtersCleared =
|
||||
oldValue[0].type !== 'filtered-search-term' || oldValue[0].value.data !== '';
|
||||
this.$emit('onFilter', [], filtersCleared);
|
||||
}
|
||||
|
||||
// Set initial render flag to false
|
||||
// as we don't want to emit event
|
||||
// on initial load when value is empty already.
|
||||
this.initialRender = false;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (this.recentSearchesStorageKey) this.setupRecentSearch();
|
||||
},
|
||||
|
@ -322,6 +295,10 @@ export default {
|
|||
|
||||
return tokenOption.title;
|
||||
},
|
||||
onClear() {
|
||||
const cleared = true;
|
||||
this.$emit('onFilter', [], cleared);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -345,6 +322,7 @@ export default {
|
|||
:suggestions-list-class="suggestionsListClass"
|
||||
class="flex-grow-1"
|
||||
@history-item-selected="handleHistoryItemSelected"
|
||||
@clear="onClear"
|
||||
@clear-history="handleClearHistory"
|
||||
@submit="handleFilterSubmit"
|
||||
>
|
||||
|
|
|
@ -452,9 +452,12 @@ a.gl-badge.badge-warning:active {
|
|||
.gl-form-input.form-control:disabled,
|
||||
.gl-form-input.form-control:not(.form-control-plaintext):not([type="color"]):read-only {
|
||||
background-color: #1f1f1f;
|
||||
color: #868686;
|
||||
box-shadow: inset 0 0 0 1px #404040;
|
||||
}
|
||||
.gl-form-input:disabled,
|
||||
.gl-form-input.form-control:disabled {
|
||||
cursor: not-allowed;
|
||||
color: #868686;
|
||||
}
|
||||
.gl-form-input::placeholder,
|
||||
.gl-form-input.form-control::placeholder {
|
||||
|
|
|
@ -438,9 +438,12 @@ a.gl-badge.badge-warning:active {
|
|||
.gl-form-input.form-control:disabled,
|
||||
.gl-form-input.form-control:not(.form-control-plaintext):not([type="color"]):read-only {
|
||||
background-color: #fafafa;
|
||||
color: #868686;
|
||||
box-shadow: inset 0 0 0 1px #dbdbdb;
|
||||
}
|
||||
.gl-form-input:disabled,
|
||||
.gl-form-input.form-control:disabled {
|
||||
cursor: not-allowed;
|
||||
color: #868686;
|
||||
}
|
||||
.gl-form-input::placeholder,
|
||||
.gl-form-input.form-control::placeholder {
|
||||
|
|
|
@ -301,9 +301,12 @@ fieldset:disabled a.btn {
|
|||
.gl-form-input.form-control:disabled,
|
||||
.gl-form-input.form-control:not(.form-control-plaintext):not([type="color"]):read-only {
|
||||
background-color: #fafafa;
|
||||
color: #868686;
|
||||
box-shadow: inset 0 0 0 1px #dbdbdb;
|
||||
}
|
||||
.gl-form-input:disabled,
|
||||
.gl-form-input.form-control:disabled {
|
||||
cursor: not-allowed;
|
||||
color: #868686;
|
||||
}
|
||||
.gl-form-input::placeholder,
|
||||
.gl-form-input.form-control::placeholder {
|
||||
|
|
|
@ -184,7 +184,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
def cluster_list
|
||||
return [] unless certificate_based_clusters_enabled?
|
||||
|
||||
finder = ClusterAncestorsFinder.new(clusterable.subject, current_user)
|
||||
finder = ClusterAncestorsFinder.new(clusterable.__subject__, current_user)
|
||||
clusters = finder.execute
|
||||
|
||||
@has_ancestor_clusters = finder.has_ancestor_clusters?
|
||||
|
@ -253,7 +253,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
]).merge(
|
||||
provider_type: :gcp,
|
||||
platform_type: :kubernetes,
|
||||
clusterable: clusterable.subject
|
||||
clusterable: clusterable.__subject__
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -274,7 +274,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
]).merge(
|
||||
provider_type: :aws,
|
||||
platform_type: :kubernetes,
|
||||
clusterable: clusterable.subject
|
||||
clusterable: clusterable.__subject__
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -291,7 +291,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
]).merge(
|
||||
provider_type: :user,
|
||||
platform_type: :kubernetes,
|
||||
clusterable: clusterable.subject
|
||||
clusterable: clusterable.__subject__
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -313,7 +313,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
end
|
||||
|
||||
def gcp_cluster
|
||||
cluster = Clusters::BuildService.new(clusterable.subject).execute
|
||||
cluster = Clusters::BuildService.new(clusterable.__subject__).execute
|
||||
cluster.build_provider_gcp
|
||||
@gcp_cluster = cluster.present(current_user: current_user)
|
||||
end
|
||||
|
@ -343,7 +343,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
end
|
||||
|
||||
def user_cluster
|
||||
cluster = Clusters::BuildService.new(clusterable.subject).execute
|
||||
cluster = Clusters::BuildService.new(clusterable.__subject__).execute
|
||||
cluster.build_platform_kubernetes
|
||||
@user_cluster = cluster.present(current_user: current_user)
|
||||
end
|
||||
|
|
|
@ -15,7 +15,6 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) }
|
||||
prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }
|
||||
prepend_before_action :ensure_export_enabled, only: [:export, :download_export]
|
||||
prepend_before_action :check_captcha, only: :create, if: -> { captcha_enabled? }
|
||||
|
||||
before_action :authenticate_user!, only: [:new, :create]
|
||||
|
@ -339,10 +338,6 @@ class GroupsController < Groups::ApplicationController
|
|||
check_rate_limit!(prefixed_action, scope: [current_user, scope].compact)
|
||||
end
|
||||
|
||||
def ensure_export_enabled
|
||||
render_404 unless Feature.enabled?(:group_import_export, @group, default_enabled: true)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_recaptcha
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
class Import::GitlabGroupsController < ApplicationController
|
||||
include WorkhorseAuthorization
|
||||
|
||||
before_action :ensure_group_import_enabled
|
||||
before_action :check_import_rate_limit!, only: %i[create]
|
||||
|
||||
feature_category :importers
|
||||
|
@ -51,10 +50,6 @@ class Import::GitlabGroupsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def ensure_group_import_enabled
|
||||
render_404 unless Feature.enabled?(:group_import_export, @group, default_enabled: true)
|
||||
end
|
||||
|
||||
def check_import_rate_limit!
|
||||
check_rate_limit!(:group_import, scope: current_user) do
|
||||
redirect_to new_group_path, alert: _('This endpoint has been requested too many times. Try again later.')
|
||||
|
|
|
@ -11,7 +11,9 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController
|
|||
style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline')
|
||||
# rubocop: enable Lint/PercentStringArray
|
||||
|
||||
p.frame_ancestors :self, 'https://*.atlassian.net'
|
||||
# *.jira.com is needed for some legacy Jira Cloud instances, new ones will use *.atlassian.net
|
||||
# https://support.atlassian.com/organization-administration/docs/ip-addresses-and-domains-for-atlassian-cloud-products/
|
||||
p.frame_ancestors :self, 'https://*.atlassian.net', 'https://*.jira.com'
|
||||
p.script_src(*script_src_values)
|
||||
p.style_src(*style_src_values)
|
||||
end
|
||||
|
|
|
@ -142,7 +142,7 @@ module Resolvers
|
|||
def object
|
||||
super.tap do |obj|
|
||||
# If the field this resolver is used in is wrapped in a presenter, unwrap its subject
|
||||
break obj.subject if obj.is_a?(Gitlab::View::Presenter::Base)
|
||||
break obj.__subject__ if obj.is_a?(Gitlab::View::Presenter::Base)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ module MergeRequestsHelper
|
|||
endpoint_metadata: @endpoint_metadata_url,
|
||||
endpoint_batch: diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params),
|
||||
endpoint_coverage: @coverage_path,
|
||||
help_page_path: help_page_path('user/discussions/index.md', anchor: 'suggest-changes'),
|
||||
help_page_path: help_page_path('user/project/merge_requests/reviews/suggestions.md'),
|
||||
current_user_data: @current_user_data,
|
||||
update_current_user_path: @update_current_user_path,
|
||||
project_path: project_path(merge_request.project),
|
||||
|
|
|
@ -838,6 +838,8 @@ module Ci
|
|||
def predefined_commit_variables
|
||||
strong_memoize(:predefined_commit_variables) do
|
||||
Gitlab::Ci::Variables::Collection.new.tap do |variables|
|
||||
next variables unless sha.present?
|
||||
|
||||
variables.append(key: 'CI_COMMIT_SHA', value: sha)
|
||||
variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
|
||||
variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
|
||||
|
|
|
@ -200,18 +200,6 @@ module Issuable
|
|||
incident?
|
||||
end
|
||||
|
||||
# When :incident_escalations feature flag is disabled, new
|
||||
# incidents should not have a status record unless the incident
|
||||
# is associated with the alert. However, escalation attributes
|
||||
# are synced with Alert/IssuableEscalationStatus, so we want to
|
||||
# ensure that parity is kept prior to rollout.
|
||||
# Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/345769.
|
||||
def sync_escalation_attributes_from_alert?
|
||||
incident? &&
|
||||
::Feature.disabled?(:incident_escalations, project) &&
|
||||
alert_management_alert.present?
|
||||
end
|
||||
|
||||
def incident?
|
||||
is_a?(Issue) && super
|
||||
end
|
||||
|
|
|
@ -68,9 +68,11 @@ we gain the following benefits:
|
|||
|
||||
If you need a presenter class that has only necessary interfaces for the view-related context,
|
||||
inherit from `Gitlab::View::Presenter::Simple`.
|
||||
It provides a `.presents` the method which allows you to define an accessor for the
|
||||
presented object. It also includes common helpers like `Gitlab::Routing` and
|
||||
`Gitlab::Allowable`.
|
||||
|
||||
It provides a `.presents` class method which allows you to define the class the presenter is wrapping,
|
||||
and specify an accessor for the presented object using the `as:` keyword.
|
||||
|
||||
It also includes common helpers like `Gitlab::Routing` and `Gitlab::Allowable`.
|
||||
|
||||
```ruby
|
||||
class LabelPresenter < Gitlab::View::Presenter::Simple
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
module Ci
|
||||
class BridgePresenter < ProcessablePresenter
|
||||
presents ::Ci::Bridge
|
||||
presents ::Ci::Bridge, as: :bridge
|
||||
|
||||
delegator_override :detailed_status
|
||||
def detailed_status
|
||||
@detailed_status ||= subject.detailed_status(user)
|
||||
@detailed_status ||= bridge.detailed_status(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Ci
|
||||
class BuildPresenter < ProcessablePresenter
|
||||
presents ::Ci::Build
|
||||
presents ::Ci::Build, as: :build
|
||||
|
||||
def erased_by_user?
|
||||
# Build can be erased through API, therefore it does not have
|
||||
|
@ -34,7 +34,7 @@ module Ci
|
|||
end
|
||||
|
||||
def tooltip_message
|
||||
"#{subject.name} - #{detailed_status.status_tooltip}"
|
||||
"#{build.name} - #{detailed_status.status_tooltip}"
|
||||
end
|
||||
|
||||
def execute_in
|
||||
|
@ -48,7 +48,7 @@ module Ci
|
|||
end
|
||||
|
||||
def detailed_status
|
||||
@detailed_status ||= subject.detailed_status(user)
|
||||
@detailed_status ||= build.detailed_status(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,7 +39,7 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
|
|||
|
||||
private_constant :CALLOUT_FAILURE_MESSAGES
|
||||
|
||||
presents ::CommitStatus, as: :build
|
||||
presents ::CommitStatus
|
||||
|
||||
def self.callout_failure_messages
|
||||
CALLOUT_FAILURE_MESSAGES
|
||||
|
|
|
@ -2,28 +2,28 @@
|
|||
|
||||
module DevOpsReport
|
||||
class MetricPresenter < Gitlab::View::Presenter::Simple
|
||||
presents ::DevOpsReport::Metric
|
||||
presents ::DevOpsReport::Metric, as: :metric
|
||||
|
||||
delegate :created_at, to: :subject
|
||||
delegate :created_at, to: :metric
|
||||
|
||||
def cards
|
||||
[
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Issues',
|
||||
description: 'created per active user',
|
||||
feature: 'issues',
|
||||
blog: 'https://www2.deloitte.com/content/dam/Deloitte/se/Documents/technology-media-telecommunications/deloitte-digital-collaboration.pdf'
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Comments',
|
||||
description: 'created per active user',
|
||||
feature: 'notes',
|
||||
blog: 'http://conversationaldevelopment.com/why/'
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Milestones',
|
||||
description: 'created per active user',
|
||||
feature: 'milestones',
|
||||
|
@ -31,7 +31,7 @@ module DevOpsReport
|
|||
docs: help_page_path('user/project/milestones/index')
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Boards',
|
||||
description: 'created per active user',
|
||||
feature: 'boards',
|
||||
|
@ -39,7 +39,7 @@ module DevOpsReport
|
|||
docs: help_page_path('user/project/issue_board')
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Merge requests',
|
||||
description: 'per active user',
|
||||
feature: 'merge_requests',
|
||||
|
@ -47,7 +47,7 @@ module DevOpsReport
|
|||
docs: help_page_path('user/project/merge_requests/index')
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Pipelines',
|
||||
description: 'created per active user',
|
||||
feature: 'ci_pipelines',
|
||||
|
@ -55,7 +55,7 @@ module DevOpsReport
|
|||
docs: help_page_path('ci/index')
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Environments',
|
||||
description: 'created per active user',
|
||||
feature: 'environments',
|
||||
|
@ -63,14 +63,14 @@ module DevOpsReport
|
|||
docs: help_page_path('ci/environments')
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Deployments',
|
||||
description: 'created per active user',
|
||||
feature: 'deployments',
|
||||
blog: 'https://puppet.com/blog/continuous-delivery-vs-continuous-deployment-what-s-diff'
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Monitoring',
|
||||
description: 'fraction of all projects',
|
||||
feature: 'projects_prometheus_active',
|
||||
|
@ -78,7 +78,7 @@ module DevOpsReport
|
|||
docs: help_page_path('user/project/integrations/prometheus')
|
||||
),
|
||||
Card.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Service Desk',
|
||||
description: 'issues created per active user',
|
||||
feature: 'service_desk_issues',
|
||||
|
@ -91,52 +91,52 @@ module DevOpsReport
|
|||
def idea_to_production_steps
|
||||
[
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Idea',
|
||||
features: %w(issues)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Issue',
|
||||
features: %w(issues notes)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Plan',
|
||||
features: %w(milestones boards)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Code',
|
||||
features: %w(merge_requests)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Commit',
|
||||
features: %w(merge_requests)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Test',
|
||||
features: %w(ci_pipelines)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Review',
|
||||
features: %w(ci_pipelines environments)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Staging',
|
||||
features: %w(environments deployments)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Production',
|
||||
features: %w(deployments)
|
||||
),
|
||||
IdeaToProductionStep.new(
|
||||
metric: subject,
|
||||
metric: metric,
|
||||
title: 'Feedback',
|
||||
features: %w(projects_prometheus_active service_desk_issues)
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
class EventPresenter < Gitlab::View::Presenter::Delegated
|
||||
presents ::Event, as: :event
|
||||
|
||||
def initialize(subject, **attributes)
|
||||
def initialize(event, **attributes)
|
||||
super
|
||||
|
||||
@visible_to_user_cache = ActiveSupport::Cache::MemoryStore.new
|
||||
|
|
|
@ -21,7 +21,7 @@ module Gitlab
|
|||
:project_blame_link,
|
||||
:time_ago_tooltip)
|
||||
|
||||
def initialize(subject, **attributes)
|
||||
def initialize(blame, **attributes)
|
||||
super
|
||||
|
||||
@commits = {}
|
||||
|
|
|
@ -4,8 +4,6 @@ class LabelPresenter < Gitlab::View::Presenter::Delegated
|
|||
presents ::Label, as: :label
|
||||
delegate :name, :full_name, to: :label_subject, prefix: :subject, allow_nil: true
|
||||
|
||||
delegator_override :subject # TODO: Fix `Gitlab::View::Presenter::Delegated#subject` not to override `Label#subject`.
|
||||
|
||||
def edit_path
|
||||
case label
|
||||
when GroupLabel then edit_group_label_path(label.group, label)
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
class PagesDomainPresenter < Gitlab::View::Presenter::Delegated
|
||||
presents ::PagesDomain, as: :pages_domain
|
||||
|
||||
delegator_override :subject # TODO: Fix `Gitlab::View::Presenter::Delegated#subject` not to override `PagesDomain#subject`.
|
||||
|
||||
def needs_verification?
|
||||
Gitlab::CurrentSettings.pages_domain_verification_enabled? && unverified?
|
||||
end
|
||||
|
|
|
@ -151,25 +151,14 @@ module AlertManagement
|
|||
status_change_reason: " by changing the status of #{alert.to_reference(project)}"
|
||||
}
|
||||
}
|
||||
).execute(issue)
|
||||
end
|
||||
|
||||
def issue
|
||||
strong_memoize(:issue) { alert.issue }
|
||||
).execute(alert.issue)
|
||||
end
|
||||
|
||||
def should_sync_to_incident?
|
||||
return false unless sync_available?
|
||||
|
||||
issue.escalation_status&.status != alert.status
|
||||
end
|
||||
|
||||
def sync_available?
|
||||
return false unless issue.present?
|
||||
|
||||
# Remove sync check with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
|
||||
issue.supports_escalation? ||
|
||||
issue.sync_escalation_attributes_from_alert?
|
||||
alert.issue &&
|
||||
alert.issue.supports_escalation? &&
|
||||
alert.issue.escalation_status &&
|
||||
alert.issue.escalation_status.status != alert.status
|
||||
end
|
||||
|
||||
def filter_duplicate
|
||||
|
|
|
@ -31,10 +31,7 @@ module IncidentManagement
|
|||
attr_reader :issuable, :param_errors
|
||||
|
||||
def available?
|
||||
(
|
||||
issuable.supports_escalation? ||
|
||||
issuable.sync_escalation_attributes_from_alert? # Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
|
||||
) && user_has_permissions?
|
||||
issuable.supports_escalation? && user_has_permissions?
|
||||
end
|
||||
|
||||
def user_has_permissions?
|
||||
|
@ -63,14 +60,6 @@ module IncidentManagement
|
|||
status = params.delete(:status)
|
||||
return unless status
|
||||
|
||||
# If we're updating the escalation status because the
|
||||
# alert was updated & the feature flag is disabled, then
|
||||
# we should not allow the status to be different from the alert's.
|
||||
# Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
|
||||
if issuable.sync_escalation_attributes_from_alert? && status != issuable.alert_management_alert.status_name
|
||||
add_param_error(:status) && return
|
||||
end
|
||||
|
||||
status_event = escalation_status.status_event_for(status)
|
||||
add_param_error(:status) && return unless status_event
|
||||
|
||||
|
|
|
@ -87,10 +87,7 @@ module Issues
|
|||
attr_reader :spam_params
|
||||
|
||||
def create_escalation_status(issue)
|
||||
# Remove sync check with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
|
||||
return unless issue.supports_escalation? || issue.sync_escalation_attributes_from_alert?
|
||||
|
||||
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute
|
||||
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
|
||||
end
|
||||
|
||||
def user_agent_detail_service
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
= link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" }
|
||||
|
||||
- if @milestones.blank?
|
||||
= render 'shared/empty_states/milestones_tab', learn_more_path: help_page_path('user/group/milestones') do
|
||||
= render 'shared/empty_states/milestones_tab', learn_more_path: help_page_path('user/project/milestones/index') do
|
||||
- if can?(current_user, :admin_milestone, @group)
|
||||
.text-center
|
||||
= link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" }
|
||||
|
@ -26,7 +26,7 @@
|
|||
= render 'milestone', milestone: milestone
|
||||
= paginate @milestones, theme: "gitlab"
|
||||
- else
|
||||
= render 'shared/empty_states/milestones', learn_more_path: help_page_path('user/group/milestones') do
|
||||
= render 'shared/empty_states/milestones', learn_more_path: help_page_path('user/project/milestones/index') do
|
||||
- if can?(current_user, :admin_milestone, @group)
|
||||
.text-center
|
||||
= link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-confirm", data: { qa_selector: "new_group_milestone_link" }
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
- return unless Feature.enabled?(:group_import_export, @group, default_enabled: true)
|
||||
|
||||
- group = local_assigns.fetch(:group)
|
||||
|
||||
.sub-section
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: group_import_export
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22423
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282245
|
||||
milestone: '12.8'
|
||||
name: ci_variables_builder_config_variables
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79935
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/358791
|
||||
milestone: '14.10'
|
||||
type: development
|
||||
group: group::import
|
||||
default_enabled: true
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348151
|
|||
milestone: '14.9'
|
||||
type: development
|
||||
group: group::threat insights
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
table_name: approval_merge_request_rules_approved_approvers
|
||||
classes: []
|
||||
feature_categories:
|
||||
- source_code_management
|
||||
- code_review
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: boards
|
|||
classes:
|
||||
- Board
|
||||
feature_categories:
|
||||
- team_planning
|
||||
- design_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: ci_build_report_results
|
|||
classes:
|
||||
- Ci::BuildReportResult
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
- code_testing
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: ci_pipelines
|
|||
classes:
|
||||
- Ci::Pipeline
|
||||
feature_categories:
|
||||
- code_review
|
||||
- continuous_integration
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: ci_pipelines_config
|
|||
classes:
|
||||
- Ci::PipelineConfig
|
||||
feature_categories:
|
||||
- pipeline_authoring
|
||||
- continuous_integration
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: ci_runner_namespaces
|
|||
classes:
|
||||
- Ci::RunnerNamespace
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
- runner
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: ci_unit_test_failures
|
|||
classes:
|
||||
- Ci::UnitTestFailure
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
- code_testing
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: deployment_merge_requests
|
|||
classes:
|
||||
- DeploymentMergeRequest
|
||||
feature_categories:
|
||||
- deployment_management
|
||||
- advanced_deployments
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: description_versions
|
|||
classes:
|
||||
- DescriptionVersion
|
||||
feature_categories:
|
||||
- team_planning
|
||||
- design_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: dora_daily_metrics
|
|||
classes:
|
||||
- Dora::DailyMetrics
|
||||
feature_categories:
|
||||
- continuous_delivery
|
||||
- value_stream_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: experiment_subjects
|
|||
classes:
|
||||
- ExperimentSubject
|
||||
feature_categories:
|
||||
- experimentation_expansion
|
||||
- experimentation_conversion
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: experiment_users
|
|||
classes:
|
||||
- ExperimentUser
|
||||
feature_categories:
|
||||
- experimentation_expansion
|
||||
- experimentation_conversion
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: fork_network_members
|
|||
classes:
|
||||
- ForkNetworkMember
|
||||
feature_categories:
|
||||
- devops_reports
|
||||
- source_code_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: in_product_marketing_emails
|
|||
classes:
|
||||
- Users::InProductMarketingEmail
|
||||
feature_categories:
|
||||
- navigation
|
||||
- experimentation_activation
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: issue_email_participants
|
|||
classes:
|
||||
- IssueEmailParticipant
|
||||
feature_categories:
|
||||
- users
|
||||
- service_desk
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: issue_metrics
|
|||
classes:
|
||||
- Issue::Metrics
|
||||
feature_categories:
|
||||
- source_code_management
|
||||
- value_stream_management
|
||||
description:
|
||||
|
|
|
@ -3,6 +3,5 @@ table_name: issue_user_mentions
|
|||
classes:
|
||||
- IssueUserMention
|
||||
feature_categories:
|
||||
- users
|
||||
- team_planning
|
||||
description:
|
||||
|
|
|
@ -4,4 +4,5 @@ classes:
|
|||
- LfsObjectsProject
|
||||
feature_categories:
|
||||
- git_lfs
|
||||
- source_code_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: lists
|
|||
classes:
|
||||
- List
|
||||
feature_categories:
|
||||
- team_planning
|
||||
- design_management
|
||||
description:
|
||||
|
|
|
@ -6,5 +6,6 @@ classes:
|
|||
- ProjectMember
|
||||
- ProjectNamespaceMember
|
||||
feature_categories:
|
||||
- authentication_and_authorization
|
||||
- projects
|
||||
- subgroups
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: merge_request_assignees
|
|||
classes:
|
||||
- MergeRequestAssignee
|
||||
feature_categories:
|
||||
- team_planning
|
||||
- code_review
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,6 @@ table_name: merge_request_metrics
|
|||
classes:
|
||||
- MergeRequest::Metrics
|
||||
feature_categories:
|
||||
- metrics
|
||||
- value_stream_management
|
||||
- code_review
|
||||
description:
|
||||
|
|
|
@ -4,5 +4,4 @@ classes:
|
|||
- MergeRequestUserMention
|
||||
feature_categories:
|
||||
- code_review
|
||||
- users
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: merge_requests_closing_issues
|
|||
classes:
|
||||
- MergeRequestsClosingIssues
|
||||
feature_categories:
|
||||
- team_planning
|
||||
- code_review
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: namespace_root_storage_statistics
|
|||
classes:
|
||||
- Namespace::RootStorageStatistics
|
||||
feature_categories:
|
||||
- subgroups
|
||||
- utilization
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: namespace_statistics
|
|||
classes:
|
||||
- NamespaceStatistics
|
||||
feature_categories:
|
||||
- source_code_management
|
||||
- utilization
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: notification_settings
|
|||
classes:
|
||||
- NotificationSetting
|
||||
feature_categories:
|
||||
- users
|
||||
- team_planning
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: project_authorizations
|
|||
classes:
|
||||
- ProjectAuthorization
|
||||
feature_categories:
|
||||
- authentication_and_authorization
|
||||
- projects
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: project_auto_devops
|
|||
classes:
|
||||
- ProjectAutoDevops
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
- auto_devops
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: project_repositories
|
|||
classes:
|
||||
- ProjectRepository
|
||||
feature_categories:
|
||||
- projects
|
||||
- source_code_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: project_repository_states
|
|||
classes:
|
||||
- ProjectRepositoryState
|
||||
feature_categories:
|
||||
- projects
|
||||
- source_code_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: project_repository_storage_moves
|
|||
classes:
|
||||
- Projects::RepositoryStorageMove
|
||||
feature_categories:
|
||||
- gitaly
|
||||
- source_code_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: project_settings
|
|||
classes:
|
||||
- ProjectSetting
|
||||
feature_categories:
|
||||
- error_tracking
|
||||
- projects
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: push_event_payloads
|
|||
classes:
|
||||
- PushEventPayload
|
||||
feature_categories:
|
||||
- gitaly
|
||||
- source_code_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: push_rules
|
|||
classes:
|
||||
- PushRule
|
||||
feature_categories:
|
||||
- source_code_management
|
||||
- compliance_management
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: resource_iteration_events
|
|||
classes:
|
||||
- ResourceIterationEvent
|
||||
feature_categories:
|
||||
- users
|
||||
- planning_analytics
|
||||
description:
|
||||
|
|
|
@ -3,6 +3,5 @@ table_name: resource_label_events
|
|||
classes:
|
||||
- ResourceLabelEvent
|
||||
feature_categories:
|
||||
- projects
|
||||
- subgroups
|
||||
- planning_analytics
|
||||
description:
|
||||
|
|
|
@ -3,6 +3,5 @@ table_name: resource_state_events
|
|||
classes:
|
||||
- ResourceStateEvent
|
||||
feature_categories:
|
||||
- source_code_management
|
||||
- team_planning
|
||||
description:
|
||||
|
|
|
@ -3,5 +3,5 @@ table_name: timelogs
|
|||
classes:
|
||||
- Timelog
|
||||
feature_categories:
|
||||
- audit_events
|
||||
- team_planning
|
||||
description:
|
||||
|
|
|
@ -265,6 +265,20 @@ Feature.disable(:dependency_proxy_for_private_groups)
|
|||
Feature.enable(:dependency_proxy_for_private_groups)
|
||||
```
|
||||
|
||||
## Changing the JWT expiration
|
||||
|
||||
The Dependency Proxy follows the [Docker v2 token authentication flow](https://docs.docker.com/registry/spec/auth/token/),
|
||||
issuing the client a JWT to use for the pull requests. The token expiration time is a configurable
|
||||
using the application setting `container_registry_token_expire_delay`. It can be changed from the
|
||||
rails console:
|
||||
|
||||
```ruby
|
||||
# update the JWT expiration to 30 minutes
|
||||
ApplicationSetting.update(container_registry_token_expire_delay: 30)
|
||||
```
|
||||
|
||||
The default expiration and the expiration on GitLab.com is 15 minutes.
|
||||
|
||||
## Using the dependency proxy behind a proxy
|
||||
|
||||
1. Edit `/etc/gitlab/gitlab.rb` and add the following lines:
|
||||
|
|
|
@ -23,6 +23,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
## Migrations
|
||||
|
||||
- [Migrations for multiple databases](migrations_for_multiple_databases.md)
|
||||
- [Avoiding downtime in migrations](avoiding_downtime_in_migrations.md)
|
||||
- [SQL guidelines](../sql.md) for working with SQL queries
|
||||
- [Migrations style guide](../migration_style_guide.md) for creating safe SQL migrations
|
||||
|
|
|
@ -0,0 +1,390 @@
|
|||
---
|
||||
stage: Enablement
|
||||
group: Database
|
||||
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
|
||||
---
|
||||
|
||||
# Migrations for Multiple databases
|
||||
|
||||
> Support for describing migration purposes was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73756) in GitLab 14.8.
|
||||
|
||||
This document describes how to properly write database migrations
|
||||
for [the decomposed GitLab application using multiple databases](https://gitlab.com/groups/gitlab-org/-/epics/6168).
|
||||
|
||||
Learn more about general multiple databases support in a [separate document](multiple_databases.md).
|
||||
|
||||
WARNING:
|
||||
If you experience any issues using `Gitlab::Database::Migration[2.0]`,
|
||||
you can temporarily revert back to the previous behavior by changing the version to `Gitlab::Database::Migration[1.0]`.
|
||||
Please report any issues with `Gitlab::Database::Migration[2.0]` in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/358430).
|
||||
|
||||
The design for multiple databases (except for the Geo database) assumes
|
||||
that all decomposed databases have **the same structure** (for example, schema), but **the data is different** in each database. This means that some tables do not contain data on each database.
|
||||
|
||||
## Operations
|
||||
|
||||
Depending on the used constructs, we can classify migrations to be either:
|
||||
|
||||
1. Modifying structure ([DDL - Data Definition Language](https://www.postgresql.org/docs/current/ddl.html)) (for example, `ALTER TABLE`).
|
||||
1. Modifying data ([DML - Data Manipulation Language](https://www.postgresql.org/docs/current/dml.html)) (for example, `UPDATE`).
|
||||
1. Performing [other queries](https://www.postgresql.org/docs/current/queries.html) (for example, `SELECT`) that are treated as **DML** for the purposes of our migrations.
|
||||
|
||||
**The usage of `Gitlab::Database::Migration[2.0]` requires migrations to always be of a single purpose**.
|
||||
Migrations cannot mix **DDL** and **DML** changes as the application requires the structure
|
||||
(as described by `db/structure.sql`) to be exactly the same across all decomposed databases.
|
||||
|
||||
### Data Definition Language (DDL)
|
||||
|
||||
The DDL migrations are all migrations that:
|
||||
|
||||
1. Create or drop a table (for example, `create_table`).
|
||||
1. Add or remove an index (for example, `add_index`, `add_index_concurrently`).
|
||||
1. Add or remove a foreign key (for example `add_foreign_key`, `add_foreign_key_concurrently`).
|
||||
1. Add or remove a column with or without a default value (for example, `add_column`).
|
||||
1. Create or drop trigger functions (for example, `create_trigger_function`).
|
||||
1. Attach or detach triggers from tables (for example, `track_record_deletions`, `untrack_record_deletions`).
|
||||
1. Prepare or not async indexes (for example, `prepare_async_index`, `unprepare_async_index_by_name`).
|
||||
|
||||
As such DDL migrations **CANNOT**:
|
||||
|
||||
1. Read or modify data in any form, via SQL statements or ActiveRecord models.
|
||||
1. Update column values (for example, `update_column_in_batches`).
|
||||
1. Schedule background migrations (for example, `queue_background_migration_jobs_by_range_at_intervals`).
|
||||
1. Read the state of feature flags since they are stored in `main:` (a `features` and `feature_gates`).
|
||||
1. Read application settings (as settings are stored in `main:`).
|
||||
|
||||
As the majority of migrations in the GitLab codebase are of the DDL-type,
|
||||
this is also the default mode of operation and requires no further changes
|
||||
to the migrations files.
|
||||
|
||||
#### Example: perform DDL on all databases
|
||||
|
||||
Example migration adding a concurrent index that is treated as change of the structure (DDL)
|
||||
that is executed on all configured databases.
|
||||
|
||||
```ruby
|
||||
class AddUserIdAndStateIndexToMergeRequestReviewers < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_on_merge_request_reviewers_user_id_and_state'
|
||||
|
||||
def up
|
||||
add_concurrent_index :merge_request_reviewers, [:user_id, :state], where: 'state = 2', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :merge_request_reviewers, INDEX_NAME
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Data Manipulation Language (DML)
|
||||
|
||||
The DML migrations are all migrations that:
|
||||
|
||||
1. Read data via SQL statements (for example, `SELECT * FROM projects WHERE id=1`).
|
||||
1. Read data via ActiveRecord models (for example, `User < MigrationRecord`).
|
||||
1. Create, update or delete data via ActiveRecord models (for example, `User.create!(...)`).
|
||||
1. Create, update or delete data via SQL statements (for example, `DELETE FROM projects WHERE id=1`).
|
||||
1. Update columns in batches (for example, `update_column_in_batches(:projects, :archived, true)`).
|
||||
1. Schedule background migrations (for example, `queue_background_migration_jobs_by_range_at_intervals`).
|
||||
1. Access application settings (for example, `ApplicationSetting.last` if run for `main:` database).
|
||||
1. Read and modify feature flags if run for the `main:` database.
|
||||
|
||||
The DML migrations **CANNOT**:
|
||||
|
||||
1. Make any changes to DDL since this breaks the rule of keeping `structure.sql` coherent across
|
||||
all decomposed databases.
|
||||
1. **Read data from another database**.
|
||||
|
||||
To indicate the `DML` migration type, a migration must use the `restrict_gitlab_migration gitlab_schema:`
|
||||
syntax in a migration class. This marks the given migration as DML and restricts access to it.
|
||||
|
||||
#### Example: perform DML only in context of the database containing the given `gitlab_schema`
|
||||
|
||||
Example migration updating `archived` column of `projects` that is executed
|
||||
only for the database containing `gitlab_main` schema.
|
||||
|
||||
```ruby
|
||||
class UpdateProjectsArchivedState < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
update_column_in_batches(:projects, :archived, true) do |table, query|
|
||||
query.where(table[:archived].eq(false)) # rubocop:disable CodeReuse/ActiveRecord
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### Example: usage of `ActiveRecord` classes
|
||||
|
||||
A migration using `ActiveRecord` class to perform data manipulation
|
||||
must use the `MigrationRecord` class. This class is guaranteed to provide
|
||||
a correct connection in a context of a given migration.
|
||||
|
||||
Underneath the `MigrationRecord == ActiveRecord::Base`, as once the `db:migrate`
|
||||
runs, it switches the active connection of `ActiveRecord::Base.establish_connection :ci`.
|
||||
To avoid confusion to using the `ActiveRecord::Base`, `MigrationRecord` is required.
|
||||
|
||||
This implies that DML migrations are forbidden to read data from other
|
||||
databases. For example, running migration in context of `ci:` and reading feature flags
|
||||
from `main:`, as no established connection to another database is present.
|
||||
|
||||
```ruby
|
||||
class UpdateProjectsArchivedState < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
class Project < MigrationRecord
|
||||
end
|
||||
|
||||
def up
|
||||
Project.where(archived: false).each_batch of |batch|
|
||||
batch.update_all(archived: true)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### The special purpose of `gitlab_shared`
|
||||
|
||||
As described in [gitlab_schema](multiple_databases.md#the-special-purpose-of-gitlab_shared),
|
||||
the `gitlab_shared` tables are allowed to contain data across all databases. This implies
|
||||
that such migrations should run across all databases to modify structure (DDL) or modify data (DML).
|
||||
|
||||
As such migrations accessing `gitlab_shared` do not need to use `restrict_gitlab_migration gitlab_schema:`,
|
||||
migrations without restriction run across all databases and are allowed to modify data on each of them.
|
||||
If the `restrict_gitlab_migration gitlab_schema:` is specified, the `DML` migration
|
||||
runs only in a context of a database containing the given `gitlab_schema`.
|
||||
|
||||
#### Example: run DML `gitlab_shared` migration on all databases
|
||||
|
||||
Example migration updating `loose_foreign_keys_deleted_records` table
|
||||
that is marked in `lib/gitlab/database/gitlab_schemas.yml` as `gitlab_shared`.
|
||||
|
||||
This migration is executed across all configured databases.
|
||||
|
||||
```ruby
|
||||
class DeleteAllLooseForeignKeyRecords < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
execute("DELETE FROM loose_foreign_keys_deleted_records")
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### Example: run DML `gitlab_shared` only on the database containing the given `gitlab_schema`
|
||||
|
||||
Example migration updating `loose_foreign_keys_deleted_records` table
|
||||
that is marked in `lib/gitlab/database/gitlab_schemas.yml` as `gitlab_shared`.
|
||||
|
||||
This migration since it configures restriction on `gitlab_ci` is executed only
|
||||
in context of database containing `gitlab_ci` schema.
|
||||
|
||||
```ruby
|
||||
class DeleteCiBuildsLooseForeignKeyRecords < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
def up
|
||||
execute("DELETE FROM loose_foreign_keys_deleted_records WHERE fully_qualified_table_name='ci_builds'")
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### The behavior of skipping migrations
|
||||
|
||||
The only migrations that are skipped are the ones performing **DML** changes.
|
||||
The **DDL** migrations are **always and unconditionally** executed.
|
||||
|
||||
The implemented [solution](https://gitlab.com/gitlab-org/gitlab/-/issues/355014#solution-2-use-database_tasks)
|
||||
uses the `database_tasks:` as a way to indicate which additional database configurations
|
||||
(in `config/database.yml`) share the same primary database. The database configurations
|
||||
marked with `database_tasks: false` are exempt from executing `db:migrate` for those
|
||||
database configurations.
|
||||
|
||||
If database configurations do not share databases (all do have `database_tasks: true`),
|
||||
each migration runs for every database configuration:
|
||||
|
||||
1. The DDL migration applies all structure changes on all databases.
|
||||
1. The DML migration runs only in the context of a database containing the given `gitlab_schema:`.
|
||||
1. If the DML migration is not eligible to run, it is skipped. It's still
|
||||
marked as executed in `schema_migrations`. While running `db:migrate`, the skipped
|
||||
migration outputs `Current migration is skipped since it modifies 'gitlab_ci' which is outside of 'gitlab_main, gitlab_shared`.
|
||||
|
||||
To prevent loss of migrations if the `database_tasks: false` is configured, a dedicated
|
||||
Rake task is used [`gitlab:db:validate_config`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83118).
|
||||
The `gitlab:db:validate_config` validates the correctness of `database_tasks:` by checking database identifiers
|
||||
of each underlying database configuration. The ones that share the database are required to have
|
||||
the `database_tasks: false` set. `gitlab:db:validate_config` always runs before `db:migrate`.
|
||||
|
||||
## Validation
|
||||
|
||||
Validation in a nutshell uses [pg_query](https://github.com/pganalyze/pg_query) to analyze
|
||||
each query and classify tables with information from [`gitlab_schema.yml`](multiple_databases.md#gitlab-schema).
|
||||
The migration is skipped if the specified `gitlab_schema` is outside of a list of schemas
|
||||
managed by a given database connection (`Gitlab::Database::gitlab_schemas_for_connection`).
|
||||
|
||||
The `Gitlab::Database::Migration[2.0]` includes `Gitlab::Database::MigrationHelpers::RestrictGitlabSchema`
|
||||
which extends the `#migrate` method. For the duration of a migration a dedicated query analyzer
|
||||
is installed `Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas` that accepts
|
||||
a list of allowed schemas as defined by `restrict_gitlab_migration:`. If the executed query
|
||||
is outside of allowed schemas, it raises an exception.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Depending on misuse or lack of `restrict_gitlab_migration` various exceptions can be raised
|
||||
as part of the migration run and prevent the migration from being completed.
|
||||
|
||||
### Exception 1: migration running in DDL mode does DML select
|
||||
|
||||
```ruby
|
||||
class UpdateProjectsArchivedState < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
# Missing:
|
||||
# restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
update_column_in_batches(:projects, :archived, true) do |table, query|
|
||||
query.where(table[:archived].eq(false)) # rubocop:disable CodeReuse/ActiveRecord
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
```plaintext
|
||||
Select/DML queries (SELECT/UPDATE/DELETE) are disallowed in the DDL (structure) mode
|
||||
Modifying of 'projects' (gitlab_main) with 'SELECT * FROM projects...
|
||||
```
|
||||
|
||||
The current migration do not use `restrict_gitlab_migration`. The lack indicates a migration
|
||||
running in **DDL** mode, but the executed payload appears to be reading data from `projects`.
|
||||
|
||||
**The solution** is to add `restrict_gitlab_migration gitlab_schema: :gitlab_main`.
|
||||
|
||||
### Exception 2: migration running in DML mode changes the structure
|
||||
|
||||
```ruby
|
||||
class AddUserIdAndStateIndexToMergeRequestReviewers < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
# restrict_gitlab_migration if defined indicates DML, it should be removed
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
INDEX_NAME = 'index_on_merge_request_reviewers_user_id_and_state'
|
||||
|
||||
def up
|
||||
add_concurrent_index :merge_request_reviewers, [:user_id, :state], where: 'state = 2', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :merge_request_reviewers, INDEX_NAME
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
```plaintext
|
||||
DDL queries (structure) are disallowed in the Select/DML (SELECT/UPDATE/DELETE) mode.
|
||||
Modifying of 'merge_request_reviewers' with 'CREATE INDEX...
|
||||
```
|
||||
|
||||
The current migration do use `restrict_gitlab_migration`. The presence indicates **DML** mode,
|
||||
but the executed payload appears to be doing structure changes (DDL).
|
||||
|
||||
**The solution** is to remove `restrict_gitlab_migration gitlab_schema: :gitlab_main`.
|
||||
|
||||
### Exception 3: migration running in DML mode accesses data from a table in another schema
|
||||
|
||||
```ruby
|
||||
class UpdateProjectsArchivedState < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
# Since it modifies `projects` it should use `gitlab_main`
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
def up
|
||||
update_column_in_batches(:projects, :archived, true) do |table, query|
|
||||
query.where(table[:archived].eq(false)) # rubocop:disable CodeReuse/ActiveRecord
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
```plaintext
|
||||
Select/DML queries (SELECT/UPDATE/DELETE) do access 'projects' (gitlab_main) " \
|
||||
which is outside of list of allowed schemas: 'gitlab_ci'
|
||||
```
|
||||
|
||||
The current migration do restrict the migration to `gitlab_ci`, but appears to modify
|
||||
data in `gitlab_main`.
|
||||
|
||||
**The solution** is to change `restrict_gitlab_migration gitlab_schema: :gitlab_ci`.
|
||||
|
||||
### Exception 4: mixing DDL and DML mode
|
||||
|
||||
```ruby
|
||||
class UpdateProjectsArchivedState < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
# This migration is invalid regardless of specification
|
||||
# as it cannot modify structure and data at the same time
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
def up
|
||||
add_concurrent_index :merge_request_reviewers, [:user_id, :state], where: 'state = 2', name: 'index_on_merge_request_reviewers'
|
||||
update_column_in_batches(:projects, :archived, true) do |table, query|
|
||||
query.where(table[:archived].eq(false)) # rubocop:disable CodeReuse/ActiveRecord
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
The migrations mixing **DDL** and **DML** depending on ordering of operations raises
|
||||
one of the prior exceptions.
|
||||
|
||||
## Upcoming changes on multiple database migrations
|
||||
|
||||
The `restrict_gitlab_migration` using `gitlab_schema:` is considered as a first iteration
|
||||
of this feature for running migrations selectively depending on a context. It is possible
|
||||
to add additional restrictions to DML-only migrations (as the structure coherency is likely
|
||||
to stay as-is until further notice) to restrict when they run.
|
||||
|
||||
A Potential extension is to limit running DML migration only to specific environments:
|
||||
|
||||
```ruby
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main, gitlab_env: :gitlab_com
|
||||
```
|
|
@ -9,6 +9,63 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
To scale GitLab, the we are
|
||||
[decomposing the GitLab application database into multiple databases](https://gitlab.com/groups/gitlab-org/-/epics/6168).
|
||||
|
||||
## GitLab Schema
|
||||
|
||||
For properly discovering allowed patterns between different databases
|
||||
the GitLab application implements the `lib/gitlab/database/gitlab_schemas.yml` YAML file.
|
||||
|
||||
This file provides a virtual classification of tables into a `gitlab_schema`
|
||||
which conceptually is similar to [PostgreSQL Schema](https://www.postgresql.org/docs/current/ddl-schemas.html).
|
||||
We decided as part of [using database schemas to better isolated CI decomposed features](https://gitlab.com/gitlab-org/gitlab/-/issues/333415)
|
||||
that we cannot use PostgreSQL schema due to complex migration procedures. Instead we implemented
|
||||
the concept of application-level classification.
|
||||
Each table of GitLab needs to have a `gitlab_schema` assigned:
|
||||
|
||||
- `gitlab_main`: describes all tables that are being stored in the `main:` database (for example, like `projects`, `users`).
|
||||
- `gitlab_ci`: describes all CI tables that are being stored in the `ci:` database (for example, `ci_pipelines`, `ci_builds`).
|
||||
- `gitlab_shared`: describe all application tables that contain data across all decomposed databases (for example, `loose_foreign_keys_deleted_records`).
|
||||
- `...`: more schemas to be introduced with additional decomposed databases
|
||||
|
||||
The usage of schema enforces the base class to be used:
|
||||
|
||||
- `ApplicationRecord` for `gitlab_main`
|
||||
- `Ci::ApplicationRecord` for `gitlab_ci`
|
||||
- `Gitlab::Database::SharedModel` for `gitlab_shared`
|
||||
|
||||
### The impact of `gitlab_schema`
|
||||
|
||||
The usage of `gitlab_schema` has a significant impact on the application.
|
||||
The `gitlab_schema` primary purpose is to introduce a barrier between different data access patterns.
|
||||
|
||||
This is used as a primary source of classification for:
|
||||
|
||||
- [Discovering cross-joins across tables from different schemas](#removing-joins-between-ci_-and-non-ci_-tables)
|
||||
- [Discovering cross-database transactions across tables from different schemas](#removing-cross-database-transactions)
|
||||
|
||||
### The special purpose of `gitlab_shared`
|
||||
|
||||
`gitlab_shared` is a special case describing tables or views that by design contain data across
|
||||
all decomposed databases. This does describe application-defined tables (like `loose_foreign_keys_deleted_records`),
|
||||
Rails-defined tables (like `schema_migrations` or `ar_internal_metadata` as well as internal PostgreSQL tables
|
||||
(for example, `pg_attribute`).
|
||||
|
||||
**Be careful** to use `gitlab_shared` as it requires special handling while accessing data.
|
||||
Since `gitlab_shared` shares not only structure but also data, the application needs to be written in a way
|
||||
that traverses all data from all databases in sequential manner.
|
||||
|
||||
```ruby
|
||||
Gitlab::Database::EachDatabase.each_model_connection([MySharedModel]) do |connection, connection_name|
|
||||
MySharedModel.select_all_data...
|
||||
end
|
||||
```
|
||||
|
||||
As such, migrations modifying data of `gitlab_shared` tables are expected to run across
|
||||
all decomposed databases.
|
||||
|
||||
## Migrations
|
||||
|
||||
Read [Migrations for Multiple Databases](migrations_for_multiple_databases.md).
|
||||
|
||||
## CI/CD Database
|
||||
|
||||
> Support for configuring the GitLab Rails application to use a distinct
|
||||
|
|
|
@ -240,7 +240,7 @@ of migration helpers.
|
|||
In this example, we use version 1.0 of the migration class:
|
||||
|
||||
```ruby
|
||||
class TestMigration < Gitlab::Database::Migration[1.0]
|
||||
class TestMigration < Gitlab::Database::Migration[2.0]
|
||||
def change
|
||||
end
|
||||
end
|
||||
|
@ -253,7 +253,7 @@ version of migration helpers automatically.
|
|||
Migration helpers and versioning were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68986)
|
||||
in GitLab 14.3.
|
||||
For merge requests targeting previous stable branches, use the old format and still inherit from
|
||||
`ActiveRecord::Migration[6.1]` instead of `Gitlab::Database::Migration[1.0]`.
|
||||
`ActiveRecord::Migration[6.1]` instead of `Gitlab::Database::Migration[2.0]`.
|
||||
|
||||
## Retry mechanism when acquiring database locks
|
||||
|
||||
|
@ -535,7 +535,7 @@ by calling the method `disable_ddl_transaction!` in the body of your migration
|
|||
class like so:
|
||||
|
||||
```ruby
|
||||
class MyMigration < Gitlab::Database::Migration[1.0]
|
||||
class MyMigration < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_name'
|
||||
|
@ -586,7 +586,7 @@ by calling the method `disable_ddl_transaction!` in the body of your migration
|
|||
class like so:
|
||||
|
||||
```ruby
|
||||
class MyMigration < Gitlab::Database::Migration[1.0]
|
||||
class MyMigration < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_name'
|
||||
|
@ -629,7 +629,7 @@ The easiest way to test for existence of an index by name is to use the
|
|||
be used with a name option. For example:
|
||||
|
||||
```ruby
|
||||
class MyMigration < Gitlab::Database::Migration[1.0]
|
||||
class MyMigration < Gitlab::Database::Migration[2.0]
|
||||
INDEX_NAME = 'index_name'
|
||||
|
||||
def up
|
||||
|
@ -664,7 +664,7 @@ Here's an example where we add a new column with a foreign key
|
|||
constraint. Note it includes `index: true` to create an index for it.
|
||||
|
||||
```ruby
|
||||
class Migration < Gitlab::Database::Migration[1.0]
|
||||
class Migration < Gitlab::Database::Migration[2.0]
|
||||
|
||||
def change
|
||||
add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade }
|
||||
|
@ -710,7 +710,7 @@ expensive and disruptive operation for larger tables, but in reality it's not.
|
|||
Take the following migration as an example:
|
||||
|
||||
```ruby
|
||||
class DefaultRequestAccessGroups < Gitlab::Database::Migration[1.0]
|
||||
class DefaultRequestAccessGroups < Gitlab::Database::Migration[2.0]
|
||||
def change
|
||||
change_column_default(:namespaces, :request_access_enabled, from: false, to: true)
|
||||
end
|
||||
|
@ -943,7 +943,7 @@ The Rails 5 natively supports `JSONB` (binary JSON) column type.
|
|||
Example migration adding this column:
|
||||
|
||||
```ruby
|
||||
class AddOptionsToBuildMetadata < Gitlab::Database::Migration[1.0]
|
||||
class AddOptionsToBuildMetadata < Gitlab::Database::Migration[2.0]
|
||||
def change
|
||||
add_column :ci_builds_metadata, :config_options, :jsonb
|
||||
end
|
||||
|
@ -975,7 +975,7 @@ Do not store `attr_encrypted` attributes as `:text` in the database; use
|
|||
efficient:
|
||||
|
||||
```ruby
|
||||
class AddSecretToSomething < Gitlab::Database::Migration[1.0]
|
||||
class AddSecretToSomething < Gitlab::Database::Migration[2.0]
|
||||
def change
|
||||
add_column :something, :encrypted_secret, :binary
|
||||
add_column :something, :encrypted_secret_iv, :binary
|
||||
|
@ -1033,8 +1033,8 @@ If you need more complex logic, you can define and use models local to a
|
|||
migration. For example:
|
||||
|
||||
```ruby
|
||||
class MyMigration < Gitlab::Database::Migration[1.0]
|
||||
class Project < ActiveRecord::Base
|
||||
class MyMigration < Gitlab::Database::Migration[2.0]
|
||||
class Project < MigrationRecord
|
||||
self.table_name = 'projects'
|
||||
end
|
||||
|
||||
|
@ -1132,8 +1132,8 @@ in a previous migration.
|
|||
It is important not to leave out the `User.reset_column_information` command, in order to ensure that the old schema is dropped from the cache and ActiveRecord loads the updated schema information.
|
||||
|
||||
```ruby
|
||||
class AddAndSeedMyColumn < Gitlab::Database::Migration[1.0]
|
||||
class User < ActiveRecord::Base
|
||||
class AddAndSeedMyColumn < Gitlab::Database::Migration[2.0]
|
||||
class User < MigrationRecord
|
||||
self.table_name = 'users'
|
||||
end
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ could result in loading unexpected code or associations which may cause unintend
|
|||
side effects or failures during upgrades.
|
||||
|
||||
```ruby
|
||||
class SomeMigration < Gitlab::Database::Migration[1.0]
|
||||
class Services < ActiveRecord::Base
|
||||
class SomeMigration < Gitlab::Database::Migration[2.0]
|
||||
class Services < MigrationRecord
|
||||
self.table_name = 'services'
|
||||
self.inheritance_column = :_type_disabled
|
||||
end
|
||||
|
|
|
@ -254,13 +254,13 @@ of records plucked. `MAX_PLUCK` defaults to `1_000` in `ApplicationRecord`.
|
|||
|
||||
## Inherit from ApplicationRecord
|
||||
|
||||
Most models in the GitLab codebase should inherit from `ApplicationRecord`,
|
||||
rather than from `ActiveRecord::Base`. This allows helper methods to be easily
|
||||
added.
|
||||
Most models in the GitLab codebase should inherit from `ApplicationRecord`
|
||||
or `Ci::ApplicationRecord` rather than from `ActiveRecord::Base`. This allows
|
||||
helper methods to be easily added.
|
||||
|
||||
An exception to this rule exists for models created in database migrations. As
|
||||
these should be isolated from application code, they should continue to subclass
|
||||
from `ActiveRecord::Base`.
|
||||
from `MigrationRecord` which is available only in migration context.
|
||||
|
||||
## Use UNIONs
|
||||
|
||||
|
|
|
@ -1236,3 +1236,24 @@ analyzers, edit your `gitlab-ci.yml` file and either:
|
|||
For example, currently the `gemnasium-maven-dependency_scanning` job pulls the latest
|
||||
`gemnasium-maven` Docker image because `DS_ANALYZER_IMAGE` is set to
|
||||
`"$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"`.
|
||||
|
||||
### Dependency Scanning of setuptools project fails with `use_2to3 is invalid` error
|
||||
|
||||
Support for [2to3](https://docs.python.org/3/library/2to3.html)
|
||||
was [removed](https://setuptools.pypa.io/en/latest/history.html#v58-0-0)
|
||||
in `setuptools` version `v58.0.0`. Dependency Scanning (running `python 3.9`) uses `setuptools`
|
||||
version `58.1.0+`, which doesn't support `2to3`. Therefore, a `setuptools` dependency relying on
|
||||
`lib2to3` will fail with this message:
|
||||
|
||||
```plaintext
|
||||
error in <dependency name> setup command: use_2to3 is invalid
|
||||
```
|
||||
|
||||
To work around this error, downgrade the analyzer's version of `setuptools` (e.g. `v57.5.0`):
|
||||
|
||||
```yaml
|
||||
gemnasium-python-dependency_scanning:
|
||||
before_script:
|
||||
- pip install setuptools==57.5.0
|
||||
image: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9
|
||||
```
|
||||
|
|
|
@ -63,13 +63,12 @@ To register an agent with GitLab:
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7, the agent configuration file can be added to multiple directories (or subdirectories) of the repository.
|
||||
> - Group authorization was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
|
||||
|
||||
You can use an agent configuration file to specify details about your implementation.
|
||||
Creating a file is optional but is needed if:
|
||||
The agent is configured through a configuration file. This file is optional. Without a configuration file, you can still use the CI/CD workflow in the project where the agent is registered.
|
||||
|
||||
- You use [a GitOps workflow](../gitops.md#gitops-configuration-reference) and you want a more advanced configuration.
|
||||
- You use a GitLab CI/CD workflow. In that workflow, you must [authorize the agent](../ci_cd_tunnel.md#authorize-the-agent).
|
||||
You need a configuration file if:
|
||||
|
||||
If you do not create an agent configuration file, you can use the CI/CD workflow in the project where the agent is registered only.
|
||||
- You want to use [a GitOps workflow](../gitops.md#gitops-configuration-reference).
|
||||
- You want to authorize a different project to use the agent for a [GitLab CI/CD workflow](../ci_cd_tunnel.md#authorize-the-agent).
|
||||
|
||||
To create an agent configuration file, go to the GitLab project. In the repository, create a file called `config.yaml` at this path:
|
||||
|
||||
|
@ -83,108 +82,62 @@ To create an agent configuration file, go to the GitLab project. In the reposito
|
|||
- For a GitOps workflow, view [the configuration reference](../gitops.md#gitops-configuration-reference) for details.
|
||||
- For a GitLab CI/CD workflow, you can leave the file blank for now.
|
||||
|
||||
The agent bootstraps with the GitLab installation URL and an access token,
|
||||
and you provide the rest of the configuration in your repository, following
|
||||
Infrastructure as Code (IaaC) best practices.
|
||||
|
||||
### Install the agent in the cluster
|
||||
|
||||
> Introduced in GitLab 14.10, GitLab recommends using Helm to install the agent.
|
||||
|
||||
To connect your cluster to GitLab, install the registered agent
|
||||
in your cluster. To install it, you can use either:
|
||||
in your cluster. You can either:
|
||||
|
||||
- [The one-liner installation method](#one-liner-installation).
|
||||
- [The advanced installation method](#advanced-installation).
|
||||
- [Install the agent with Helm](#install-the-agent-with-helm).
|
||||
- Or, follow the [advanced installation method](#advanced-installation-method).
|
||||
|
||||
You can use the one-liner installation for trying to use the agent for the first time, to do internal setups with
|
||||
high trust, and to quickly get started. For long-term production usage, you may want to use the advanced installation
|
||||
method to benefit from more configuration options.
|
||||
If you do not know which one to choose, we recommend starting with Helm.
|
||||
|
||||
#### One-liner installation
|
||||
#### Install the agent with Helm
|
||||
|
||||
The one-liner installation is the simplest process, but you need
|
||||
Docker installed locally. If you don't have it, you can either install
|
||||
it or opt to the [advanced installation method](#advanced-installation).
|
||||
|
||||
Use the one-liner process for simple use cases or to get started with the agent for Kubernetes.
|
||||
For production use, opt for the [advanced installation method](#advanced-installation)
|
||||
as it gives you more customization options and access to all settings.
|
||||
|
||||
To install the agent on your cluster using the one-liner installation:
|
||||
To install the agent on your cluster using Helm:
|
||||
|
||||
1. [Install Helm](https://helm.sh/docs/intro/install/)
|
||||
1. In your computer, open a terminal and [connect to your cluster](https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/).
|
||||
1. Run the command you copied when registering your cluster in the previous step.
|
||||
1. Run the command you copied when registering your agent with GitLab.
|
||||
|
||||
Optionally, you can [customize the one-liner installation command](#customize-the-one-liner-installation).
|
||||
Optionally, you can [customize the Helm installation](#customize-the-helm-installation).
|
||||
|
||||
##### Customize the one-liner installation
|
||||
##### Customize the Helm installation
|
||||
|
||||
By default, the one-liner command generated by GitLab:
|
||||
By default, the Helm installation command generated by GitLab:
|
||||
|
||||
- Creates a namespace for the deployment (`gitlab-agent`).
|
||||
- Sets up a service account with `cluster-admin` rights (see [how to restrict this service account](#customize-the-permissions-for-the-agentk-service-account)).
|
||||
- Creates a `Secret` resource for the agent's access token.
|
||||
- Creates a namespace `gitlab-agent` for the deployment (`--namespace gitlab-agent`). You can skip creating the namespace by omitting the `--create-namespace` flag.
|
||||
- Sets up a service account for the agent with `cluster-admin` rights. You can:
|
||||
- Skip creating the service account by adding `--set serviceAccount.create=false` to the `helm install` command. In this case, you must set `serviceAccount.name` to a pre-existing service account.
|
||||
- Skip creating the RBAC permissions by adding `--set rbac.create=false` to the `helm install` command. In this case, you must bring your own RBAC permissions for the agent. Otherwise, it has no permissions at all.
|
||||
- Creates a `Secret` resource for the agent's access token. To instead bring your own secret with a token, omit the token (`--set token=...`) and instead use `--set config.secretName=<your secret name>`.
|
||||
- Creates a `Deployment` resource for the `agentk` pod.
|
||||
|
||||
You can edit these parameters to customize the one-liner installation command.
|
||||
To view all available options, open a terminal and run this command:
|
||||
To see the full list of customizations available, see the Helm chart's [default values file](https://gitlab.com/gitlab-org/charts/gitlab-agent/-/blob/main/values.yaml).
|
||||
|
||||
```shell
|
||||
docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --help
|
||||
#### Advanced installation method
|
||||
|
||||
Usage:
|
||||
cli generate [flags]
|
||||
|
||||
Flags:
|
||||
--agent-token string Access token registered for agent
|
||||
--agent-version string Version of the agentk image to use (default "v14.8.1")
|
||||
-h, --help help for generate
|
||||
--kas-address string GitLab agent server for Kubernetes address
|
||||
--name-prefix string The prefix to use for names of Kubernetes objects
|
||||
--namespace string Kubernetes namespace to create resources in (default "gitlab-agent")
|
||||
--no-rbac Do not include corresponding Roles and RoleBindings for the agent service account
|
||||
```
|
||||
|
||||
WARNING:
|
||||
Use `--agent-version stable` to refer to the latest stable
|
||||
release at the time when the command runs. For production, however,
|
||||
you should explicitly specify a matching version.
|
||||
|
||||
#### Advanced installation
|
||||
|
||||
For advanced installation options, use [the `kpt` installation method](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent).
|
||||
|
||||
##### Customize the permissions for the `agentk` service account
|
||||
|
||||
You own your cluster and can grant GitLab the permissions you want.
|
||||
By default, however, the generated manifests provide `cluster-admin` rights to the agent.
|
||||
|
||||
You can restrict the agent's access rights by using Kustomize overlays. [An example is commented out](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/build/deployment/gitlab-agent/cluster/kustomization.yaml) in the `kpt` package you retrieved as part of the installation.
|
||||
|
||||
To restrict permissions:
|
||||
|
||||
1. Copy the `cluster` directory.
|
||||
1. Edit the `kustomization.yaml` and `components/*` files based on your requirements.
|
||||
1. Run `kustomize build <your copied directory> | kubectl apply -f -` to apply your configuration.
|
||||
|
||||
#### Update the advanced installation base layer
|
||||
|
||||
Now you can update from the upstream package by using `kpt pkg update gitlab-agent --strategy resource-merge`.
|
||||
When the advanced installation setup changes, you will not need to change your custom overlays.
|
||||
GitLab also provides a [KPT package for the agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent). This method provides greater flexibility, but is only recommended for advanced users.
|
||||
|
||||
## Install multiple agents in your cluster
|
||||
|
||||
For total separation between teams, you might need to run multiple `agentk` instances in your cluster.
|
||||
You might want multiple agents so you can restrict RBAC for every `agentk` deployment.
|
||||
To install a second agent in your cluster, you can follow the [previous steps](#register-the-agent-with-gitlab) a second time. To avoid resource name collisions within the cluster, you must either:
|
||||
|
||||
To install multiple agents, follow the
|
||||
[advanced installation steps](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent)
|
||||
a second time and:
|
||||
- Use a different release name for the agent, e.g. `second-gitlab-agent`:
|
||||
|
||||
1. Change the agent name and create a new configuration file.
|
||||
1. Register the new agent. You receive a new access token. Each token should be used only with one agent.
|
||||
1. Change the namespace or prefix you use for the installation.
|
||||
```shell
|
||||
helm upgrade --install second-gitlab-agent gitlab/gitlab-agent ...
|
||||
```
|
||||
|
||||
You should also change the RBAC for the installed `agentk`.
|
||||
- Or, install the agent in a different namespace, e.g. `different-namespace`:
|
||||
|
||||
```shell
|
||||
helm upgrade --install gitlab-agent gitlab/gitlab-agent \
|
||||
--namespace different-namespace \
|
||||
...
|
||||
```
|
||||
|
||||
## Example projects
|
||||
|
||||
|
@ -195,50 +148,37 @@ The following example projects can help you get started with the agent.
|
|||
- [Auto DevOps setup that uses the CI/CD workflow](https://gitlab.com/gitlab-examples/ops/gitops-demo/hello-world-service)
|
||||
- [Cluster management project template example that uses the CI/CD workflow](https://gitlab.com/gitlab-examples/ops/gitops-demo/cluster-management)
|
||||
|
||||
## Upgrades and version compatibility
|
||||
|
||||
The agent has two major components: `agentk` and `kas`.
|
||||
GitLab provides `kas` installers built into the various GitLab installation methods.
|
||||
The required `kas` version corresponds to the GitLab `major.minor` (X.Y) versions.
|
||||
|
||||
At the same time, `agentk` and `kas` can differ by 1 minor version in either direction. For example,
|
||||
`agentk` 14.4 supports `kas` 14.3, 14.4, and 14.5 (regardless of the patch).
|
||||
|
||||
A feature introduced in a given GitLab minor version might work with other `agentk` or `kas` versions.
|
||||
To ensure it works, use at least the same `agentk` and `kas` minor version. For example,
|
||||
if your GitLab version is 14.2, use at least `agentk` 14.2 and `kas` 14.2.
|
||||
|
||||
We recommend upgrading your `kas` installations together with GitLab instances' upgrades, and to
|
||||
[upgrade the `agentk` installations](#update-the-agent-version) after upgrading GitLab.
|
||||
|
||||
The available `agentk` and `kas` versions are available in
|
||||
[the Container Registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/).
|
||||
|
||||
### Update the agent version
|
||||
## Updates and version compatibility
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340882) in GitLab 14.8, GitLab warns you on the agent's list page to update the agent version installed on your cluster.
|
||||
|
||||
To update the agent's version, re-run the [installation command](#install-the-agent-in-the-cluster)
|
||||
with a newer `--agent-version`. Make sure to specify the other required parameters: `--kas-address`, `--namespace`, and `--agent-token`.
|
||||
The available `agentk` versions are in [the Container Registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/1223205?sort=desc).
|
||||
For the best experience, the version of the agent installed in your cluster should match the GitLab major and minor version. The previous minor version is also supported. For example, if your GitLab version is v14.9.4 (major version 14, minor version 9), then versions v14.9.0 and v14.9.1 of the agent are ideal, but any v14.8.x version of the agent is also supported. See [this page](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/releases) of releases of the GitLab agent.
|
||||
|
||||
If you don't have access to your agent's access token, you can retrieve it from your cluster:
|
||||
### Update the agent version
|
||||
|
||||
1. Open a terminal and connect to your cluster.
|
||||
1. To retrieve the namespace, run:
|
||||
To update the agent to the latest version, you can run:
|
||||
|
||||
```shell
|
||||
kubectl get namespaces
|
||||
```
|
||||
```shell
|
||||
helm repo update
|
||||
helm upgrade --install gitlab-agent gitlab/gitlab-agent \
|
||||
--namespace gitlab-agent \
|
||||
--reuse-values
|
||||
```
|
||||
|
||||
1. To retrieve the secret, run:
|
||||
To set a specific version, you can override the `image.tag` value. For example, to install version `v14.9.1`, run:
|
||||
|
||||
```shell
|
||||
kubectl -n <namespace> get secrets
|
||||
```
|
||||
```shell
|
||||
helm upgrade gitlab-agent gitlab/gitlab-agent \
|
||||
--namespace gitlab-agent \
|
||||
--reuse-values \
|
||||
--set image.tag=v14.9.1
|
||||
```
|
||||
|
||||
1. To retrieve the access token, run:
|
||||
## Uninstall the agent
|
||||
|
||||
```shell
|
||||
kubectl -n <namespace> get secret <secret-name> --template={{.data.token}} | base64 --decode
|
||||
```
|
||||
If you [installed the agent with Helm](#install-the-agent-with-helm), then you can also uninstall with Helm. For example, if the release and namespace are both called `gitlab-agent`, then you can uninstall the agent using the following command:
|
||||
|
||||
```shell
|
||||
helm uninstall gitlab-agent \
|
||||
--namespace gitlab-agent
|
||||
```
|
||||
|
|
|
@ -96,6 +96,14 @@ You can authenticate using:
|
|||
Users accessing the Dependency Proxy with a personal access token or username and password must
|
||||
have at least the Guest role for the group they pull images from.
|
||||
|
||||
The Dependency Proxy follows the [Docker v2 token authentication flow](https://docs.docker.com/registry/spec/auth/token/),
|
||||
issuing the client a JWT to use for the pull requests. The JWT issued as a result of authenticating
|
||||
expires after some time. When the token expires, most Docker clients store your credentials and
|
||||
automatically request a new token without further action.
|
||||
|
||||
The token expiration time is a [configurable setting](../../../administration/packages/dependency_proxy.md#changing-the-jwt-expiration).
|
||||
On GitLab.com, the expiration time is 15 minutes.
|
||||
|
||||
#### SAML SSO
|
||||
|
||||
When [SSO enforcement](../../group/saml_sso/index.md#sso-enforcement)
|
||||
|
|
|
@ -16,6 +16,10 @@ class <%= migration_class_name %> < Gitlab::Database::Migration[<%= Gitlab::Data
|
|||
# To disable transactions uncomment the following line and remove these
|
||||
# comments:
|
||||
# disable_ddl_transaction!
|
||||
#
|
||||
# Configure the `gitlab_schema` to perform data manipulation (DML).
|
||||
# Visit: https://docs.gitlab.com/ee/development/database/migrations_for_multiple_databases.html
|
||||
# restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
<%- if migration_action == 'add' -%>
|
||||
def change
|
||||
|
|
|
@ -16,6 +16,10 @@ class <%= migration_class_name %> < Gitlab::Database::Migration[<%= Gitlab::Data
|
|||
# To disable transactions uncomment the following line and remove these
|
||||
# comments:
|
||||
# disable_ddl_transaction!
|
||||
#
|
||||
# Configure the `gitlab_schema` to perform data manipulation (DML).
|
||||
# Visit: https://docs.gitlab.com/ee/development/database/migrations_for_multiple_databases.html
|
||||
# restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
end
|
||||
|
|
|
@ -68,7 +68,15 @@ module HamlLint
|
|||
# Sometimes links are provided via data attributes in html tag
|
||||
return node.parsed_attributes.syntax_tree if node.type == :tag
|
||||
|
||||
node.parsed_script.syntax_tree
|
||||
parse_script(node).syntax_tree
|
||||
end
|
||||
|
||||
def parse_script(node)
|
||||
# It's a workaround for cases for scripts ending with "do"
|
||||
# For some reason they don't parse correctly
|
||||
code = node.script.delete_suffix(' do')
|
||||
|
||||
HamlLint::ParsedRuby.new(HamlLint::RubyParser.new.parse(code))
|
||||
end
|
||||
|
||||
def detect_path_to_file(link)
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
module API
|
||||
class GroupExport < ::API::Base
|
||||
before do
|
||||
not_found! unless Feature.enabled?(:group_import_export, user_group, default_enabled: true)
|
||||
|
||||
authorize! :admin_group, user_group
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ module Gitlab
|
|||
# Base GitLab CI Configuration facade
|
||||
#
|
||||
class Config
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
ConfigError = Class.new(StandardError)
|
||||
TIMEOUT_SECONDS = 30.seconds
|
||||
TIMEOUT_MESSAGE = 'Resolving config took longer than expected'
|
||||
|
@ -22,6 +24,11 @@ module Gitlab
|
|||
def initialize(config, project: nil, pipeline: nil, sha: nil, user: nil, parent_pipeline: nil, source: nil, logger: nil)
|
||||
@logger = logger || ::Gitlab::Ci::Pipeline::Logger.new(project: project)
|
||||
@source_ref_path = pipeline&.source_ref_path
|
||||
@project = project
|
||||
|
||||
if use_config_variables?
|
||||
pipeline ||= ::Ci::Pipeline.new(project: project, sha: sha, user: user, source: source)
|
||||
end
|
||||
|
||||
@context = self.logger.instrument(:config_build_context) do
|
||||
build_context(project: project, pipeline: pipeline, sha: sha, user: user, parent_pipeline: parent_pipeline)
|
||||
|
@ -155,6 +162,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def build_variables_without_instrumentation(project:, pipeline:)
|
||||
if use_config_variables?
|
||||
return pipeline.variables_builder.config_variables
|
||||
end
|
||||
|
||||
Gitlab::Ci::Variables::Collection.new.tap do |variables|
|
||||
break variables unless project
|
||||
|
||||
|
@ -184,6 +195,12 @@ module Gitlab
|
|||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, @context.sentry_payload)
|
||||
end
|
||||
|
||||
def use_config_variables?
|
||||
strong_memoize(:use_config_variables) do
|
||||
::Feature.enabled?(:ci_variables_builder_config_variables, @project, default_enabled: :yaml)
|
||||
end
|
||||
end
|
||||
|
||||
# Overridden in EE
|
||||
def rescue_errors
|
||||
RESCUE_ERRORS
|
||||
|
|
|
@ -10,7 +10,7 @@ module Gitlab
|
|||
@pipeline = pipeline
|
||||
@instance_variables_builder = Builder::Instance.new
|
||||
@project_variables_builder = Builder::Project.new(project)
|
||||
@group_variables_builder = Builder::Group.new(project.group)
|
||||
@group_variables_builder = Builder::Group.new(project&.group)
|
||||
end
|
||||
|
||||
def scoped_variables(job, environment:, dependencies:)
|
||||
|
@ -32,6 +32,20 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def config_variables
|
||||
Gitlab::Ci::Variables::Collection.new.tap do |variables|
|
||||
break variables unless project
|
||||
|
||||
variables.concat(project.predefined_variables)
|
||||
variables.concat(pipeline.predefined_variables)
|
||||
variables.concat(secret_instance_variables)
|
||||
variables.concat(secret_group_variables(environment: nil))
|
||||
variables.concat(secret_project_variables(environment: nil))
|
||||
variables.concat(pipeline.variables)
|
||||
variables.concat(pipeline_schedule_variables)
|
||||
end
|
||||
end
|
||||
|
||||
def kubernetes_variables(environment:, job:)
|
||||
::Gitlab::Ci::Variables::Collection.new.tap do |collection|
|
||||
# NOTE: deployment_variables will be removed as part of cleanup for
|
||||
|
|
|
@ -41,6 +41,12 @@ module Gitlab
|
|||
|
||||
class V2_0 < V1_0 # rubocop:disable Naming/ClassAndModuleCamelCase
|
||||
include Gitlab::Database::MigrationHelpers::RestrictGitlabSchema
|
||||
|
||||
# When running migrations, the `db:migrate` switches connection of
|
||||
# ActiveRecord::Base depending where the migration runs.
|
||||
# This helper class is provided to avoid confusion using `ActiveRecord::Base`
|
||||
class MigrationRecord < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def self.[](version)
|
||||
|
@ -53,7 +59,7 @@ module Gitlab
|
|||
|
||||
# The current version to be used in new migrations
|
||||
def self.current_version
|
||||
1.0
|
||||
2.0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -69,8 +69,10 @@ module Gitlab
|
|||
schemas = self.dml_schemas(tables)
|
||||
|
||||
if (schemas - self.allowed_gitlab_schemas).any?
|
||||
raise DMLAccessDeniedError, "Select/DML queries (SELECT/UPDATE/DELETE) do access '#{tables}' (#{schemas.to_a}) " \
|
||||
"which is outside of list of allowed schemas: '#{self.allowed_gitlab_schemas}'."
|
||||
raise DMLAccessDeniedError, \
|
||||
"Select/DML queries (SELECT/UPDATE/DELETE) do access '#{tables}' (#{schemas.to_a}) " \
|
||||
"which is outside of list of allowed schemas: '#{self.allowed_gitlab_schemas}'. " \
|
||||
"#{documentation_url}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -93,11 +95,19 @@ module Gitlab
|
|||
end
|
||||
|
||||
def raise_dml_not_allowed_error(message)
|
||||
raise DMLNotAllowedError, "Select/DML queries (SELECT/UPDATE/DELETE) are disallowed in the DDL (structure) mode. #{message}"
|
||||
raise DMLNotAllowedError, \
|
||||
"Select/DML queries (SELECT/UPDATE/DELETE) are disallowed in the DDL (structure) mode. " \
|
||||
"#{message}. #{documentation_url}" \
|
||||
end
|
||||
|
||||
def raise_ddl_not_allowed_error(message)
|
||||
raise DDLNotAllowedError, "DDL queries (structure) are disallowed in the Select/DML (SELECT/UPDATE/DELETE) mode. #{message}"
|
||||
raise DDLNotAllowedError, \
|
||||
"DDL queries (structure) are disallowed in the Select/DML (SELECT/UPDATE/DELETE) mode. " \
|
||||
"#{message}. #{documentation_url}"
|
||||
end
|
||||
|
||||
def documentation_url
|
||||
"For more information visit: https://docs.gitlab.com/ee/development/database/migrations_for_multiple_databases.html"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,21 @@ module Gitlab
|
|||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, snowplow_category: category, snowplow_action: action)
|
||||
end
|
||||
|
||||
def definition(basename, category: nil, action: nil, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil, **extra) # rubocop:disable Metrics/ParameterLists
|
||||
definition = YAML.load_file(Rails.root.join("config/events/#{basename}.yml"))
|
||||
|
||||
dispatch_from_definition(definition, label: label, property: property, value: value, context: context, project: project, user: user, namespace: namespace, **extra)
|
||||
end
|
||||
|
||||
def dispatch_from_definition(definition, **event_data)
|
||||
definition = definition.with_indifferent_access
|
||||
|
||||
category ||= definition[:category]
|
||||
action ||= definition[:action]
|
||||
|
||||
event(category, action, **event_data)
|
||||
end
|
||||
|
||||
def options(group)
|
||||
snowplow.options(group)
|
||||
end
|
||||
|
@ -39,3 +54,5 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Tracking.prepend_mod_with('Gitlab::Tracking')
|
||||
|
|
|
@ -11,15 +11,19 @@ module Gitlab
|
|||
include Gitlab::Routing
|
||||
include Gitlab::Allowable
|
||||
|
||||
attr_reader :subject
|
||||
# Presenters should always access the subject through an explicit getter defined with
|
||||
# `presents ..., as:`, the `__subject__` method is only intended for internal use.
|
||||
def __subject__
|
||||
@subject
|
||||
end
|
||||
|
||||
def can?(user, action, overridden_subject = nil)
|
||||
super(user, action, overridden_subject || subject)
|
||||
super(user, action, overridden_subject || __subject__)
|
||||
end
|
||||
|
||||
# delegate all #can? queries to the subject
|
||||
def declarative_policy_delegate
|
||||
subject
|
||||
__subject__
|
||||
end
|
||||
|
||||
def present(**attributes)
|
||||
|
@ -31,15 +35,15 @@ module Gitlab
|
|||
end
|
||||
|
||||
def is_a?(type)
|
||||
super || subject.is_a?(type)
|
||||
super || __subject__.is_a?(type)
|
||||
end
|
||||
|
||||
def web_url
|
||||
url_builder.build(subject)
|
||||
url_builder.build(__subject__)
|
||||
end
|
||||
|
||||
def web_path
|
||||
url_builder.build(subject, only_path: true)
|
||||
url_builder.build(__subject__, only_path: true)
|
||||
end
|
||||
|
||||
class_methods do
|
||||
|
@ -58,7 +62,7 @@ module Gitlab
|
|||
# no-op
|
||||
end
|
||||
|
||||
define_method(as) { subject } if as
|
||||
define_method(as) { __subject__ } if as
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7038,6 +7038,9 @@ msgstr ""
|
|||
msgid "Changed assignee(s)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Changed merge method to %{merge_method}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Changed reviewer(s)."
|
||||
msgstr ""
|
||||
|
||||
|
@ -8001,7 +8004,7 @@ msgstr ""
|
|||
msgid "ClusterAgents|Failed to register an agent"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included."
|
||||
msgid "ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included in the command."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterAgents|GitLab agent"
|
||||
|
@ -8019,6 +8022,9 @@ msgstr ""
|
|||
msgid "ClusterAgents|How to update an agent?"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterAgents|Install using Helm (recommended)"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterAgents|Last connected %{timeAgo}."
|
||||
msgstr ""
|
||||
|
||||
|
@ -8052,9 +8058,6 @@ msgstr ""
|
|||
msgid "ClusterAgents|Recommended"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterAgents|Recommended installation method"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterAgents|Register"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@
|
|||
"@babel/preset-env": "^7.10.1",
|
||||
"@gitlab/at.js": "1.5.7",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "2.6.0",
|
||||
"@gitlab/ui": "38.0.1",
|
||||
"@gitlab/svgs": "2.8.0",
|
||||
"@gitlab/ui": "38.8.1",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "6.1.4-7",
|
||||
"@rails/ujs": "6.1.4-7",
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue