Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
9ea23bb2f6
commit
38ec668b55
|
@ -206,7 +206,7 @@ workflow:
|
||||||
GLCI_PUSH_RAILS_TEST_FAILURE_ISSUES_TO_GCS: "false"
|
GLCI_PUSH_RAILS_TEST_FAILURE_ISSUES_TO_GCS: "false"
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
PG_VERSION: "14"
|
PG_VERSION: "16"
|
||||||
DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/ci/${BUILD_OS}-${OS_VERSION}-slim-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-node-${NODE_VERSION}-postgresql-${PG_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-yarn-${YARN_VERSION}-graphicsmagick-${GRAPHICSMAGICK_VERSION}"
|
DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/ci/${BUILD_OS}-${OS_VERSION}-slim-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-node-${NODE_VERSION}-postgresql-${PG_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-yarn-${YARN_VERSION}-graphicsmagick-${GRAPHICSMAGICK_VERSION}"
|
||||||
DEFAULT_JOB_TAG: "gitlab-org"
|
DEFAULT_JOB_TAG: "gitlab-org"
|
||||||
GITLAB_LARGE_RUNNER_OPTIONAL: "gitlab-org" # overridden just in gitlab-org/gitlab
|
GITLAB_LARGE_RUNNER_OPTIONAL: "gitlab-org" # overridden just in gitlab-org/gitlab
|
||||||
|
|
|
@ -1279,12 +1279,9 @@ RSpec/FactoryBot/LocalStaticAssignment:
|
||||||
Rails/TransactionExitStatement:
|
Rails/TransactionExitStatement:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
Search/AvoidCheckingFinishedOnDeprecatedMigrations:
|
Search/AvoidCheckingFinishedOnInvalidMigrations:
|
||||||
Include:
|
Include:
|
||||||
- 'ee/app/models/**/*.rb'
|
- 'ee/**/*.rb'
|
||||||
- 'ee/lib/elastic/**/*.rb'
|
|
||||||
- 'ee/lib/gitlab/elastic/**/*.rb'
|
|
||||||
- 'ee/spec/support/helpers/elasticsearch_helpers.rb'
|
|
||||||
|
|
||||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/407233
|
# See https://gitlab.com/gitlab-org/gitlab/-/issues/407233
|
||||||
Cop/ExperimentsTestCoverage:
|
Cop/ExperimentsTestCoverage:
|
||||||
|
|
|
@ -32,7 +32,6 @@ InternalAffairs/ExampleHeredocDelimiter:
|
||||||
- 'spec/rubocop/cop/scalability/cron_worker_context_spec.rb'
|
- 'spec/rubocop/cop/scalability/cron_worker_context_spec.rb'
|
||||||
- 'spec/rubocop/cop/scalability/file_uploads_spec.rb'
|
- 'spec/rubocop/cop/scalability/file_uploads_spec.rb'
|
||||||
- 'spec/rubocop/cop/scalability/idempotent_worker_spec.rb'
|
- 'spec/rubocop/cop/scalability/idempotent_worker_spec.rb'
|
||||||
- 'spec/rubocop/cop/search/avoid_checking_finished_on_deprecated_migrations_spec.rb'
|
|
||||||
- 'spec/rubocop/cop/search/namespaced_class_spec.rb'
|
- 'spec/rubocop/cop/search/namespaced_class_spec.rb'
|
||||||
- 'spec/rubocop/cop/sidekiq_api_usage_spec.rb'
|
- 'spec/rubocop/cop/sidekiq_api_usage_spec.rb'
|
||||||
- 'spec/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_spec.rb'
|
- 'spec/rubocop/cop/sidekiq_load_balancing/worker_data_consistency_spec.rb'
|
||||||
|
|
|
@ -60,7 +60,6 @@ InternalAffairs/NodeMatcherDirective:
|
||||||
- 'rubocop/cop/scalability/cron_worker_context.rb'
|
- 'rubocop/cop/scalability/cron_worker_context.rb'
|
||||||
- 'rubocop/cop/scalability/file_uploads.rb'
|
- 'rubocop/cop/scalability/file_uploads.rb'
|
||||||
- 'rubocop/cop/scalability/idempotent_worker.rb'
|
- 'rubocop/cop/scalability/idempotent_worker.rb'
|
||||||
- 'rubocop/cop/search/avoid_checking_finished_on_deprecated_migrations.rb'
|
|
||||||
- 'rubocop/cop/sidekiq_api_usage.rb'
|
- 'rubocop/cop/sidekiq_api_usage.rb'
|
||||||
- 'rubocop/cop/sidekiq_load_balancing/worker_data_consistency.rb'
|
- 'rubocop/cop/sidekiq_load_balancing/worker_data_consistency.rb'
|
||||||
- 'rubocop/cop/sidekiq_options_queue.rb'
|
- 'rubocop/cop/sidekiq_options_queue.rb'
|
||||||
|
|
|
@ -117,7 +117,6 @@ InternalAffairs/OnSendWithoutOnCSend:
|
||||||
- 'rubocop/cop/scalability/bulk_perform_with_context.rb'
|
- 'rubocop/cop/scalability/bulk_perform_with_context.rb'
|
||||||
- 'rubocop/cop/scalability/cron_worker_context.rb'
|
- 'rubocop/cop/scalability/cron_worker_context.rb'
|
||||||
- 'rubocop/cop/scalability/file_uploads.rb'
|
- 'rubocop/cop/scalability/file_uploads.rb'
|
||||||
- 'rubocop/cop/search/avoid_checking_finished_on_deprecated_migrations.rb'
|
|
||||||
- 'rubocop/cop/sidekiq_api_usage.rb'
|
- 'rubocop/cop/sidekiq_api_usage.rb'
|
||||||
- 'rubocop/cop/sidekiq_options_queue.rb'
|
- 'rubocop/cop/sidekiq_options_queue.rb'
|
||||||
- 'rubocop/cop/sidekiq_redis_call.rb'
|
- 'rubocop/cop/sidekiq_redis_call.rb'
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
838089751c1ffa6700b328f3060ce869217393fe
|
e30c5e007ce5c67d4dbbdfdf5e95634d0cc09344
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 312 B |
Binary file not shown.
After Width: | Height: | Size: 437 B |
Binary file not shown.
After Width: | Height: | Size: 259 B |
Binary file not shown.
After Width: | Height: | Size: 612 B |
Binary file not shown.
After Width: | Height: | Size: 375 B |
|
@ -109,6 +109,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
isWidget: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -300,7 +305,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="gl-mt-5">
|
<div class="gl-mt-5">
|
||||||
<p data-testid="runner-token-message">
|
<p v-if="!isWidget" data-testid="runner-token-message">
|
||||||
<gl-icon name="information-o" variant="info" />
|
<gl-icon name="information-o" variant="info" />
|
||||||
<gl-sprintf :message="tokenMessage">
|
<gl-sprintf :message="tokenMessage">
|
||||||
<template #token>
|
<template #token>
|
||||||
|
@ -326,11 +331,12 @@ export default {
|
||||||
</gl-sprintf>
|
</gl-sprintf>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr v-if="!isWidget" />
|
||||||
|
|
||||||
<!-- start: before you begin -->
|
<!-- start: before you begin -->
|
||||||
<div>
|
<div>
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.beforeHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.beforeHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.beforeHeading }}</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<gl-sprintf :message="$options.i18n.permissionsText">
|
<gl-sprintf :message="$options.i18n.permissionsText">
|
||||||
|
@ -374,7 +380,8 @@ export default {
|
||||||
<!-- end: before you begin -->
|
<!-- end: before you begin -->
|
||||||
|
|
||||||
<!-- start: step one -->
|
<!-- start: step one -->
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.stepOneHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.stepOneHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.stepOneHeading }}</h2>
|
||||||
<p>{{ $options.i18n.stepOneDescription }}</p>
|
<p>{{ $options.i18n.stepOneDescription }}</p>
|
||||||
|
|
||||||
<google-cloud-field-group
|
<google-cloud-field-group
|
||||||
|
@ -504,7 +511,8 @@ export default {
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.stepOneNodePoolHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.stepOneNodePoolHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.stepOneNodePoolHeading }}</h2>
|
||||||
<p>{{ $options.i18n.stepOneNodePoolDescription }}</p>
|
<p>{{ $options.i18n.stepOneNodePoolDescription }}</p>
|
||||||
|
|
||||||
<template v-for="(nodePool, index) in nodePools">
|
<template v-for="(nodePool, index) in nodePools">
|
||||||
|
@ -527,7 +535,8 @@ export default {
|
||||||
<!-- end: step 1.2 -->
|
<!-- end: step 1.2 -->
|
||||||
|
|
||||||
<!-- start: step two -->
|
<!-- start: step two -->
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.stepTwoHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.stepTwoHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.stepTwoHeading }}</h2>
|
||||||
<p>{{ $options.i18n.stepTwoDescription }}</p>
|
<p>{{ $options.i18n.stepTwoDescription }}</p>
|
||||||
<gl-alert
|
<gl-alert
|
||||||
v-if="showAlert"
|
v-if="showAlert"
|
||||||
|
@ -559,6 +568,6 @@ export default {
|
||||||
:apply-terraform-script="applyTerraformScript"
|
:apply-terraform-script="applyTerraformScript"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<hr />
|
<hr v-if="!isWidget" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -101,6 +101,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
isWidget: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -245,7 +250,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="gl-mt-5">
|
<div class="gl-mt-5">
|
||||||
<p>
|
<p v-if="!isWidget" data-testid="runner-token-message">
|
||||||
<gl-icon name="information-o" variant="info" />
|
<gl-icon name="information-o" variant="info" />
|
||||||
<gl-sprintf :message="tokenMessage">
|
<gl-sprintf :message="tokenMessage">
|
||||||
<template #token>
|
<template #token>
|
||||||
|
@ -271,11 +276,12 @@ export default {
|
||||||
</gl-sprintf>
|
</gl-sprintf>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr v-if="!isWidget" />
|
||||||
|
|
||||||
<!-- start: before you begin -->
|
<!-- start: before you begin -->
|
||||||
<div>
|
<div>
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.beforeHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.beforeHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.beforeHeading }}</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<gl-sprintf :message="$options.i18n.permissionsText">
|
<gl-sprintf :message="$options.i18n.permissionsText">
|
||||||
|
@ -319,7 +325,8 @@ export default {
|
||||||
<!-- end: before you begin -->
|
<!-- end: before you begin -->
|
||||||
|
|
||||||
<!-- start: step one -->
|
<!-- start: step one -->
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.stepOneHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.stepOneHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.stepOneHeading }}</h2>
|
||||||
<p>{{ $options.i18n.stepOneDescription }}</p>
|
<p>{{ $options.i18n.stepOneDescription }}</p>
|
||||||
|
|
||||||
<google-cloud-field-group
|
<google-cloud-field-group
|
||||||
|
@ -501,7 +508,8 @@ export default {
|
||||||
<!-- end: step one -->
|
<!-- end: step one -->
|
||||||
|
|
||||||
<!-- start: step two -->
|
<!-- start: step two -->
|
||||||
<h2 class="gl-heading-2">{{ $options.i18n.stepTwoHeading }}</h2>
|
<h3 v-if="isWidget" class="gl-heading-3">{{ $options.i18n.stepTwoHeading }}</h3>
|
||||||
|
<h2 v-else class="gl-heading-2">{{ $options.i18n.stepTwoHeading }}</h2>
|
||||||
<p>{{ $options.i18n.stepTwoDescription }}</p>
|
<p>{{ $options.i18n.stepTwoDescription }}</p>
|
||||||
<gl-alert
|
<gl-alert
|
||||||
v-if="showAlert"
|
v-if="showAlert"
|
||||||
|
@ -533,6 +541,6 @@ export default {
|
||||||
:apply-terraform-script="applyTerraformScript"
|
:apply-terraform-script="applyTerraformScript"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<hr />
|
<hr v-if="!isWidget" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
<script>
|
||||||
|
import { GlIcon, GlLink, GlSprintf, GlBadge } from '@gitlab/ui';
|
||||||
|
import CrudComponent from '~/vue_shared/components/crud_component.vue';
|
||||||
|
import { EXECUTORS_HELP_URL, SERVICE_COMMANDS_HELP_URL } from '../../constants';
|
||||||
|
import PlatformsDrawer from './platforms_drawer.vue';
|
||||||
|
import CliCommand from './cli_command.vue';
|
||||||
|
import { commandPrompt, registerCommand, runCommand } from './utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'OperatingSystemRegistrationInstructions',
|
||||||
|
components: {
|
||||||
|
GlIcon,
|
||||||
|
GlLink,
|
||||||
|
GlSprintf,
|
||||||
|
GlBadge,
|
||||||
|
CrudComponent,
|
||||||
|
CliCommand,
|
||||||
|
PlatformsDrawer,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
token: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
platform: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isDrawerOpen: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
commandPrompt() {
|
||||||
|
return commandPrompt({ platform: this.platform });
|
||||||
|
},
|
||||||
|
registerCommand() {
|
||||||
|
return registerCommand({
|
||||||
|
platform: this.platform,
|
||||||
|
token: this.token,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
runCommand() {
|
||||||
|
return runCommand({ platform: this.platform });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onToggleDrawer(val = !this.isDrawerOpen) {
|
||||||
|
this.isDrawerOpen = val;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EXECUTORS_HELP_URL,
|
||||||
|
SERVICE_COMMANDS_HELP_URL,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<crud-component :is-collapsible="true" :collapsed="true">
|
||||||
|
<template #title>
|
||||||
|
{{ title }}
|
||||||
|
<gl-badge variant="neutral">{{ s__('Runners|Operating System') }}</gl-badge>
|
||||||
|
</template>
|
||||||
|
<p>
|
||||||
|
<gl-sprintf
|
||||||
|
:message="
|
||||||
|
s__(
|
||||||
|
'Runners|GitLab Runner must be installed before you can register a runner. %{linkStart}How do I install GitLab Runner?%{linkEnd}',
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #link="{ content }">
|
||||||
|
<gl-link data-testid="how-to-install-btn" @click="onToggleDrawer()">{{
|
||||||
|
content
|
||||||
|
}}</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<section class="gl-mt-6" data-testid="step-1">
|
||||||
|
<h3 class="gl-heading-3">{{ s__('Runners|Step 1') }}</h3>
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
s__(
|
||||||
|
'Runners|Copy and paste the following command into your command line to register the runner.',
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<cli-command :prompt="commandPrompt" :command="registerCommand" />
|
||||||
|
</section>
|
||||||
|
<section class="gl-mt-6" data-testid="step-2">
|
||||||
|
<h3 class="gl-heading-3">{{ s__('Runners|Step 2') }}</h3>
|
||||||
|
<p>
|
||||||
|
<gl-sprintf
|
||||||
|
:message="
|
||||||
|
s__(
|
||||||
|
'Runners|Choose an executor when prompted by the command line. Executors run builds in different environments. %{linkStart}Not sure which one to select?%{linkEnd}',
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #link="{ content }">
|
||||||
|
<gl-link
|
||||||
|
:href="$options.EXECUTORS_HELP_URL"
|
||||||
|
target="_blank"
|
||||||
|
data-testid="executors-help-link"
|
||||||
|
>
|
||||||
|
{{ content }} <gl-icon name="external-link" />
|
||||||
|
</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="gl-mt-6" data-testid="step-3">
|
||||||
|
<h3 class="gl-heading-3">{{ s__('Runners|Step 3 (optional)') }}</h3>
|
||||||
|
<p>{{ s__('Runners|Manually verify that the runner is available to pick up jobs.') }}</p>
|
||||||
|
<cli-command :prompt="commandPrompt" :command="runCommand" />
|
||||||
|
<p>
|
||||||
|
<gl-sprintf
|
||||||
|
:message="
|
||||||
|
s__(
|
||||||
|
'Runners|This may not be needed if you manage your runner as a %{linkStart}system or user service%{linkEnd}.',
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #link="{ content }">
|
||||||
|
<gl-link
|
||||||
|
:href="$options.SERVICE_COMMANDS_HELP_URL"
|
||||||
|
target="_blank"
|
||||||
|
data-testid="service-commands-help-link"
|
||||||
|
>
|
||||||
|
{{ content }} <gl-icon name="external-link" />
|
||||||
|
</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<platforms-drawer :platform="platform" :open="isDrawerOpen" @close="onToggleDrawer(false)" />
|
||||||
|
</crud-component>
|
||||||
|
</template>
|
|
@ -3,29 +3,43 @@ import {
|
||||||
GlFormGroup,
|
GlFormGroup,
|
||||||
GlFormInputGroup,
|
GlFormInputGroup,
|
||||||
GlButton,
|
GlButton,
|
||||||
|
GlBadge,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
GlAlert,
|
GlAlert,
|
||||||
|
GlLink,
|
||||||
|
GlIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import { createAlert } from '~/alert';
|
import { createAlert } from '~/alert';
|
||||||
import MultiStepFormTemplate from '~/vue_shared/components/multi_step_form_template.vue';
|
import MultiStepFormTemplate from '~/vue_shared/components/multi_step_form_template.vue';
|
||||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||||
|
import CrudComponent from '~/vue_shared/components/crud_component.vue';
|
||||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { TYPENAME_CI_RUNNER } from '~/graphql_shared/constants';
|
import { TYPENAME_CI_RUNNER } from '~/graphql_shared/constants';
|
||||||
import runnerForRegistrationQuery from '../graphql/register/runner_for_registration.query.graphql';
|
import runnerForRegistrationQuery from '../graphql/register/runner_for_registration.query.graphql';
|
||||||
import { I18N_FETCH_ERROR } from '../constants';
|
import { DOCKER_HELP_URL, KUBERNETES_HELP_URL, I18N_FETCH_ERROR } from '../constants';
|
||||||
import { captureException } from '../sentry_utils';
|
import { captureException } from '../sentry_utils';
|
||||||
|
import OperatingSystemInstruction from './registration/wizard_operating_system_instruction.vue';
|
||||||
|
import GoogleCloudRegistrationInstructions from './registration/google_cloud_registration_instructions.vue';
|
||||||
|
import GkeRegistrationInstructions from './registration/gke_registration_instructions.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GlFormGroup,
|
GlFormGroup,
|
||||||
GlFormInputGroup,
|
GlFormInputGroup,
|
||||||
GlButton,
|
GlButton,
|
||||||
|
GlBadge,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
GlAlert,
|
GlAlert,
|
||||||
|
GlLink,
|
||||||
|
GlIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
MultiStepFormTemplate,
|
MultiStepFormTemplate,
|
||||||
ClipboardButton,
|
ClipboardButton,
|
||||||
|
CrudComponent,
|
||||||
|
OperatingSystemInstruction,
|
||||||
|
GoogleCloudRegistrationInstructions,
|
||||||
|
GkeRegistrationInstructions,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
currentStep: {
|
currentStep: {
|
||||||
|
@ -81,6 +95,8 @@ export default {
|
||||||
return this.$apollo.queries.runner.loading;
|
return this.$apollo.queries.runner.loading;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DOCKER_HELP_URL,
|
||||||
|
KUBERNETES_HELP_URL,
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
@ -158,7 +174,96 @@ export default {
|
||||||
</gl-sprintf>
|
</gl-sprintf>
|
||||||
</gl-alert>
|
</gl-alert>
|
||||||
|
|
||||||
<!-- instructions will be added in https://gitlab.com/gitlab-org/gitlab/-/issues/396544 -->
|
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
|
||||||
|
<!-- Operating systems -->
|
||||||
|
<operating-system-instruction
|
||||||
|
platform="linux"
|
||||||
|
:token="token"
|
||||||
|
title="Linux"
|
||||||
|
class="gl-rounded-b-none"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<operating-system-instruction
|
||||||
|
platform="osx"
|
||||||
|
:token="token"
|
||||||
|
title="macOS"
|
||||||
|
class="!gl-mt-0 gl-rounded-none gl-border-t-0"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<operating-system-instruction
|
||||||
|
platform="windows"
|
||||||
|
:token="token"
|
||||||
|
title="Windows"
|
||||||
|
class="!gl-mt-0 gl-rounded-none gl-border-t-0"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Clouds -->
|
||||||
|
<crud-component
|
||||||
|
is-collapsible
|
||||||
|
:collapsed="true"
|
||||||
|
:is-empty="false"
|
||||||
|
class="!gl-mt-0 gl-rounded-none gl-border-t-0"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
Google Cloud
|
||||||
|
<gl-badge variant="neutral">{{ s__('Runners|Cloud') }}</gl-badge>
|
||||||
|
</template>
|
||||||
|
<google-cloud-registration-instructions :is-widget="true" />
|
||||||
|
</crud-component>
|
||||||
|
|
||||||
|
<crud-component
|
||||||
|
is-collapsible
|
||||||
|
:collapsed="true"
|
||||||
|
:is-empty="false"
|
||||||
|
class="!gl-mt-0 gl-rounded-none gl-border-t-0"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
GKE
|
||||||
|
<gl-badge variant="neutral">{{ s__('Runners|Cloud') }}</gl-badge>
|
||||||
|
</template>
|
||||||
|
<gke-registration-instructions :is-widget="true" />
|
||||||
|
</crud-component>
|
||||||
|
|
||||||
|
<!-- Containers -->
|
||||||
|
<crud-component
|
||||||
|
is-collapsible
|
||||||
|
:collapsed="true"
|
||||||
|
:is-empty="false"
|
||||||
|
class="!gl-mt-0 gl-rounded-none gl-border-t-0"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
Docker
|
||||||
|
<gl-badge variant="neutral">{{ s__('Runners|Container') }}</gl-badge>
|
||||||
|
</template>
|
||||||
|
<gl-sprintf :message="s__('Runners|View instructions in %{helpLink}.')">
|
||||||
|
<template #helpLink>
|
||||||
|
<gl-link :href="$options.DOCKER_HELP_URL" target="_blank">
|
||||||
|
{{ s__('Runners|documentation') }}
|
||||||
|
<gl-icon name="external-link" />
|
||||||
|
</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</crud-component>
|
||||||
|
|
||||||
|
<crud-component
|
||||||
|
is-collapsible
|
||||||
|
:collapsed="true"
|
||||||
|
:is-empty="false"
|
||||||
|
class="!gl-mt-0 gl-rounded-t-none gl-border-t-0"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
Kubernetes
|
||||||
|
<gl-badge variant="neutral">{{ s__('Runners|Container') }}</gl-badge>
|
||||||
|
</template>
|
||||||
|
<gl-sprintf :message="s__('Runners|View instructions in %{helpLink}.')">
|
||||||
|
<template #helpLink>
|
||||||
|
<gl-link :href="$options.KUBERNETES_HELP_URL" target="_blank">
|
||||||
|
{{ s__('Runners|documentation') }}
|
||||||
|
<gl-icon name="external-link" />
|
||||||
|
</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</crud-component>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="!loading" #next>
|
<template v-if="!loading" #next>
|
||||||
|
|
|
@ -263,26 +263,24 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
</groups-app>
|
</groups-app>
|
||||||
</gl-tab>
|
</gl-tab>
|
||||||
<template #tabs-end>
|
<template #toolbar-end>
|
||||||
<li class="gl-w-full">
|
<filtered-search-and-sort
|
||||||
<filtered-search-and-sort
|
class="gl-w-full gl-border-b-0"
|
||||||
class="gl-border-b-0"
|
:filtered-search-namespace="$options.filteredSearch.namespace"
|
||||||
:filtered-search-namespace="$options.filteredSearch.namespace"
|
:filtered-search-tokens="$options.filteredSearch.tokens"
|
||||||
:filtered-search-tokens="$options.filteredSearch.tokens"
|
:filtered-search-term-key="$options.filteredSearch.searchTermKey"
|
||||||
:filtered-search-term-key="$options.filteredSearch.searchTermKey"
|
:filtered-search-recent-searches-storage-key="
|
||||||
:filtered-search-recent-searches-storage-key="
|
$options.filteredSearch.recentSearchesStorageKey
|
||||||
$options.filteredSearch.recentSearchesStorageKey
|
"
|
||||||
"
|
:filtered-search-query="$route.query"
|
||||||
:filtered-search-query="$route.query"
|
:is-ascending="isAscending"
|
||||||
:is-ascending="isAscending"
|
:sort-options="activeTabSortOptions"
|
||||||
:sort-options="activeTabSortOptions"
|
:active-sort-option="activeSortOption"
|
||||||
:active-sort-option="activeSortOption"
|
:search-input-placeholder="$options.i18n.searchPlaceholder"
|
||||||
:search-input-placeholder="$options.i18n.searchPlaceholder"
|
@filter="onFilter"
|
||||||
@filter="onFilter"
|
@sort-direction-change="onSortDirectionChange"
|
||||||
@sort-direction-change="onSortDirectionChange"
|
@sort-by-change="onSortByChange"
|
||||||
@sort-by-change="onSortByChange"
|
/>
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</template>
|
</template>
|
||||||
</gl-tabs>
|
</gl-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -581,24 +581,22 @@ export default {
|
||||||
<template v-else>{{ tab.text }}</template>
|
<template v-else>{{ tab.text }}</template>
|
||||||
</gl-tab>
|
</gl-tab>
|
||||||
|
|
||||||
<template #tabs-end>
|
<template #toolbar-end>
|
||||||
<li class="gl-w-full">
|
<filtered-search-and-sort
|
||||||
<filtered-search-and-sort
|
class="gl-w-full gl-border-b-0"
|
||||||
class="gl-border-b-0"
|
:filtered-search-namespace="filteredSearchNamespace"
|
||||||
:filtered-search-namespace="filteredSearchNamespace"
|
:filtered-search-tokens="filteredSearchTokens"
|
||||||
:filtered-search-tokens="filteredSearchTokens"
|
:filtered-search-term-key="filteredSearchTermKey"
|
||||||
:filtered-search-term-key="filteredSearchTermKey"
|
:filtered-search-recent-searches-storage-key="filteredSearchRecentSearchesStorageKey"
|
||||||
:filtered-search-recent-searches-storage-key="filteredSearchRecentSearchesStorageKey"
|
:filtered-search-query="$route.query"
|
||||||
:filtered-search-query="$route.query"
|
:search-input-placeholder="filteredSearchInputPlaceholder"
|
||||||
:search-input-placeholder="filteredSearchInputPlaceholder"
|
:is-ascending="isAscending"
|
||||||
:is-ascending="isAscending"
|
:sort-options="sortOptions"
|
||||||
:sort-options="sortOptions"
|
:active-sort-option="activeSortOption"
|
||||||
:active-sort-option="activeSortOption"
|
@filter="onFilter"
|
||||||
@filter="onFilter"
|
@sort-direction-change="onSortDirectionChange"
|
||||||
@sort-direction-change="onSortDirectionChange"
|
@sort-by-change="onSortByChange"
|
||||||
@sort-by-change="onSortByChange"
|
/>
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</template>
|
</template>
|
||||||
</gl-tabs>
|
</gl-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -110,7 +110,7 @@ export default {
|
||||||
/>
|
/>
|
||||||
<members-app v-else :namespace="tab.namespace" :tab-query-param-value="tab.queryParamValue" />
|
<members-app v-else :namespace="tab.namespace" :tab-query-param-value="tab.queryParamValue" />
|
||||||
</gl-tab>
|
</gl-tab>
|
||||||
<template #tabs-end>
|
<template #toolbar-end>
|
||||||
<gl-button
|
<gl-button
|
||||||
v-if="shouldShowExportButton"
|
v-if="shouldShowExportButton"
|
||||||
data-event-tracking="click_export_group_members_as_csv"
|
data-event-tracking="click_export_group_members_as_csv"
|
||||||
|
|
|
@ -411,7 +411,7 @@ export default {
|
||||||
/>
|
/>
|
||||||
</gl-tab>
|
</gl-tab>
|
||||||
|
|
||||||
<template #tabs-end>
|
<template #toolbar-end>
|
||||||
<div class="gl-ml-auto gl-flex gl-gap-2">
|
<div class="gl-ml-auto gl-flex gl-gap-2">
|
||||||
<gl-button
|
<gl-button
|
||||||
v-gl-modal="$options.uploadCsvModalId"
|
v-gl-modal="$options.uploadCsvModalId"
|
||||||
|
|
|
@ -259,6 +259,7 @@ export default {
|
||||||
<template #tabs-end>
|
<template #tabs-end>
|
||||||
<li role="presentation" class="nav-item">
|
<li role="presentation" class="nav-item">
|
||||||
<gl-link
|
<gl-link
|
||||||
|
role="tab"
|
||||||
:href="mergeRequestsSearchDashboardPath"
|
:href="mergeRequestsSearchDashboardPath"
|
||||||
class="nav-link gl-tab-nav-item !gl-no-underline"
|
class="nav-link gl-tab-nav-item !gl-no-underline"
|
||||||
>
|
>
|
||||||
|
|
|
@ -22,32 +22,32 @@ class Profiles::ChatNamesController < Profiles::ApplicationController
|
||||||
if new_chat_name.save
|
if new_chat_name.save
|
||||||
flash[:notice] = safe_format(_("Authorized %{new_chat_name}"), new_chat_name: new_chat_name.chat_name)
|
flash[:notice] = safe_format(_("Authorized %{new_chat_name}"), new_chat_name: new_chat_name.chat_name)
|
||||||
else
|
else
|
||||||
flash[:alert] = _("Could not authorize chat nickname. Try again!")
|
flash[:alert] = s_("Integrations|Could not authorize integration account nickname. Try again!")
|
||||||
end
|
end
|
||||||
|
|
||||||
delete_chat_name_token
|
delete_chat_name_token
|
||||||
redirect_to profile_chat_names_path
|
redirect_to user_settings_integration_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def deny
|
def deny
|
||||||
delete_chat_name_token
|
delete_chat_name_token
|
||||||
|
|
||||||
flash[:notice] =
|
flash[:notice] =
|
||||||
safe_format(_("Denied authorization of chat nickname %{user_name}."), user_name: chat_name_params[:user_name])
|
safe_format(_("Denied authorization of account nickname %{user_name}."), user_name: chat_name_params[:user_name])
|
||||||
|
|
||||||
redirect_to profile_chat_names_path
|
redirect_to user_settings_integration_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@chat_name = chat_names.find(params[:id])
|
@chat_name = chat_names.find(params[:id])
|
||||||
|
|
||||||
if @chat_name.destroy
|
if @chat_name.destroy
|
||||||
flash[:notice] = safe_format(_("Deleted chat nickname: %{chat_name}!"), chat_name: @chat_name.chat_name)
|
flash[:notice] = safe_format(_("Deleted account nickname: %{chat_name}!"), chat_name: @chat_name.chat_name)
|
||||||
else
|
else
|
||||||
flash[:alert] = safe_format(_("Could not delete chat nickname %{chat_name}."), chat_name: @chat_name.chat_name)
|
flash[:alert] = safe_format(_("Could not delete account nickname %{chat_name}."), chat_name: @chat_name.chat_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to profile_chat_names_path, status: :found
|
redirect_to user_settings_integration_accounts_path, status: :found
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -735,6 +735,7 @@ module Types
|
||||||
field :languages, [Types::Projects::RepositoryLanguageType],
|
field :languages, [Types::Projects::RepositoryLanguageType],
|
||||||
null: true,
|
null: true,
|
||||||
description: "Programming languages used in the project.",
|
description: "Programming languages used in the project.",
|
||||||
|
scopes: [:api, :read_api, :ai_workflows],
|
||||||
calls_gitaly: true
|
calls_gitaly: true
|
||||||
|
|
||||||
field :runners, Types::Ci::RunnerType.connection_type,
|
field :runners, Types::Ci::RunnerType.connection_type,
|
||||||
|
|
|
@ -6,11 +6,17 @@ module Types
|
||||||
class RepositoryLanguageType < BaseObject
|
class RepositoryLanguageType < BaseObject
|
||||||
graphql_name 'RepositoryLanguage'
|
graphql_name 'RepositoryLanguage'
|
||||||
|
|
||||||
|
def self.authorization_scopes
|
||||||
|
super + [:ai_workflows]
|
||||||
|
end
|
||||||
|
|
||||||
field :name, GraphQL::Types::String, null: false,
|
field :name, GraphQL::Types::String, null: false,
|
||||||
description: 'Name of the repository language.'
|
description: 'Name of the repository language.',
|
||||||
|
scopes: [:api, :read_api, :ai_workflows]
|
||||||
|
|
||||||
field :share, GraphQL::Types::Float, null: true,
|
field :share, GraphQL::Types::Float, null: true,
|
||||||
description: "Percentage of the repository's languages."
|
description: "Percentage of the repository's languages.",
|
||||||
|
scopes: [:api, :read_api, :ai_workflows]
|
||||||
|
|
||||||
field :color, Types::ColorType, null: true,
|
field :color, Types::ColorType, null: true,
|
||||||
description: 'Color to visualize the repository language.'
|
description: 'Color to visualize the repository language.'
|
||||||
|
|
|
@ -13,7 +13,7 @@ module ChatNames
|
||||||
|
|
||||||
token = request_token
|
token = request_token
|
||||||
|
|
||||||
new_profile_chat_name_url(token: token) if token
|
new_user_settings_integration_account_url(token: token) if token
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
- if !Gitlab.com? || current_user.try(:onboarding_status_initial_registration_type) != "trial"
|
- experiment(:lightweight_trial_registration_redesign, actor: current_user) do |e|
|
||||||
= render 'devise/sessions/successful_verification', local_assigns
|
- e.control do
|
||||||
- else
|
= render 'devise/sessions/successful_verification', local_assigns
|
||||||
- experiment(:lightweight_trial_registration_redesign, actor: current_user) do |e|
|
- e.candidate do
|
||||||
- e.control do
|
= render 'devise/sessions/successful_verification_lightweight', local_assigns
|
||||||
= render 'devise/sessions/successful_verification', local_assigns
|
|
||||||
- e.candidate do
|
|
||||||
= render 'devise/sessions/successful_verification_lightweight', local_assigns
|
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
%tbody
|
%tbody
|
||||||
- failed.each do |build|
|
- failed.each do |build|
|
||||||
%tr.build-state
|
%tr.build-state
|
||||||
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #8c8c8c; font-weight: 500; font-size: 14px;" }
|
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #737278; font-weight: 500; font-size: 14px;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse: collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse: collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #d22f57; font-weight: 500; font-size: 16px; vertical-align: middle; padding-right: 8px; line-height: 10px" }
|
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #d22f57; font-weight: 500; font-size: 16px; vertical-align: middle; padding-right: 8px; line-height: 10px" }
|
||||||
%img{ alt: "✖", height: "10", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red.gif'), style: "display: block;", width: "10" }/
|
%img{ alt: "✖", height: "10", src: image_url('mailers/ci_pipeline_notif_v2/x-red.png'), style: "display: block;", width: "10" }/
|
||||||
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #8c8c8c; font-weight: 500; font-size: 14px; vertical-align: middle;" }
|
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; color: #737278; font-weight: 500; font-size: 14px; vertical-align: middle;" }
|
||||||
= build.stage_name
|
= build.stage_name
|
||||||
%td{ align: "right", style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #8c8c8c; font-weight: 500; font-size: 14px;" }
|
%td{ align: "right", style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #737278; font-weight: 500; font-size: 14px;" }
|
||||||
= render "notify/links/#{build.to_partial_path}", pipeline: pipeline, build: build
|
= render "notify/links/#{build.to_partial_path}", pipeline: pipeline, build: build
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
- title = local_assigns[:title]
|
- title = local_assigns[:title]
|
||||||
%tr.table-success
|
%tr.table-success
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#108548;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }/
|
%img{ alt: "✓", height: "16", src: image_url('mailers/ci_pipeline_notif_v2/check.png'), style: "display:block;", width: "16" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||||
= title
|
= title
|
||||||
%tr.spacer
|
%tr.spacer
|
||||||
|
@ -16,9 +16,9 @@
|
||||||
%table.table-info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
%table.table-info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;" }
|
||||||
= _('Project')
|
= _('Project')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;" }
|
||||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||||
|
@ -27,26 +27,26 @@
|
||||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||||
= @project.name
|
= @project.name
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= _('Branch')
|
= _('Branch')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
%a.muted{ href: commits_url(@pipeline), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: commits_url(@pipeline), style: "color:#333333;text-decoration:none;" }
|
||||||
= @pipeline.source_ref
|
= @pipeline.source_ref
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= _('Commit')
|
= _('Commit')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:400;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-commit-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-commit-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
- commit_link = content_tag(:a, @pipeline.short_sha, href: commit_url(@pipeline), style: "color:#3777b0;text-decoration:none;").html_safe
|
- commit_link = content_tag(:a, @pipeline.short_sha, href: commit_url(@pipeline), style: "color:#3777b0;text-decoration:none;").html_safe
|
||||||
- if @merge_request
|
- if @merge_request
|
||||||
|
@ -54,13 +54,13 @@
|
||||||
= s_('Notify|%{commit_link} in %{mr_link}').html_safe % { commit_link: commit_link, mr_link: mr_link }
|
= s_('Notify|%{commit_link} in %{mr_link}').html_safe % { commit_link: commit_link, mr_link: mr_link }
|
||||||
- else
|
- else
|
||||||
= commit_link
|
= commit_link
|
||||||
.commit{ style: "color:#5c5c5c;font-weight:300;" }
|
.commit{ style: "color:#5c5c5c;font-weight:400;" }
|
||||||
= @pipeline.git_commit_message.truncate(50)
|
= @pipeline.git_commit_message.truncate(50)
|
||||||
- commit = @pipeline.commit
|
- commit = @pipeline.commit
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= s_('Notify|Commit Author')
|
= s_('Notify|Commit Author')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
@ -75,9 +75,9 @@
|
||||||
= commit.author_name
|
= commit.author_name
|
||||||
- if commit.different_committer?
|
- if commit.different_committer?
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= s_('Notify|Committed by')
|
= s_('Notify|Committed by')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
= _('API')
|
= _('API')
|
||||||
|
|
||||||
%tr
|
%tr
|
||||||
%td{ colspan: 2, style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#333333;font-size:15px;font-weight:300;line-height:1.4;padding:15px 5px;text-align:center;" }
|
%td{ colspan: 2, style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#333333;font-size:15px;font-weight:400;line-height:1.4;padding:15px 5px;text-align:center;" }
|
||||||
- job_count = @pipeline.total_size
|
- job_count = @pipeline.total_size
|
||||||
- stage_count = @pipeline.stages_count
|
- stage_count = @pipeline.stages_count
|
||||||
= s_('Notify|successfully completed %{jobs} in %{stages}.').html_safe % { jobs: n_('%d job', '%d jobs', job_count) % job_count, stages: n_('%d stage', '%d stages', stage_count) % stage_count }
|
= s_('Notify|successfully completed %{jobs} in %{stages}.').html_safe % { jobs: n_('%d job', '%d jobs', job_count) % job_count, stages: n_('%d stage', '%d stages', stage_count) % stage_count }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= user_label
|
= user_label
|
||||||
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; margin: 0; padding: 14px 0 0px 5px; font-size: 15px; line-height: 1.4; color: #333333; font-weight: 400; width: 75%; border-top-style: solid; border-top-color: #ededed; border-top-width: 1px; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;" }
|
%td{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; margin: 0; padding: 14px 0 0px 5px; font-size: 15px; line-height: 1.4; color: #333333; font-weight: 400; width: 75%; border-top-style: solid; border-top-color: #ededed; border-top-width: 1px; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;" }
|
||||||
%ul.users-list{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 15px; line-height: 1.4; padding-right: 5px; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;" }
|
%ul.users-list{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 15px; line-height: 1.4; padding-right: 5px; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; mso-table-lspace: 0pt; mso-table-rspace: 0pt;" }
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
%tr.success
|
%tr.success
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#108548;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }/
|
%img{ alt: "✓", height: "16", src: image_url('mailers/ci_pipeline_notif_v2/check.png'), style: "display:block;", width: "16" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||||
%span
|
%span
|
||||||
- if @merge_request.respond_to? :approvals_required
|
- if @merge_request.respond_to? :approvals_required
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr{ style: 'width:100%;' }
|
%tr{ style: 'width:100%;' }
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;text-align:center;" }
|
||||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:16px;width:16px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||||
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @approved_by)
|
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @approved_by)
|
||||||
%tr.spacer
|
%tr.spacer
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||||
|
@ -30,8 +30,8 @@
|
||||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align:left;width:100%;" }
|
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align:left;width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _("Project")
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;" }= _("Project")
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||||
|
@ -40,19 +40,19 @@
|
||||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||||
= @project.name
|
= @project.name
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Branch")
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Branch")
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||||
= @merge_request.source_branch
|
= @merge_request.source_branch
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Author")
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Author")
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
%tr.success
|
%tr.success
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#108548;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }
|
%img{ alt: "✓", height: "16", src: image_url('mailers/ci_pipeline_notif_v2/check.png'), style: "display:block;", width: "16" }
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||||
%span= _('Merge request was set to auto-merge')
|
%span= _('Merge request was set to auto-merge')
|
||||||
%tr.spacer
|
%tr.spacer
|
||||||
|
@ -15,8 +15,8 @@
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr{ style: 'width:100%;' }
|
%tr{ style: 'width:100%;' }
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;text-align:center;" }
|
||||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:16px;width:16px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||||
%span{ style: "font-weight: 600;color:#333333;" }= _('Merge request')
|
%span{ style: "font-weight: 600;color:#333333;" }= _('Merge request')
|
||||||
%a{ href: merge_request_url(@merge_request), style: "font-weight: 600;color:#3777b0;text-decoration:none" }= @merge_request.to_reference
|
%a{ href: merge_request_url(@merge_request), style: "font-weight: 600;color:#3777b0;text-decoration:none" }= @merge_request.to_reference
|
||||||
%span= _('was set to auto-merge by')
|
%span= _('was set to auto-merge by')
|
||||||
|
@ -31,9 +31,9 @@
|
||||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align:left;width:100%;" }
|
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align:left;width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _('Project')
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;" }= _('Project')
|
||||||
-# haml-lint:disable NoPlainNodes
|
-# haml-lint:disable NoPlainNodes
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||||
|
@ -42,19 +42,19 @@
|
||||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||||
= @project.name
|
= @project.name
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Branch')
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Branch')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||||
= @merge_request.source_branch
|
= @merge_request.source_branch
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Author')
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Author')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;line-height:1;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;line-height:1;" }
|
||||||
%img{ alt: "✖", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red-inverted.gif'), style: "display:block;", width: "13" }/
|
%img{ alt: "✖", height: "16", src: image_url('mailers/ci_pipeline_notif_v2/x.png'), style: "display:block;", width: "16" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||||
= s_('Notify|Pipeline %{pipeline_name_or_id} has failed!') % { pipeline_name_or_id: sanitize_name(@pipeline.name) || "##{@pipeline.id}" }
|
= s_('Notify|Pipeline %{pipeline_name_or_id} has failed!') % { pipeline_name_or_id: sanitize_name(@pipeline.name) || "##{@pipeline.id}" }
|
||||||
%tr.spacer
|
%tr.spacer
|
||||||
|
@ -15,9 +15,9 @@
|
||||||
%table.table-info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
%table.table-info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;" }
|
||||||
= _('Project')
|
= _('Project')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;" }
|
||||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||||
|
@ -26,26 +26,26 @@
|
||||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||||
= @project.name
|
= @project.name
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= _('Branch')
|
= _('Branch')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
%a.muted{ href: commits_url(@pipeline), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: commits_url(@pipeline), style: "color:#333333;text-decoration:none;" }
|
||||||
= @pipeline.source_ref
|
= @pipeline.source_ref
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= _('Commit')
|
= _('Commit')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:400;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-commit-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-commit-gray.gif'), style: "display:block;", width: "13", alt: "" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
%a{ href: commit_url(@pipeline), style: "color:#3777b0;text-decoration:none;" }
|
%a{ href: commit_url(@pipeline), style: "color:#3777b0;text-decoration:none;" }
|
||||||
= @pipeline.short_sha
|
= @pipeline.short_sha
|
||||||
|
@ -53,13 +53,13 @@
|
||||||
in
|
in
|
||||||
%a{ href: merge_request_url(@merge_request), style: "color:#3777b0;text-decoration:none;" }
|
%a{ href: merge_request_url(@merge_request), style: "color:#3777b0;text-decoration:none;" }
|
||||||
= @merge_request.to_reference
|
= @merge_request.to_reference
|
||||||
.commit{ style: "color:#5c5c5c;font-weight:300;" }
|
.commit{ style: "color:#5c5c5c;font-weight:400;" }
|
||||||
= @pipeline.git_commit_message.truncate(50)
|
= @pipeline.git_commit_message.truncate(50)
|
||||||
- commit = @pipeline.commit
|
- commit = @pipeline.commit
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= s_('Notify|Commit Author')
|
= s_('Notify|Commit Author')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
@ -74,8 +74,8 @@
|
||||||
= commit.author_name
|
= commit.author_name
|
||||||
- if commit.different_committer?
|
- if commit.different_committer?
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" } Committed by
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" } Committed by
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;line-height:1;" }
|
%td{ style: "vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;line-height:1;" }
|
||||||
%img{ alt: "✖", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red-inverted.gif'), style: "display:block;", width: "13" }/
|
%img{ alt: "✖", height: "16", src: image_url('mailers/ci_pipeline_notif_v2/x.png'), style: "display:block;", width: "16" }/
|
||||||
%td{ style: "vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||||
= s_('Notify|A remote mirror update has failed.')
|
= s_('Notify|A remote mirror update has failed.')
|
||||||
%tr.spacer{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
%tr.spacer{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||||
|
@ -13,9 +13,9 @@
|
||||||
%tr.section{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
%tr.section{ style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||||
%td{ style: "padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
%td{ style: "padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||||
%table.table-info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
%table.table-info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||||
%tbody{ style: "font-size:15px;line-height:1.4;color:#8c8c8c;" }
|
%tbody{ style: "font-size:15px;line-height:1.4;color:#737278;" }
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-weight:300;padding:14px 0;margin:0;" }
|
%td{ style: "font-weight:400;padding:14px 0;margin:0;" }
|
||||||
= _('Source project')
|
= _('Source project')
|
||||||
%td{ style: "font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;" }
|
%td{ style: "font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;" }
|
||||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||||
|
@ -25,12 +25,12 @@
|
||||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||||
= @project.name
|
= @project.name
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= s_('Notify|Remote mirror')
|
= s_('Notify|Remote mirror')
|
||||||
%td{ style: "font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
= @remote_mirror.safe_url
|
= @remote_mirror.safe_url
|
||||||
%tr
|
%tr
|
||||||
- update_at_start = '<td style="font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;">'.html_safe
|
- update_at_start = '<td style="font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;">'.html_safe
|
||||||
- update_at_mid = '</td><td style="font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;">'.html_safe
|
- update_at_mid = '</td><td style="font-weight:500;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;">'.html_safe
|
||||||
- update_at_end = '</td>'.html_safe
|
- update_at_end = '</td>'.html_safe
|
||||||
= html_escape(s_('Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}')) % {update_at_start: update_at_start, update_at_mid: update_at_mid, last_update_at: @remote_mirror.last_update_at, update_at_end: update_at_end}
|
= html_escape(s_('Notify|%{update_at_start} Last update at %{update_at_mid} %{last_update_at} %{update_at_end}')) % {update_at_start: update_at_start, update_at_mid: update_at_mid, last_update_at: @remote_mirror.last_update_at, update_at_end: update_at_end}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
- default_font = "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;"
|
- default_font = "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;"
|
||||||
- default_style = "#{default_font}font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;"
|
- default_style = "#{default_font}font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;"
|
||||||
- spacer_style = "#{default_font};height:18px;font-size:18px;line-height:18px;"
|
- spacer_style = "#{default_font};height:18px;font-size:18px;line-height:18px;"
|
||||||
|
|
||||||
%tr.alert
|
%tr.alert
|
||||||
%td{ style: "#{default_font}padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#FC6D26;" }
|
%td{ style: "#{default_font}padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#d22f57;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
%tr.success
|
%tr.success
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#FC6D26;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#d22f57;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||||
%img{ alt: "✗", height: "13", src: image_url('mailers/approval/icon-x-orange-inverted.gif'), style: "display:block;", width: "13" }/
|
%img{ alt: "✗", height: "16", src: image_url('mailers/approval_v2/x.png'), style: "display:block;", width: "16" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||||
- if @merge_request.respond_to? :approvals_required
|
- if @merge_request.respond_to? :approvals_required
|
||||||
%span
|
%span
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr{ style: 'width:100%;' }
|
%tr{ style: 'width:100%;' }
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;text-align:center;" }
|
||||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:16px;width:16px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||||
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @unapproved_by)
|
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @unapproved_by)
|
||||||
%tr.spacer
|
%tr.spacer
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||||
|
@ -31,9 +31,9 @@
|
||||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align:left;width:100%;" }
|
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "text-align:left;width:100%;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;" }
|
||||||
= _('Project')
|
= _('Project')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||||
|
@ -42,21 +42,21 @@
|
||||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||||
= @project.name
|
= @project.name
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= _('Branch')
|
= _('Branch')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v2/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||||
= @merge_request.source_branch
|
= @merge_request.source_branch
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||||
= _('Author')
|
= _('Author')
|
||||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#737278;font-weight:400;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
- default_font = "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;"
|
- default_font = "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;"
|
||||||
- default_style = "#{default_font}font-size:15px;line-height:1.4;color:#626168;font-weight:300;padding:14px 0;margin:0;"
|
- default_style = "#{default_font}font-size:15px;line-height:1.4;color:#626168;font-weight:400;padding:14px 0;margin:0;"
|
||||||
- spacer_style = "#{default_font};height:18px;font-size:18px;line-height:18px;"
|
- spacer_style = "#{default_font};height:18px;font-size:18px;line-height:18px;"
|
||||||
|
|
||||||
%tr.alert
|
%tr.alert
|
||||||
%td{ style: "#{default_font}padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#FC6D26;" }
|
%td{ style: "#{default_font}padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#3a383f;background-color:#fdf1dd;" }
|
||||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td{ style: "#{default_font}vertical-align:middle;color:#ffffff;text-align:center;" }
|
%td{ style: "#{default_font}vertical-align:middle;color:#3a383f;text-align:center;" }
|
||||||
%span
|
%span
|
||||||
= _("Someone signed in to your %{host} account from a new location") % { host: Gitlab.config.gitlab.host }
|
= _("Someone signed in to your %{host} account from a new location") % { host: Gitlab.config.gitlab.host }
|
||||||
%tr.spacer
|
%tr.spacer
|
||||||
|
|
|
@ -10,4 +10,4 @@
|
||||||
= _('Never')
|
= _('Never')
|
||||||
|
|
||||||
%td
|
%td
|
||||||
= link_button_to _('Remove'), profile_chat_name_path(chat_name), method: :delete, class: 'gl-float-right', aria: { label: _('Remove') }, data: { confirm: _('Are you sure you want to remove this nickname?'), confirm_btn_variant: 'danger' }, variant: :danger
|
= link_button_to _('Remove'), user_settings_integration_account_path(chat_name), method: :delete, class: 'gl-float-right', aria: { label: _('Remove') }, data: { confirm: _('Are you sure you want to remove this nickname?'), confirm_btn_variant: 'danger' }, variant: :danger
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
- page_title _('Chat')
|
- page_title s_('Integrations|Integration accounts')
|
||||||
- @hide_search_settings = true
|
- @hide_search_settings = true
|
||||||
- @force_desktop_expanded_sidebar = true
|
- @force_desktop_expanded_sidebar = true
|
||||||
|
|
||||||
= render ::Layouts::SettingsSectionComponent.new(page_title) do |c|
|
= render ::Layouts::SettingsSectionComponent.new(page_title) do |c|
|
||||||
|
- c.with_description do
|
||||||
|
= s_('Integrations|Manage your integration accounts in GitLab. Use these connected integrations to perform actions in GitLab.')
|
||||||
- c.with_body do
|
- c.with_body do
|
||||||
= render ::Layouts::CrudComponent.new(_('Active chat names'),
|
= render ::Layouts::CrudComponent.new(s_('Integrations|Connected integration accounts'),
|
||||||
count: @chat_names.size,
|
count: @chat_names.size,
|
||||||
icon: 'comment') do |c|
|
icon: 'connected') do |c|
|
||||||
- c.with_body do
|
- c.with_body do
|
||||||
- if @chat_names.present?
|
- if @chat_names.present?
|
||||||
.table-responsive
|
.table-responsive
|
||||||
|
@ -20,4 +22,4 @@
|
||||||
%tbody
|
%tbody
|
||||||
= render @chat_names
|
= render @chat_names
|
||||||
- else
|
- else
|
||||||
.gl-text-subtle= _("You don't have any active chat names.")
|
.gl-text-subtle= s_('Integrations|You do not have any connected integration accounts.')
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
= s_("SlackIntegration|You don't have to reauthorize this application if the permission scope changes in future releases.")
|
= s_("SlackIntegration|You don't have to reauthorize this application if the permission scope changes in future releases.")
|
||||||
- c.with_footer do
|
- c.with_footer do
|
||||||
.gl-flex
|
.gl-flex
|
||||||
= form_tag profile_chat_names_path, method: :post do
|
= form_tag user_settings_integration_accounts_path, method: :post do
|
||||||
= hidden_field_tag :token, @chat_name_token.token
|
= hidden_field_tag :token, @chat_name_token.token
|
||||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :danger, button_options: { data: { testid: 'authorize-button' } }) do
|
= render Pajamas::ButtonComponent.new(type: :submit, variant: :danger, button_options: { data: { testid: 'authorize-button' } }) do
|
||||||
= _('Authorize')
|
= _('Authorize')
|
||||||
= form_tag deny_profile_chat_names_path, method: :delete do
|
= form_tag deny_user_settings_integration_accounts_path, method: :delete do
|
||||||
= hidden_field_tag :token, @chat_name_token.token
|
= hidden_field_tag :token, @chat_name_token.token
|
||||||
= render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-ml-3' }) do
|
= render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-ml-3' }) do
|
||||||
= _('Deny')
|
= _('Deny')
|
||||||
|
|
|
@ -51,14 +51,14 @@ resource :profile, only: [] do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :chat_names, only: [:index, :new, :create, :destroy] do
|
|
||||||
collection do
|
|
||||||
delete :deny
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
resource :avatar, only: [:destroy]
|
resource :avatar, only: [:destroy]
|
||||||
|
|
||||||
|
get 'chat_names', to: redirect('-/user_settings/integration_accounts')
|
||||||
|
|
||||||
|
get 'chat_names/new', to: redirect { |_params, request|
|
||||||
|
"-/user_settings/integration_accounts/new?#{request.query_string}"
|
||||||
|
}
|
||||||
|
|
||||||
resource :two_factor_auth, only: [:show, :create, :destroy] do
|
resource :two_factor_auth, only: [:show, :create, :destroy] do
|
||||||
member do
|
member do
|
||||||
post :codes
|
post :codes
|
||||||
|
|
|
@ -30,4 +30,9 @@ namespace :user_settings do
|
||||||
delete :revoke
|
delete :revoke
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
resources :integration_accounts, only: [:index, :new, :create, :destroy], controller: '/profiles/chat_names' do
|
||||||
|
collection do
|
||||||
|
delete :deny
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
---
|
---
|
||||||
migration_job_name: BackfillOnboardingStatusRegistrationObjective
|
migration_job_name: BackfillOnboardingStatusRegistrationObjective
|
||||||
description: Moves data from user_details.registration_objective to the new registration_objective field in user_details.onboarding_status
|
description: Moves data from user_details.registration_objective to the new registration_objective
|
||||||
|
field in user_details.onboarding_status
|
||||||
feature_category: onboarding
|
feature_category: onboarding
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/176428
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/176428
|
||||||
milestone: '17.9'
|
milestone: '17.9'
|
||||||
queued_migration_version: 20250117172734
|
queued_migration_version: 20250117172734
|
||||||
finalized_by:
|
finalized_by: '20250708081911'
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
---
|
---
|
||||||
migration_job_name: BackfillOnboardingStatusSetupForCompany
|
migration_job_name: BackfillOnboardingStatusSetupForCompany
|
||||||
description: Moves data from user_preferences.setup_for_company to the new setup_for_company field in user_details.onboarding_status
|
description: Moves data from user_preferences.setup_for_company to the new setup_for_company
|
||||||
|
field in user_details.onboarding_status
|
||||||
feature_category: onboarding
|
feature_category: onboarding
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/180602
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/180602
|
||||||
milestone: '17.10'
|
milestone: '17.10'
|
||||||
queued_migration_version: 20250228155146
|
queued_migration_version: 20250228155146
|
||||||
finalized_by: # version of the migration that finalized this BBM
|
finalized_by: '20250713232042'
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
---
|
---
|
||||||
migration_job_name: FixUsernamespaceAuditEvents
|
migration_job_name: FixUsernamespaceAuditEvents
|
||||||
description: Some audit events are tagged with scope UserNamespace which is incorrect this migration corrects the scope
|
description: Some audit events are tagged with scope UserNamespace which is incorrect
|
||||||
|
this migration corrects the scope
|
||||||
feature_category: audit_events
|
feature_category: audit_events
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177095
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177095
|
||||||
milestone: '17.9'
|
milestone: '17.9'
|
||||||
queued_migration_version: 20250106104021
|
queued_migration_version: 20250106104021
|
||||||
finalized_by: # version of the migration that finalized this BBM
|
finalized_by: '20250709154335'
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddProjectIdToMergeRequestDiffCommits < Gitlab::Database::Migration[2.3]
|
||||||
|
milestone '18.2'
|
||||||
|
|
||||||
|
def change
|
||||||
|
add_column :merge_request_diff_commits, :project_id, :bigint # rubocop:disable Migration/PreventAddingColumns -- Needed for future partitioning and sharding
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddDeletedAtToAiCatalogItems < Gitlab::Database::Migration[2.3]
|
||||||
|
milestone '18.3'
|
||||||
|
|
||||||
|
def change
|
||||||
|
add_column :ai_catalog_items, :deleted_at, :datetime_with_timezone
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddIndexToAiCatalogItemsDeletedAt < Gitlab::Database::Migration[2.3]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
milestone '18.3'
|
||||||
|
|
||||||
|
INDEX_NAME = 'index_ai_catalog_items_where_deleted_at_is_null'
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_index :ai_catalog_items, :deleted_at, where: 'deleted_at IS NULL', name: INDEX_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_concurrent_index_by_name :ai_catalog_items, INDEX_NAME
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeHkBackfillOnboardingStatusRegistrationObjective < Gitlab::Database::Migration[2.3]
|
||||||
|
milestone '18.2'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'BackfillOnboardingStatusRegistrationObjective',
|
||||||
|
table_name: :user_details,
|
||||||
|
column_name: :user_id,
|
||||||
|
job_arguments: [],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeHkFixUsernamespaceAuditEvents < Gitlab::Database::Migration[2.3]
|
||||||
|
milestone '18.2'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'FixUsernamespaceAuditEvents',
|
||||||
|
table_name: :audit_events,
|
||||||
|
column_name: :id,
|
||||||
|
job_arguments: [],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeHkBackfillOnboardingStatusSetupForCompany < Gitlab::Database::Migration[2.3]
|
||||||
|
milestone '18.2'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'BackfillOnboardingStatusSetupForCompany',
|
||||||
|
table_name: :user_details,
|
||||||
|
column_name: :user_id,
|
||||||
|
job_arguments: [],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
fb637948469c5747563202f5395dd1814f24bb92711d5355638f8b4f1fdf3429
|
|
@ -0,0 +1 @@
|
||||||
|
23bd123c461e72a7d497fc10b99d2dc32be516cd518a0cde9655f3dd8d20ae5f
|
|
@ -0,0 +1 @@
|
||||||
|
51a690472117d17ebf648351f10b8acdc23a95da2b623cc29a47e4faca2f1b78
|
|
@ -0,0 +1 @@
|
||||||
|
3825f64cf8388cfdc4b48ba4573b6d90b46ce741df0ec6b6d07d646615d242ec
|
|
@ -0,0 +1 @@
|
||||||
|
82a7340f7a4aa6c7996a795485bbe974f91e106b525697390ea57334036a3e6e
|
|
@ -0,0 +1 @@
|
||||||
|
3235012c99576472c6b504866cfe78ba790260308a5b335eb73e6b7713849be6
|
|
@ -8295,6 +8295,7 @@ CREATE TABLE ai_catalog_items (
|
||||||
description text NOT NULL,
|
description text NOT NULL,
|
||||||
name text NOT NULL,
|
name text NOT NULL,
|
||||||
public boolean DEFAULT false NOT NULL,
|
public boolean DEFAULT false NOT NULL,
|
||||||
|
deleted_at timestamp with time zone,
|
||||||
CONSTRAINT check_7e02a4805b CHECK ((char_length(description) <= 1024)),
|
CONSTRAINT check_7e02a4805b CHECK ((char_length(description) <= 1024)),
|
||||||
CONSTRAINT check_edddd6e1fe CHECK ((char_length(name) <= 255))
|
CONSTRAINT check_edddd6e1fe CHECK ((char_length(name) <= 255))
|
||||||
);
|
);
|
||||||
|
@ -17504,7 +17505,8 @@ CREATE TABLE merge_request_diff_commits (
|
||||||
trailers jsonb DEFAULT '{}'::jsonb,
|
trailers jsonb DEFAULT '{}'::jsonb,
|
||||||
commit_author_id bigint,
|
commit_author_id bigint,
|
||||||
committer_id bigint,
|
committer_id bigint,
|
||||||
merge_request_commits_metadata_id bigint
|
merge_request_commits_metadata_id bigint,
|
||||||
|
project_id bigint
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE merge_request_diff_details (
|
CREATE TABLE merge_request_diff_details (
|
||||||
|
@ -34537,6 +34539,8 @@ CREATE INDEX index_ai_catalog_items_on_project_id ON ai_catalog_items USING btre
|
||||||
|
|
||||||
CREATE INDEX index_ai_catalog_items_on_public ON ai_catalog_items USING btree (public);
|
CREATE INDEX index_ai_catalog_items_on_public ON ai_catalog_items USING btree (public);
|
||||||
|
|
||||||
|
CREATE INDEX index_ai_catalog_items_where_deleted_at_is_null ON ai_catalog_items USING btree (deleted_at) WHERE (deleted_at IS NULL);
|
||||||
|
|
||||||
CREATE INDEX index_ai_code_suggestion_events_on_organization_id ON ONLY ai_code_suggestion_events USING btree (organization_id);
|
CREATE INDEX index_ai_code_suggestion_events_on_organization_id ON ONLY ai_code_suggestion_events USING btree (organization_id);
|
||||||
|
|
||||||
CREATE INDEX index_ai_code_suggestion_events_on_user_id ON ONLY ai_code_suggestion_events USING btree (user_id);
|
CREATE INDEX index_ai_code_suggestion_events_on_user_id ON ONLY ai_code_suggestion_events USING btree (user_id);
|
||||||
|
|
|
@ -18,7 +18,7 @@ like joining projects, commenting on issues, pushing changes to MRs, or closing
|
||||||
For information about activity retention limits, see:
|
For information about activity retention limits, see:
|
||||||
|
|
||||||
- [User activity time period limit](../user/profile/contributions_calendar.md#event-time-period-limit)
|
- [User activity time period limit](../user/profile/contributions_calendar.md#event-time-period-limit)
|
||||||
- [Project activity time period limit](../user/project/working_with_projects.md#event-time-period-limit)
|
- [Project activity time period limit](../user/project/working_with_projects.md#view-project-activity)
|
||||||
|
|
||||||
## List all events
|
## List all events
|
||||||
|
|
||||||
|
|
|
@ -571,6 +571,27 @@ Get the list of all the compliance requirement controls.
|
||||||
|
|
||||||
Returns [`ComplianceRequirementControl`](#compliancerequirementcontrol).
|
Returns [`ComplianceRequirementControl`](#compliancerequirementcontrol).
|
||||||
|
|
||||||
|
### `Query.configuredAiCatalogItems`
|
||||||
|
|
||||||
|
AI Catalog items configured for use.
|
||||||
|
|
||||||
|
{{< details >}}
|
||||||
|
**Introduced** in GitLab 18.2.
|
||||||
|
**Status**: Experiment.
|
||||||
|
{{< /details >}}
|
||||||
|
|
||||||
|
Returns [`AiCatalogItemConsumerConnection!`](#aicatalogitemconsumerconnection).
|
||||||
|
|
||||||
|
This field returns a [connection](#connections). It accepts the
|
||||||
|
four standard [pagination arguments](#pagination-arguments):
|
||||||
|
`before: String`, `after: String`, `first: Int`, and `last: Int`.
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="queryconfiguredaicatalogitemsprojectid"></a>`projectId` | [`ProjectID!`](#projectid) | Project ID to retrieve configured AI Catalog items for. |
|
||||||
|
|
||||||
### `Query.containerRepository`
|
### `Query.containerRepository`
|
||||||
|
|
||||||
Find a container repository.
|
Find a container repository.
|
||||||
|
@ -2277,6 +2298,33 @@ Input type: `AiCatalogAgentDeleteInput`
|
||||||
| <a id="mutationaicatalogagentdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during the mutation. |
|
| <a id="mutationaicatalogagentdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during the mutation. |
|
||||||
| <a id="mutationaicatalogagentdeletesuccess"></a>`success` | [`Boolean!`](#boolean) | Returns true if catalog Agent was successfully deleted. |
|
| <a id="mutationaicatalogagentdeletesuccess"></a>`success` | [`Boolean!`](#boolean) | Returns true if catalog Agent was successfully deleted. |
|
||||||
|
|
||||||
|
### `Mutation.aiCatalogFlowCreate`
|
||||||
|
|
||||||
|
{{< details >}}
|
||||||
|
**Introduced** in GitLab 18.3.
|
||||||
|
**Status**: Experiment.
|
||||||
|
{{< /details >}}
|
||||||
|
|
||||||
|
Input type: `AiCatalogFlowCreateInput`
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="mutationaicatalogflowcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||||
|
| <a id="mutationaicatalogflowcreatedescription"></a>`description` | [`String!`](#string) | Description for the flow. |
|
||||||
|
| <a id="mutationaicatalogflowcreatename"></a>`name` | [`String!`](#string) | Name for the flow. |
|
||||||
|
| <a id="mutationaicatalogflowcreateprojectid"></a>`projectId` | [`ProjectID!`](#projectid) | Project for the flow. |
|
||||||
|
| <a id="mutationaicatalogflowcreatepublic"></a>`public` | [`Boolean!`](#boolean) | Whether the flow is publicly visible in the catalog. |
|
||||||
|
|
||||||
|
#### Fields
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="mutationaicatalogflowcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||||
|
| <a id="mutationaicatalogflowcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during the mutation. |
|
||||||
|
| <a id="mutationaicatalogflowcreateitem"></a>`item` | [`AiCatalogItem`](#aicatalogitem) | Item created. |
|
||||||
|
|
||||||
### `Mutation.aiDuoWorkflowCreate`
|
### `Mutation.aiDuoWorkflowCreate`
|
||||||
|
|
||||||
{{< details >}}
|
{{< details >}}
|
||||||
|
@ -13966,6 +14014,30 @@ The connection type for [`AiCatalogItem`](#aicatalogitem).
|
||||||
| <a id="aicatalogitemconnectionnodes"></a>`nodes` | [`[AiCatalogItem]`](#aicatalogitem) | A list of nodes. |
|
| <a id="aicatalogitemconnectionnodes"></a>`nodes` | [`[AiCatalogItem]`](#aicatalogitem) | A list of nodes. |
|
||||||
| <a id="aicatalogitemconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
| <a id="aicatalogitemconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||||
|
|
||||||
|
#### `AiCatalogItemConsumerConnection`
|
||||||
|
|
||||||
|
The connection type for [`AiCatalogItemConsumer`](#aicatalogitemconsumer).
|
||||||
|
|
||||||
|
##### Fields
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="aicatalogitemconsumerconnectioncount"></a>`count` | [`Int!`](#int) | Total count of collection. |
|
||||||
|
| <a id="aicatalogitemconsumerconnectionedges"></a>`edges` | [`[AiCatalogItemConsumerEdge]`](#aicatalogitemconsumeredge) | A list of edges. |
|
||||||
|
| <a id="aicatalogitemconsumerconnectionnodes"></a>`nodes` | [`[AiCatalogItemConsumer]`](#aicatalogitemconsumer) | A list of nodes. |
|
||||||
|
| <a id="aicatalogitemconsumerconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||||
|
|
||||||
|
#### `AiCatalogItemConsumerEdge`
|
||||||
|
|
||||||
|
The edge type for [`AiCatalogItemConsumer`](#aicatalogitemconsumer).
|
||||||
|
|
||||||
|
##### Fields
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="aicatalogitemconsumeredgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||||
|
| <a id="aicatalogitemconsumeredgenode"></a>`node` | [`AiCatalogItemConsumer`](#aicatalogitemconsumer) | The item at the end of the edge. |
|
||||||
|
|
||||||
#### `AiCatalogItemEdge`
|
#### `AiCatalogItemEdge`
|
||||||
|
|
||||||
The edge type for [`AiCatalogItem`](#aicatalogitem).
|
The edge type for [`AiCatalogItem`](#aicatalogitem).
|
||||||
|
@ -21991,6 +22063,7 @@ An AI catalog agent.
|
||||||
| <a id="aicatalogagentdescription"></a>`description` | [`String!`](#string) | Description of the item. |
|
| <a id="aicatalogagentdescription"></a>`description` | [`String!`](#string) | Description of the item. |
|
||||||
| <a id="aicatalogagentid"></a>`id` | [`ID!`](#id) | ID of the item. |
|
| <a id="aicatalogagentid"></a>`id` | [`ID!`](#id) | ID of the item. |
|
||||||
| <a id="aicatalogagentitemtype"></a>`itemType` | [`AiCatalogItemType!`](#aicatalogitemtype) | Type of the item. |
|
| <a id="aicatalogagentitemtype"></a>`itemType` | [`AiCatalogItemType!`](#aicatalogitemtype) | Type of the item. |
|
||||||
|
| <a id="aicatalogagentlatestversion"></a>`latestVersion` | [`AiCatalogItemVersion`](#aicatalogitemversion) | Latest version of the item. |
|
||||||
| <a id="aicatalogagentname"></a>`name` | [`String!`](#string) | Name of the item. |
|
| <a id="aicatalogagentname"></a>`name` | [`String!`](#string) | Name of the item. |
|
||||||
| <a id="aicatalogagentproject"></a>`project` | [`Project`](#project) | Project for the item. |
|
| <a id="aicatalogagentproject"></a>`project` | [`Project`](#project) | Project for the item. |
|
||||||
| <a id="aicatalogagentpublic"></a>`public` | [`Boolean!`](#boolean) | Whether the item is publicly visible in the catalog. |
|
| <a id="aicatalogagentpublic"></a>`public` | [`Boolean!`](#boolean) | Whether the item is publicly visible in the catalog. |
|
||||||
|
@ -22024,6 +22097,7 @@ An AI catalog flow.
|
||||||
| <a id="aicatalogflowdescription"></a>`description` | [`String!`](#string) | Description of the item. |
|
| <a id="aicatalogflowdescription"></a>`description` | [`String!`](#string) | Description of the item. |
|
||||||
| <a id="aicatalogflowid"></a>`id` | [`ID!`](#id) | ID of the item. |
|
| <a id="aicatalogflowid"></a>`id` | [`ID!`](#id) | ID of the item. |
|
||||||
| <a id="aicatalogflowitemtype"></a>`itemType` | [`AiCatalogItemType!`](#aicatalogitemtype) | Type of the item. |
|
| <a id="aicatalogflowitemtype"></a>`itemType` | [`AiCatalogItemType!`](#aicatalogitemtype) | Type of the item. |
|
||||||
|
| <a id="aicatalogflowlatestversion"></a>`latestVersion` | [`AiCatalogItemVersion`](#aicatalogitemversion) | Latest version of the item. |
|
||||||
| <a id="aicatalogflowname"></a>`name` | [`String!`](#string) | Name of the item. |
|
| <a id="aicatalogflowname"></a>`name` | [`String!`](#string) | Name of the item. |
|
||||||
| <a id="aicatalogflowproject"></a>`project` | [`Project`](#project) | Project for the item. |
|
| <a id="aicatalogflowproject"></a>`project` | [`Project`](#project) | Project for the item. |
|
||||||
| <a id="aicatalogflowpublic"></a>`public` | [`Boolean!`](#boolean) | Whether the item is publicly visible in the catalog. |
|
| <a id="aicatalogflowpublic"></a>`public` | [`Boolean!`](#boolean) | Whether the item is publicly visible in the catalog. |
|
||||||
|
@ -22043,6 +22117,22 @@ An AI catalog flow version.
|
||||||
| <a id="aicatalogflowversionupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the item version was updated. |
|
| <a id="aicatalogflowversionupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the item version was updated. |
|
||||||
| <a id="aicatalogflowversionversionname"></a>`versionName` | [`String`](#string) | Version name of the item version. |
|
| <a id="aicatalogflowversionversionname"></a>`versionName` | [`String`](#string) | Version name of the item version. |
|
||||||
|
|
||||||
|
### `AiCatalogItemConsumer`
|
||||||
|
|
||||||
|
An AI catalog item configuration.
|
||||||
|
|
||||||
|
#### Fields
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="aicatalogitemconsumerenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether the catalog item is enabled or not. |
|
||||||
|
| <a id="aicatalogitemconsumergroup"></a>`group` | [`Group`](#group) | Group in which the catalog item is configured. |
|
||||||
|
| <a id="aicatalogitemconsumerid"></a>`id` | [`ID!`](#id) | ID of the configuration item. |
|
||||||
|
| <a id="aicatalogitemconsumeritem"></a>`item` | [`AiCatalogItem`](#aicatalogitem) | Configuration catalog item. |
|
||||||
|
| <a id="aicatalogitemconsumerlocked"></a>`locked` | [`Boolean!`](#boolean) | Indicates whether the catalog item configuration is locked or can be overridden. |
|
||||||
|
| <a id="aicatalogitemconsumerorganization"></a>`organization` | [`Organization`](#organization) | Organization in which the catalog item is configured. |
|
||||||
|
| <a id="aicatalogitemconsumerproject"></a>`project` | [`Project`](#project) | Project in which the catalog item is configured. |
|
||||||
|
|
||||||
### `AiConversationsThread`
|
### `AiConversationsThread`
|
||||||
|
|
||||||
Conversation thread of the AI feature.
|
Conversation thread of the AI feature.
|
||||||
|
@ -27581,6 +27671,7 @@ GitLab Duo Agent Platform session.
|
||||||
| ---- | ---- | ----------- |
|
| ---- | ---- | ----------- |
|
||||||
| <a id="duoworkflowagentprivilegesnames"></a>`agentPrivilegesNames` | [`[String!]`](#string) | Privileges granted to the agent during execution. |
|
| <a id="duoworkflowagentprivilegesnames"></a>`agentPrivilegesNames` | [`[String!]`](#string) | Privileges granted to the agent during execution. |
|
||||||
| <a id="duoworkflowallowagenttorequestuser"></a>`allowAgentToRequestUser` | [`Boolean`](#boolean) | Allow the agent to request user input. |
|
| <a id="duoworkflowallowagenttorequestuser"></a>`allowAgentToRequestUser` | [`Boolean`](#boolean) | Allow the agent to request user input. |
|
||||||
|
| <a id="duoworkflowarchived"></a>`archived` | [`Boolean`](#boolean) | Archived due to retention policy. |
|
||||||
| <a id="duoworkflowcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the session was created. |
|
| <a id="duoworkflowcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the session was created. |
|
||||||
| <a id="duoworkflowenvironment"></a>`environment` | [`WorkflowEnvironment`](#workflowenvironment) | Environment, like IDE or web. |
|
| <a id="duoworkflowenvironment"></a>`environment` | [`WorkflowEnvironment`](#workflowenvironment) | Environment, like IDE or web. |
|
||||||
| <a id="duoworkflowfirstcheckpoint"></a>`firstCheckpoint` | [`DuoWorkflowEvent`](#duoworkflowevent) | First checkpoint of the session. |
|
| <a id="duoworkflowfirstcheckpoint"></a>`firstCheckpoint` | [`DuoWorkflowEvent`](#duoworkflowevent) | First checkpoint of the session. |
|
||||||
|
@ -27591,6 +27682,7 @@ GitLab Duo Agent Platform session.
|
||||||
| <a id="duoworkflowpreapprovedagentprivilegesnames"></a>`preApprovedAgentPrivilegesNames` | [`[String!]`](#string) | Privileges pre-approved for the agent during execution. |
|
| <a id="duoworkflowpreapprovedagentprivilegesnames"></a>`preApprovedAgentPrivilegesNames` | [`[String!]`](#string) | Privileges pre-approved for the agent during execution. |
|
||||||
| <a id="duoworkflowproject"></a>`project` | [`Project!`](#project) | Project that the session is in. |
|
| <a id="duoworkflowproject"></a>`project` | [`Project!`](#project) | Project that the session is in. |
|
||||||
| <a id="duoworkflowprojectid"></a>`projectId` | [`ProjectID!`](#projectid) | ID of the project. |
|
| <a id="duoworkflowprojectid"></a>`projectId` | [`ProjectID!`](#projectid) | ID of the project. |
|
||||||
|
| <a id="duoworkflowstalled"></a>`stalled` | [`Boolean`](#boolean) | Workflow got created but has no checkpoints. |
|
||||||
| <a id="duoworkflowstatus"></a>`status` | [`DuoWorkflowStatus`](#duoworkflowstatus) | Status of the session. |
|
| <a id="duoworkflowstatus"></a>`status` | [`DuoWorkflowStatus`](#duoworkflowstatus) | Status of the session. |
|
||||||
| <a id="duoworkflowstatusname"></a>`statusName` | [`String`](#string) | Status name of the session. |
|
| <a id="duoworkflowstatusname"></a>`statusName` | [`String`](#string) | Status name of the session. |
|
||||||
| <a id="duoworkflowupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the session was last updated. |
|
| <a id="duoworkflowupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the session was last updated. |
|
||||||
|
@ -50170,6 +50262,7 @@ Implementations:
|
||||||
| <a id="aicatalogitemdescription"></a>`description` | [`String!`](#string) | Description of the item. |
|
| <a id="aicatalogitemdescription"></a>`description` | [`String!`](#string) | Description of the item. |
|
||||||
| <a id="aicatalogitemid"></a>`id` | [`ID!`](#id) | ID of the item. |
|
| <a id="aicatalogitemid"></a>`id` | [`ID!`](#id) | ID of the item. |
|
||||||
| <a id="aicatalogitemitemtype"></a>`itemType` | [`AiCatalogItemType!`](#aicatalogitemtype) | Type of the item. |
|
| <a id="aicatalogitemitemtype"></a>`itemType` | [`AiCatalogItemType!`](#aicatalogitemtype) | Type of the item. |
|
||||||
|
| <a id="aicatalogitemlatestversion"></a>`latestVersion` | [`AiCatalogItemVersion`](#aicatalogitemversion) | Latest version of the item. |
|
||||||
| <a id="aicatalogitemname"></a>`name` | [`String!`](#string) | Name of the item. |
|
| <a id="aicatalogitemname"></a>`name` | [`String!`](#string) | Name of the item. |
|
||||||
| <a id="aicatalogitemproject"></a>`project` | [`Project`](#project) | Project for the item. |
|
| <a id="aicatalogitemproject"></a>`project` | [`Project`](#project) | Project for the item. |
|
||||||
| <a id="aicatalogitempublic"></a>`public` | [`Boolean!`](#boolean) | Whether the item is publicly visible in the catalog. |
|
| <a id="aicatalogitempublic"></a>`public` | [`Boolean!`](#boolean) | Whether the item is publicly visible in the catalog. |
|
||||||
|
|
|
@ -952,7 +952,7 @@ Example response:
|
||||||
|
|
||||||
### List projects a user has contributed to
|
### List projects a user has contributed to
|
||||||
|
|
||||||
Returns a list of visible projects a given user has contributed to within the past year. For more information about what counts as a contribution, see [view projects you have contributed to](../user/project/working_with_projects.md#view-projects-you-have-contributed-to).
|
Returns a list of visible projects a given user has contributed to within the past year. For more information about what counts as a contribution, [view projects you have contributed to](../user/project/working_with_projects.md#view-projects-you-work-with).
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
GET /users/:user_id/contributed_projects
|
GET /users/:user_id/contributed_projects
|
||||||
|
|
|
@ -664,7 +664,7 @@ Prerequisites:
|
||||||
- You must have at least the Maintainer role for the project.
|
- You must have at least the Maintainer role for the project.
|
||||||
- The project must:
|
- The project must:
|
||||||
- Be set as a [catalog project](#set-a-component-project-as-a-catalog-project).
|
- Be set as a [catalog project](#set-a-component-project-as-a-catalog-project).
|
||||||
- Have a [project description](../../user/project/working_with_projects.md#edit-project-name-and-description) defined.
|
- Have a [project description](../../user/project/working_with_projects.md#edit-a-project) defined.
|
||||||
- Have a `README.md` file in the root directory for the commit SHA of the tag being released.
|
- Have a `README.md` file in the root directory for the commit SHA of the tag being released.
|
||||||
- Have at least one [CI/CD component in the `templates/` directory](#directory-structure)
|
- Have at least one [CI/CD component in the `templates/` directory](#directory-structure)
|
||||||
for the commit SHA of the tag being released.
|
for the commit SHA of the tag being released.
|
||||||
|
@ -833,7 +833,7 @@ To mirror a GitLab.com component in your GitLab Self-Managed instance:
|
||||||
1. Make sure that [network outbound requests](../../security/webhooks.md) are allowed for `gitlab.com`.
|
1. Make sure that [network outbound requests](../../security/webhooks.md) are allowed for `gitlab.com`.
|
||||||
1. [Create a group](../../user/group/_index.md#create-a-group) to host the component projects (recommended group: `components`).
|
1. [Create a group](../../user/group/_index.md#create-a-group) to host the component projects (recommended group: `components`).
|
||||||
1. [Create a mirror of the component project](../../user/project/repository/mirror/pull.md) in the new group.
|
1. [Create a mirror of the component project](../../user/project/repository/mirror/pull.md) in the new group.
|
||||||
1. Write a [project description](../../user/project/working_with_projects.md#edit-project-name-and-description)
|
1. Write a [project description](../../user/project/working_with_projects.md#edit-a-project)
|
||||||
for the component project mirror because mirroring repositories does not copy the description.
|
for the component project mirror because mirroring repositories does not copy the description.
|
||||||
1. [Set the self-hosted component project as a catalog resource](#set-a-component-project-as-a-catalog-project).
|
1. [Set the self-hosted component project as a catalog resource](#set-a-component-project-as-a-catalog-project).
|
||||||
1. Publish [a new release](../../user/project/releases/_index.md) in the self-hosted component project by
|
1. Publish [a new release](../../user/project/releases/_index.md) in the self-hosted component project by
|
||||||
|
|
|
@ -96,5 +96,5 @@ You can view the compute usage for your personal namespace:
|
||||||
1. Select **Edit profile**.
|
1. Select **Edit profile**.
|
||||||
1. On the left sidebar, select **Usage Quotas**.
|
1. On the left sidebar, select **Usage Quotas**.
|
||||||
|
|
||||||
The projects list shows [personal projects](../../user/project/working_with_projects.md#view-personal-projects)
|
The projects list shows [personal projects](../../user/project/working_with_projects.md)
|
||||||
with compute usage or instance runners usage in the current month only.
|
with compute usage or instance runners usage in the current month only.
|
||||||
|
|
|
@ -57,19 +57,33 @@ The diagram below shows how protection rules are evaluated in the context of an
|
||||||
%%{init: { "fontFamily": "GitLab Sans" }}%%
|
%%{init: { "fontFamily": "GitLab Sans" }}%%
|
||||||
graph TD
|
graph TD
|
||||||
accTitle: Evaluation of protected and immutable tag rules
|
accTitle: Evaluation of protected and immutable tag rules
|
||||||
accDescr: An illustration of the evaluation process for protected and immutable tag rules during an image push.
|
accDescr: Flow chart showing the evaluation process for protected and immutable tag rules during an image push.
|
||||||
A[User attempts to push a tag] --> B{Does the user have the required role for push?}
|
A[User attempts to push a tag] --> B{Protected tag check:<br/>Does user have required role<br/>to push this tag pattern?}
|
||||||
B -- Yes --> C{Does the tag already exist?}
|
B -- Yes --> C{Does the tag already exist?}
|
||||||
B -- No --> D[Push denied: Insufficient permissions]
|
B -- No --> D[Push denied:<br/>Protected tag - insufficient permissions]
|
||||||
C -- Yes --> E{Is the tag marked as immutable?}
|
C -- Yes --> E{Immutable tag check:<br/>Does tag match an<br/>immutable rule pattern?}
|
||||||
C -- No --> F[Tag is created successfully]
|
C -- No --> F[Tag is created successfully]
|
||||||
E -- Yes --> G[Push denied: Tag is immutable]
|
E -- Yes --> G[Push denied:<br/>Tag is immutable]
|
||||||
E -- No --> H[Tag is overwritten successfully]
|
E -- No --> H[Tag is overwritten successfully]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Example scenarios
|
||||||
|
|
||||||
|
For a project with these rules:
|
||||||
|
|
||||||
|
- Protected tag rule: Pattern `v.*` requires at least the Maintainer role.
|
||||||
|
- Immutable tag rule: Pattern `v\d+\.\d+\.\d+` protects semantic version tags.
|
||||||
|
|
||||||
|
| User role | Action | Protected tag check | Immutable tag check | Result |
|
||||||
|
|-----------|--------|-------------------|-------------------|---------|
|
||||||
|
| Developer | Push new tag `v1.0.0` | Denied | Not evaluated | Push denied. User lacks required role. |
|
||||||
|
| Maintainer | Push new tag `v1.0.0` | Allowed | Not evaluated | Tag created. |
|
||||||
|
| Maintainer | Overwrite existing tag `v1.0.0` | Allowed | Denied | Push denied. Tag is immutable. |
|
||||||
|
| Maintainer | Push new tag `v-beta` | Allowed | Not evaluated | Tag created. |
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
To use protected container tags, make sure the container registry is available:
|
To use immutable container tags, make sure the container registry is available:
|
||||||
|
|
||||||
- In GitLab.com, the container registry is enabled by default.
|
- In GitLab.com, the container registry is enabled by default.
|
||||||
- In GitLab Self-Managed, [enable the metadata database](../../../administration/packages/container_registry_metadata_database.md).
|
- In GitLab Self-Managed, [enable the metadata database](../../../administration/packages/container_registry_metadata_database.md).
|
||||||
|
|
|
@ -19,7 +19,7 @@ You can assign a topic to several projects.
|
||||||
|
|
||||||
For example, you can create and assign the topics `python` and `hackathon` to all projects that use Python and are intended for Hackathon contributions.
|
For example, you can create and assign the topics `python` and `hackathon` to all projects that use Python and are intended for Hackathon contributions.
|
||||||
|
|
||||||
Topics assigned to a project are displayed in the **Project overview** and [**Projects**](working_with_projects.md#view-all-projects-for-the-instance) lists, below the project information description.
|
Topics assigned to a project are displayed in the **Project overview** and [**Projects**](working_with_projects.md#view-projects) lists, below the project information description.
|
||||||
|
|
||||||
{{< alert type="note" >}}
|
{{< alert type="note" >}}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ In GitLab 17.5 and later, you can also use `https://gitlab.example.com/-/p/<id>`
|
||||||
|
|
||||||
## Find the Project ID
|
## Find the Project ID
|
||||||
|
|
||||||
You might also need the project ID if you want to interact with the project using the [GitLab API](../../api/_index.md).
|
You might need the project ID if you want to interact with the project using the [GitLab API](../../api/_index.md).
|
||||||
|
|
||||||
To find the project ID:
|
To find the project ID:
|
||||||
|
|
||||||
|
@ -76,101 +76,171 @@ To find the project ID:
|
||||||
1. On the project overview page, in the upper-right corner, select **Actions** ({{< icon name="ellipsis_v" >}}).
|
1. On the project overview page, in the upper-right corner, select **Actions** ({{< icon name="ellipsis_v" >}}).
|
||||||
1. Select **Copy project ID**.
|
1. Select **Copy project ID**.
|
||||||
|
|
||||||
## View all projects for the instance
|
## View projects
|
||||||
|
|
||||||
To view all projects for the GitLab instance:
|
Use the **Projects** list to view:
|
||||||
|
|
||||||
|
- All the projects on an instance
|
||||||
|
- The projects you work with or own
|
||||||
|
- Inactive projects, including archived projects and projects pending deletion
|
||||||
|
|
||||||
|
### View all projects on an instance
|
||||||
|
|
||||||
|
To view the projects on your GitLab instance:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
1. On the left sidebar, select **Search or go to**.
|
||||||
1. Select **Explore**.
|
1. Select **Explore**.
|
||||||
|
1. Optional. Select a tab to filter which projects are displayed.
|
||||||
On the left sidebar, **Projects** is selected.
|
|
||||||
A list of all projects for the instance is displayed.
|
|
||||||
|
|
||||||
If you are not authenticated, the list shows public projects only.
|
If you are not authenticated, the list shows public projects only.
|
||||||
|
|
||||||
## View projects you have contributed to
|
### View projects you work with
|
||||||
|
|
||||||
{{< history >}}
|
{{< history >}}
|
||||||
|
|
||||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13066) in GitLab 17.9 [with a flag](../../administration/feature_flags/_index.md) named `your_work_projects_vue`. Disabled by default.
|
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13066) in GitLab 17.9 [with a flag](../../administration/feature_flags/_index.md) named `your_work_projects_vue`. Disabled by default.
|
||||||
|
- [Changed](https://gitlab.com/groups/gitlab-org/-/epics/13066) tab label from **Yours** to **Member** in GitLab 17.9 [with a flag](../../administration/feature_flags/_index.md) named `your_work_projects_vue`. Disabled by default.
|
||||||
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/465889) in GitLab 17.10. Feature flag `your_work_projects_vue` removed.
|
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/465889) in GitLab 17.10. Feature flag `your_work_projects_vue` removed.
|
||||||
|
|
||||||
{{< /history >}}
|
{{< /history >}}
|
||||||
|
|
||||||
{{< alert type="flag" >}}
|
To view the projects you have interacted with:
|
||||||
|
|
||||||
The availability of this feature is controlled by a feature flag. For more information, see the history.
|
|
||||||
|
|
||||||
{{< /alert >}}
|
|
||||||
|
|
||||||
The **Contributed** tab displays projects where you have:
|
|
||||||
|
|
||||||
- Created issues, merge requests, or epics
|
|
||||||
- Commented on issues, merge requests, or epics
|
|
||||||
- Closed issues, merge requests, or epics
|
|
||||||
- Pushed commits
|
|
||||||
- Approved merge requests
|
|
||||||
- Merged merge requests
|
|
||||||
|
|
||||||
To view projects you have contributed to:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
1. On the left sidebar, select **Search or go to**.
|
||||||
1. Select **View all my projects**.
|
1. Select **View all my projects**.
|
||||||
1. Select the **Contributed** tab.
|
1. Optional. Select a tab to filter which projects are displayed:
|
||||||
|
- **Contributed**: Projects where you have:
|
||||||
|
- Created issues, merge requests, or epics
|
||||||
|
- Commented on issues, merge requests, or epics
|
||||||
|
- Closed issues, merge requests, or epics
|
||||||
|
- Pushed commits
|
||||||
|
- Approved merge requests
|
||||||
|
- Merged merge requests
|
||||||
|
- **Starred**: Projects you have [starred](#star-a-project)
|
||||||
|
- **Personal**: Projects created under your personal namespace
|
||||||
|
- **Member**: Projects you are a member of
|
||||||
|
- **Inactive**: Archived projects and projects pending deletion
|
||||||
|
|
||||||
## View projects you are a member of
|
You can also view your starred and personal projects from your personal profile:
|
||||||
|
|
||||||
|
1. On the left sidebar, select your avatar and then your username.
|
||||||
|
1. On the left sidebar, select **Starred projects** or **Personal projects**.
|
||||||
|
|
||||||
|
### View inactive projects
|
||||||
|
|
||||||
{{< history >}}
|
{{< history >}}
|
||||||
|
|
||||||
- [Changed](https://gitlab.com/groups/gitlab-org/-/epics/13066) tab label from "Yours" to "Member" in GitLab 17.9 [with a flag](../../administration/feature_flags/_index.md) named `your_work_projects_vue`. Disabled by default.
|
- [Changed](https://gitlab.com/groups/gitlab-org/-/epics/13066) tab label from "Pending deletion" to "Inactive" in GitLab 17.9 [with a flag](../../administration/feature_flags/_index.md) named `your_work_projects_vue`. Disabled by default.
|
||||||
- [Changed tab label generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/465889) in GitLab 17.10. Feature flag `your_work_projects_vue` removed.
|
- [Changed tab label generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/465889) in GitLab 17.10. Feature flag `your_work_projects_vue` removed.
|
||||||
|
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
|
||||||
|
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
|
||||||
|
|
||||||
{{< /history >}}
|
{{< /history >}}
|
||||||
|
|
||||||
To view projects you are a member of:
|
A project is inactive when:
|
||||||
|
|
||||||
|
- It is pending deletion.
|
||||||
|
- It has been archived.
|
||||||
|
|
||||||
|
To view all inactive projects:
|
||||||
|
|
||||||
|
1. Select either:
|
||||||
|
- **View all my projects**, to filter your projects.
|
||||||
|
- **Explore**, to filter all projects you can access.
|
||||||
|
1. Select the **Inactive** tab.
|
||||||
|
|
||||||
|
Each project in the list shows:
|
||||||
|
|
||||||
|
- A badge indicating that the project is archived or marked for deletion.
|
||||||
|
If the project is marked for deletion, the list also shows:
|
||||||
|
- The time the project was marked for deletion.
|
||||||
|
- The time the project is scheduled for final deletion.
|
||||||
|
- A **Restore** action to stop the project being eventually deleted.
|
||||||
|
|
||||||
|
### View only projects you own
|
||||||
|
|
||||||
|
To view only the projects you are the owner of:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
1. On the left sidebar, select **Search or go to**.
|
||||||
1. Select **View all my projects**.
|
1. Select either:
|
||||||
1. Select the **Yours** tab.
|
- **View all your projects**, to filter your projects.
|
||||||
|
- **Explore**, to filter all projects you can access.
|
||||||
|
1. Above the list of projects, select **Search or filter results**.
|
||||||
|
1. From the **Role** dropdown list, select **Owner**.
|
||||||
|
|
||||||
{{< alert type="note" >}}
|
## View project activity
|
||||||
|
|
||||||
This tab appears as **Member** when the `your_work_projects_vue` feature flag is enabled.
|
To view the activity of a project:
|
||||||
|
|
||||||
{{< /alert >}}
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
|
1. Select **Manage > Activity**.
|
||||||
|
1. Optional. To filter activity by contribution type, select a tab:
|
||||||
|
|
||||||
## View personal projects
|
- **All**: All contributions by project members.
|
||||||
|
- **Push events**: Push events in the project.
|
||||||
|
- **Merge events**: Accepted merge requests in the project.
|
||||||
|
- **Issue events**: Issues opened and closed in the project.
|
||||||
|
- **Comments**: Comments posted by project members.
|
||||||
|
- **Designs**: Designs added, updated, and removed in the project.
|
||||||
|
- **Team**: Members who joined and left the project.
|
||||||
|
|
||||||
Personal projects are projects created under your personal namespace.
|
GitLab removes project activity events older than three years from the events table for performance reasons.
|
||||||
|
|
||||||
For example, if you create an account with the username `alex`, and create a project
|
## Filter projects by language
|
||||||
called `my-project` under your username, the project is created at `https://gitlab.example.com/alex/my-project`.
|
|
||||||
|
|
||||||
To view your personal projects:
|
{{< history >}}
|
||||||
|
|
||||||
|
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385465) in GitLab 15.9 [with a flag](../../administration/feature_flags/_index.md) named `project_language_search`. Enabled by default.
|
||||||
|
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110956) in GitLab 15.9. Feature flag `project_language_search` removed.
|
||||||
|
|
||||||
|
{{< /history >}}
|
||||||
|
|
||||||
|
You can filter projects by the programming language they use. To do this:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
1. On the left sidebar, select **Search or go to**.
|
||||||
1. Select **View all my projects**.
|
1. Select either:
|
||||||
1. Select the **Personal** tab.
|
- **View all your projects**, to filter your projects.
|
||||||
|
- **Explore**, to filter all projects you can access.
|
||||||
|
1. Above the list of projects, select **Search or filter results**.
|
||||||
|
1. From the **Language** dropdown list, select the language you want to filter projects by.
|
||||||
|
|
||||||
Or
|
A list of projects that use the selected language is displayed.
|
||||||
|
|
||||||
1. On the left sidebar, select your avatar and then your username.
|
## Star a project
|
||||||
1. On the left sidebar, select **Personal projects**.
|
|
||||||
|
|
||||||
## View starred projects
|
You can star projects you use frequently to make them easier to find.
|
||||||
|
|
||||||
To view projects you have [starred](#star-a-project):
|
To star a project:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
1. Select **View all my projects**.
|
1. In the upper-right corner of the page, select **Star**.
|
||||||
1. Select the **Starred** tab.
|
|
||||||
|
|
||||||
Or
|
## Leave a project
|
||||||
|
|
||||||
1. On the left sidebar, select your avatar and then your username.
|
{{< history >}}
|
||||||
1. On the left sidebar, select **Starred projects**.
|
|
||||||
|
|
||||||
## Edit project name and description
|
- The button to leave a project [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/431539) to the Actions menu in GitLab 16.7.
|
||||||
|
|
||||||
|
{{< /history >}}
|
||||||
|
|
||||||
|
When you leave a project:
|
||||||
|
|
||||||
|
- You are no longer a project member and cannot contribute.
|
||||||
|
- All the issues and merge requests that were assigned
|
||||||
|
to you are unassigned.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You can leave a project this way only when a project is part of a group under a [group namespace](../namespace/_index.md).
|
||||||
|
- You must be a [direct member](members/_index.md#membership-types) of the project.
|
||||||
|
|
||||||
|
To leave a project:
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
|
1. On the project overview page, in the upper-right corner, select **Actions** ({{< icon name="ellipsis_v" >}}).
|
||||||
|
1. Select **Leave project**, then **Leave project** again.
|
||||||
|
|
||||||
|
## Edit a project
|
||||||
|
|
||||||
Use the project general settings to edit your project details.
|
Use the project general settings to edit your project details.
|
||||||
|
|
||||||
|
@ -185,16 +255,40 @@ Prerequisites:
|
||||||
Components published in the CI/CD catalog require a project description.
|
Components published in the CI/CD catalog require a project description.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
## Add a project avatar
|
### Rename a repository
|
||||||
|
|
||||||
|
A project's repository name defines its URL.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must be an administrator or have the Maintainer or Owner role for the project.
|
||||||
|
|
||||||
|
{{< alert type="note" >}}
|
||||||
|
|
||||||
|
When you change the repository path, users may experience issues if they push to, or pull from, the old URL.
|
||||||
|
For more information on redirect duration and its side-effects, see
|
||||||
|
[redirects when renaming repositories](repository/_index.md#repository-path-changes).
|
||||||
|
|
||||||
|
{{< /alert >}}
|
||||||
|
|
||||||
|
To rename a repository:
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
|
1. Select **Settings > General**.
|
||||||
|
1. Expand **Advanced**.
|
||||||
|
1. In the **Change path** text box, edit the path.
|
||||||
|
1. Select **Change path**.
|
||||||
|
|
||||||
|
### Add a project avatar
|
||||||
|
|
||||||
Add a project avatar to help visually identify your project. If you do not add an avatar, GitLab displays the first letter of your project name as the default project avatar.
|
Add a project avatar to help visually identify your project. If you do not add an avatar, GitLab displays the first letter of your project name as the default project avatar.
|
||||||
|
|
||||||
To add a project avatar, use one of the following methods:
|
To add a project avatar, use one of the following methods:
|
||||||
|
|
||||||
- [Add a logo](#add-a-logo-to-your-repository) to your repository.
|
- Add a logo to your repository.
|
||||||
- [Upload an avatar](#upload-an-avatar-in-project-settings) in your project settings.
|
- Upload an avatar in your project settings.
|
||||||
|
|
||||||
### Add a logo to your repository
|
#### Add a logo to your repository
|
||||||
|
|
||||||
If you haven't uploaded an avatar to your project settings, GitLab looks for a file named `logo` in your repository to use as the default project avatar.
|
If you haven't uploaded an avatar to your project settings, GitLab looks for a file named `logo` in your repository to use as the default project avatar.
|
||||||
|
|
||||||
|
@ -209,7 +303,7 @@ To add a logo file to use as your project avatar:
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
1. In the root of your project repository, upload the logo file.
|
1. In the root of your project repository, upload the logo file.
|
||||||
|
|
||||||
### Upload an avatar in project settings
|
#### Upload an avatar in project settings
|
||||||
|
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
|
|
||||||
|
@ -231,14 +325,138 @@ To upload an avatar in your project settings:
|
||||||
1. Select your avatar file.
|
1. Select your avatar file.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
## Star a project
|
## Delete a project
|
||||||
|
|
||||||
You can star projects you use frequently to make them easier to find.
|
{{< history >}}
|
||||||
|
|
||||||
To star a project:
|
- Default behavior [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/389557) to delayed project deletion for Premium and Ultimate tiers on [GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in 16.0.
|
||||||
|
- Option to delete projects immediately as a group setting removed [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0.
|
||||||
|
- Default behavior changed to delayed project deletion for [GitLab Free](https://gitlab.com/groups/gitlab-org/-/epics/17208) and [personal projects](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in 18.0.
|
||||||
|
- Option to delete projects immediately [moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
|
||||||
|
|
||||||
|
{{< /history >}}
|
||||||
|
|
||||||
|
You can schedule a project for deletion.
|
||||||
|
By default, when you delete a project for the first time, it enters a pending deletion state.
|
||||||
|
Delete a project again to remove it immediately.
|
||||||
|
|
||||||
|
On GitLab.com, after a project is deleted, its data is retained for 30 days.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for a project.
|
||||||
|
- Owners must be [allowed to delete projects](../../administration/settings/visibility_and_access_controls.md#restrict-project-deletion-to-administrators).
|
||||||
|
|
||||||
|
To delete a project:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
1. In the upper-right corner of the page, select **Star**.
|
1. Select **Settings > General**.
|
||||||
|
1. Expand **Advanced**.
|
||||||
|
1. In the **Delete project** section, select **Delete project**.
|
||||||
|
1. On the confirmation dialog, enter the project name and select **Yes, delete project**.
|
||||||
|
1. Optional. To delete the project immediately, repeat these steps.
|
||||||
|
|
||||||
|
You can also [delete projects using the Rails console](troubleshooting.md#delete-a-project-using-console).
|
||||||
|
|
||||||
|
If the user who scheduled the project deletion loses access to the project before the deletion occurs
|
||||||
|
(for example, by leaving the project, having their role downgraded, or being banned from the project),
|
||||||
|
the deletion job restores the project. However, if the user regains access before the deletion job runs,
|
||||||
|
the job removes the project permanently.
|
||||||
|
|
||||||
|
### Restore a project
|
||||||
|
|
||||||
|
{{< history >}}
|
||||||
|
|
||||||
|
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
|
||||||
|
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
|
||||||
|
|
||||||
|
{{< /history >}}
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the project.
|
||||||
|
|
||||||
|
To restore a project pending deletion:
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
|
1. Select **Settings > General**.
|
||||||
|
1. Expand **Advanced**.
|
||||||
|
1. In the **Restore project** section, select **Restore project**.
|
||||||
|
|
||||||
|
## Archive a project
|
||||||
|
|
||||||
|
{{< history >}}
|
||||||
|
|
||||||
|
- Pages removal [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343109) in GitLab 17.5.
|
||||||
|
|
||||||
|
{{< /history >}}
|
||||||
|
|
||||||
|
{{< alert type="note" >}}
|
||||||
|
|
||||||
|
When a project is archived, its fork relationship is removed and any open merge requests from forks
|
||||||
|
targeting this project are automatically closed.
|
||||||
|
|
||||||
|
{{< /alert >}}
|
||||||
|
|
||||||
|
When you archive a project, some features become read-only.
|
||||||
|
These features are still accessible, but not writable.
|
||||||
|
|
||||||
|
- Repository
|
||||||
|
- Packages
|
||||||
|
- Issues
|
||||||
|
- Merge requests
|
||||||
|
- Feature flags
|
||||||
|
- Pull mirroring
|
||||||
|
- All other project features
|
||||||
|
|
||||||
|
Active pipeline schedules of archived projects don't become read-only.
|
||||||
|
|
||||||
|
If the project has deployed Pages, they are removed along with any custom domains,
|
||||||
|
and the Pages link is no longer accessible.
|
||||||
|
|
||||||
|
Archived projects are:
|
||||||
|
|
||||||
|
- Labeled with an `archived` badge on the project page.
|
||||||
|
- Listed in the **Inactive** tab on the group page, **Your work** page, and **Explore** page.
|
||||||
|
- Read-only.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Deactivate](../../ci/pipelines/schedules.md#edit-a-pipeline-schedule) or delete any active pipeline schedules for the project.
|
||||||
|
<!-- LP: Remove this prerequisite after the issue is resolved (when a project is archived, active pipeline schedules continue to run). -->
|
||||||
|
|
||||||
|
To archive a project:
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
|
1. Select **Settings > General**.
|
||||||
|
1. Expand **Advanced**.
|
||||||
|
1. In the **Archive project** section, select **Archive project**.
|
||||||
|
1. To confirm, select **OK**.
|
||||||
|
|
||||||
|
### Unarchive a project
|
||||||
|
|
||||||
|
When you unarchive a project, the read-only restriction is removed,
|
||||||
|
and the project becomes available in project lists.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must be an administrator or have the Owner role for the project.
|
||||||
|
|
||||||
|
1. Find the archived project.
|
||||||
|
1. On the left sidebar, select **Search or go to**.
|
||||||
|
1. Select **View all my projects**.
|
||||||
|
1. Select **Explore projects**.
|
||||||
|
1. In the **Sort projects** dropdown list, select **Show archived projects**.
|
||||||
|
1. In the **Filter by name** field, enter the project name.
|
||||||
|
1. Select the project link.
|
||||||
|
1. On the left sidebar, select **Settings > General**.
|
||||||
|
1. Under **Advanced**, select **Expand**.
|
||||||
|
1. In the **Unarchive project** section, select **Unarchive project**.
|
||||||
|
1. To confirm, select **OK**.
|
||||||
|
|
||||||
|
The deployed Pages are not restored and you must rerun the pipeline.
|
||||||
|
|
||||||
|
When a project is unarchived, its pull mirroring process will automatically resume.
|
||||||
|
|
||||||
## Transfer a project
|
## Transfer a project
|
||||||
|
|
||||||
|
@ -325,280 +543,6 @@ When you transfer a project from a namespace licensed for GitLab.com Premium or
|
||||||
- [Pipeline subscriptions](../../ci/pipelines/_index.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt-deprecated)
|
- [Pipeline subscriptions](../../ci/pipelines/_index.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt-deprecated)
|
||||||
and [test cases](../../ci/test_cases/_index.md) are deleted.
|
and [test cases](../../ci/test_cases/_index.md) are deleted.
|
||||||
|
|
||||||
## Delete a project
|
|
||||||
|
|
||||||
{{< history >}}
|
|
||||||
|
|
||||||
- Default behavior [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/389557) to delayed project deletion for Premium and Ultimate tiers on [GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in 16.0.
|
|
||||||
- Option to delete projects immediately as a group setting removed [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0.
|
|
||||||
- Default behavior changed to delayed project deletion for [GitLab Free](https://gitlab.com/groups/gitlab-org/-/epics/17208) and [personal projects](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in 18.0.
|
|
||||||
- Option to delete projects immediately [moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
|
|
||||||
|
|
||||||
{{< /history >}}
|
|
||||||
|
|
||||||
You can schedule a project for deletion.
|
|
||||||
By default, when you delete a project for the first time, it enters a pending deletion state.
|
|
||||||
Delete a project again to remove it immediately.
|
|
||||||
|
|
||||||
On GitLab.com, after a project is deleted, its data is retained for seven days.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You must have the Owner role for a project.
|
|
||||||
- Owners must be [allowed to delete projects](../../administration/settings/visibility_and_access_controls.md#restrict-project-deletion-to-administrators).
|
|
||||||
|
|
||||||
To delete a project:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. Select **Settings > General**.
|
|
||||||
1. Expand **Advanced**.
|
|
||||||
1. In the **Delete project** section, select **Delete project**.
|
|
||||||
1. On the confirmation dialog, enter the project name and select **Yes, delete project**.
|
|
||||||
1. Optional. To delete the project immediately, repeat these steps.
|
|
||||||
|
|
||||||
You can also [delete projects using the Rails console](troubleshooting.md#delete-a-project-using-console).
|
|
||||||
|
|
||||||
If the user who scheduled the project deletion loses access to the project before the deletion occurs
|
|
||||||
(for example, by leaving the project, having their role downgraded, or being banned from the project),
|
|
||||||
the deletion job restores the project. However, if the user regains access before the deletion job runs,
|
|
||||||
the job removes the project permanently.
|
|
||||||
|
|
||||||
### View projects pending deletion
|
|
||||||
|
|
||||||
{{< history >}}
|
|
||||||
|
|
||||||
- [Changed](https://gitlab.com/groups/gitlab-org/-/epics/13066) tab label from "Pending deletion" to "Inactive" in GitLab 17.9 [with a flag](../../administration/feature_flags/_index.md) named `your_work_projects_vue`. Disabled by default.
|
|
||||||
- [Changed tab label generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/465889) in GitLab 17.10. Feature flag `your_work_projects_vue` removed.
|
|
||||||
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
|
|
||||||
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
|
|
||||||
|
|
||||||
{{< /history >}}
|
|
||||||
|
|
||||||
To view a list of all projects that are pending deletion:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
|
||||||
1. Select **View all my projects**.
|
|
||||||
1. Select the **Inactive** tab.
|
|
||||||
|
|
||||||
Each project in the list shows:
|
|
||||||
|
|
||||||
- A badge indicating that the project has been marked for deletion.
|
|
||||||
- The time the project was marked for deletion.
|
|
||||||
- The time the project is scheduled for final deletion.
|
|
||||||
- A **Restore** action to stop the project being eventually deleted.
|
|
||||||
|
|
||||||
### Restore a project
|
|
||||||
|
|
||||||
{{< history >}}
|
|
||||||
|
|
||||||
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
|
|
||||||
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
|
|
||||||
|
|
||||||
{{< /history >}}
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You must have the Owner role for the project.
|
|
||||||
|
|
||||||
To restore a project pending deletion:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. Select **Settings > General**.
|
|
||||||
1. Expand **Advanced**.
|
|
||||||
1. In the **Restore project** section, select **Restore project**.
|
|
||||||
|
|
||||||
## Archive a project
|
|
||||||
|
|
||||||
{{< history >}}
|
|
||||||
|
|
||||||
- Pages removal [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/343109) in GitLab 17.5.
|
|
||||||
|
|
||||||
{{< /history >}}
|
|
||||||
|
|
||||||
{{< alert type="note" >}}
|
|
||||||
|
|
||||||
When a project is archived, its fork relationship is removed and any open merge requests from forks
|
|
||||||
targeting this project are automatically closed.
|
|
||||||
|
|
||||||
{{< /alert >}}
|
|
||||||
|
|
||||||
When you archive a project, some features become read-only.
|
|
||||||
These features are still accessible, but not writable.
|
|
||||||
|
|
||||||
- Repository
|
|
||||||
- Packages
|
|
||||||
- Issues
|
|
||||||
- Merge requests
|
|
||||||
- Feature flags
|
|
||||||
- Pull mirroring
|
|
||||||
- All other project features
|
|
||||||
|
|
||||||
Active pipeline schedules of archived projects don't become read-only.
|
|
||||||
|
|
||||||
If the project has deployed Pages, they are removed along with any custom domains,
|
|
||||||
and the Pages link is no longer accessible.
|
|
||||||
|
|
||||||
Archived projects are:
|
|
||||||
|
|
||||||
- Labeled with an `archived` badge on the project page.
|
|
||||||
- Listed in the **Inactive** tab on the group page, **Your work** page, and **Explore** page.
|
|
||||||
- Read-only.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- [Deactivate](../../ci/pipelines/schedules.md#edit-a-pipeline-schedule) or delete any active pipeline schedules for the project.
|
|
||||||
<!-- LP: Remove this prerequisite after the issue is resolved (when a project is archived, active pipeline schedules continue to run). -->
|
|
||||||
|
|
||||||
To archive a project:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. Select **Settings > General**.
|
|
||||||
1. Expand **Advanced**.
|
|
||||||
1. In the **Archive project** section, select **Archive project**.
|
|
||||||
1. To confirm, select **OK**.
|
|
||||||
|
|
||||||
## Unarchive a project
|
|
||||||
|
|
||||||
When you unarchive a project, the read-only restriction is removed,
|
|
||||||
and the project becomes available in project lists.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You must be an administrator or have the Owner role for the project.
|
|
||||||
|
|
||||||
1. Find the archived project.
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
|
||||||
1. Select **View all my projects**.
|
|
||||||
1. Select **Explore projects**.
|
|
||||||
1. In the **Sort projects** dropdown list, select **Show archived projects**.
|
|
||||||
1. In the **Filter by name** field, enter the project name.
|
|
||||||
1. Select the project link.
|
|
||||||
1. On the left sidebar, select **Settings > General**.
|
|
||||||
1. Under **Advanced**, select **Expand**.
|
|
||||||
1. In the **Unarchive project** section, select **Unarchive project**.
|
|
||||||
1. To confirm, select **OK**.
|
|
||||||
|
|
||||||
The deployed Pages are not restored and you must rerun the pipeline.
|
|
||||||
|
|
||||||
When a project is unarchived, its pull mirroring process will automatically resume.
|
|
||||||
|
|
||||||
## View project activity
|
|
||||||
|
|
||||||
To view the activity of a project:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. Select **Manage > Activity**.
|
|
||||||
1. Optional. To filter activity by contribution type, select a tab:
|
|
||||||
|
|
||||||
- **All**: All contributions by project members.
|
|
||||||
- **Push events**: Push events in the project.
|
|
||||||
- **Merge events**: Accepted merge requests in the project.
|
|
||||||
- **Issue events**: Issues opened and closed in the project.
|
|
||||||
- **Comments**: Comments posted by project members.
|
|
||||||
- **Designs**: Designs added, updated, and removed in the project.
|
|
||||||
- **Team**: Members who joined and left the project.
|
|
||||||
|
|
||||||
### Event time period limit
|
|
||||||
|
|
||||||
GitLab removes project activity events older than 3 years from the events table for performance reasons.
|
|
||||||
|
|
||||||
## Search in projects
|
|
||||||
|
|
||||||
To search through your projects, on the left sidebar, select **Search or go to**.
|
|
||||||
GitLab filters as you type.
|
|
||||||
|
|
||||||
You can also look for the projects you [starred](#star-a-project) (**Starred projects**).
|
|
||||||
|
|
||||||
You can **Explore** all public and internal projects available in GitLab.com, from which you can filter by visibility,
|
|
||||||
through **Trending**, best rated with **Most stars**, or **All** of them.
|
|
||||||
|
|
||||||
You can sort projects by:
|
|
||||||
|
|
||||||
- Name
|
|
||||||
- Created date
|
|
||||||
- Updated date
|
|
||||||
- Stars
|
|
||||||
|
|
||||||
### Filter projects by language
|
|
||||||
|
|
||||||
{{< history >}}
|
|
||||||
|
|
||||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385465) in GitLab 15.9 [with a flag](../../administration/feature_flags/_index.md) named `project_language_search`. Enabled by default.
|
|
||||||
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110956) in GitLab 15.9. Feature flag `project_language_search` removed.
|
|
||||||
|
|
||||||
{{< /history >}}
|
|
||||||
|
|
||||||
You can filter projects by the programming language they use. To do this:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
|
||||||
1. Select either:
|
|
||||||
- **View all your projects**, to filter your projects.
|
|
||||||
- **Explore**, to filter all projects you can access.
|
|
||||||
1. Above the list of projects, select **Search or filter results**.
|
|
||||||
1. From the **Language** dropdown list, select the language you want to filter projects by.
|
|
||||||
|
|
||||||
A list of projects that use the selected language is displayed.
|
|
||||||
|
|
||||||
### View only projects you own
|
|
||||||
|
|
||||||
To view only the projects you are the owner of:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to**.
|
|
||||||
1. Select either:
|
|
||||||
- **View all your projects**, to filter your projects.
|
|
||||||
- **Explore**, to filter all projects you can access.
|
|
||||||
1. Above the list of projects, select **Search or filter results**.
|
|
||||||
1. From the **Role** dropdown list, select **Owner**.
|
|
||||||
|
|
||||||
## Rename a repository
|
|
||||||
|
|
||||||
A project's repository name defines its URL.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You must be an administrator or have the Maintainer or Owner role for the project.
|
|
||||||
|
|
||||||
{{< alert type="note" >}}
|
|
||||||
|
|
||||||
When you change the repository path, users may experience issues if they push to, or pull from, the old URL.
|
|
||||||
For more information on redirect duration and its side-effects, see
|
|
||||||
[redirects when renaming repositories](repository/_index.md#repository-path-changes).
|
|
||||||
|
|
||||||
{{< /alert >}}
|
|
||||||
|
|
||||||
To rename a repository:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. Select **Settings > General**.
|
|
||||||
1. Expand **Advanced**.
|
|
||||||
1. In the **Change path** text box, edit the path.
|
|
||||||
1. Select **Change path**.
|
|
||||||
|
|
||||||
## Leave a project
|
|
||||||
|
|
||||||
{{< history >}}
|
|
||||||
|
|
||||||
- The button to leave a project [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/431539) to the Actions menu in GitLab 16.7.
|
|
||||||
|
|
||||||
{{< /history >}}
|
|
||||||
|
|
||||||
When you leave a project:
|
|
||||||
|
|
||||||
- You are no longer a project member and cannot contribute.
|
|
||||||
- All the issues and merge requests that were assigned
|
|
||||||
to you are unassigned.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- You can leave a project this way only when a project is part of a group under a [group namespace](../namespace/_index.md).
|
|
||||||
- You must be a [direct member](members/_index.md#membership-types) of the project.
|
|
||||||
|
|
||||||
To leave a project:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. On the project overview page, in the upper-right corner, select **Actions** ({{< icon name="ellipsis_v" >}}).
|
|
||||||
1. Select **Leave project**, then **Leave project** again.
|
|
||||||
|
|
||||||
## Add a compliance framework to a project
|
## Add a compliance framework to a project
|
||||||
|
|
||||||
{{< details >}}
|
{{< details >}}
|
||||||
|
|
|
@ -16,12 +16,9 @@ rspec:
|
||||||
services:
|
services:
|
||||||
- name: postgres:${POSTGRES_VERSION}
|
- name: postgres:${POSTGRES_VERSION}
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||||
needs:
|
|
||||||
- project: $CI_PROJECT_PATH
|
|
||||||
job: "db:setup pg16"
|
|
||||||
ref: "master"
|
|
||||||
artifacts: true
|
|
||||||
before_script:
|
before_script:
|
||||||
|
- |
|
||||||
|
curl -o structure.sql -fsSL --retry 3 --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/files/db%2Fstructure.sql/raw?ref=master"
|
||||||
- echo -e "\e[0Ksection_start:`date +%s`:postgresql16\r\e[0KInstalling PostgreSQL 16"
|
- echo -e "\e[0Ksection_start:`date +%s`:postgresql16\r\e[0KInstalling PostgreSQL 16"
|
||||||
- curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc|gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
|
- curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc|gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
|
||||||
- echo "deb https://apt.postgresql.org/pub/repos/apt $(. /etc/os-release && echo "$VERSION_CODENAME")-pgdg main" > /etc/apt/sources.list.d/pgdg.list
|
- echo "deb https://apt.postgresql.org/pub/repos/apt $(. /etc/os-release && echo "$VERSION_CODENAME")-pgdg main" > /etc/apt/sources.list.d/pgdg.list
|
||||||
|
@ -29,7 +26,8 @@ rspec:
|
||||||
- echo -e "\e[0Ksection_end:`date +%s`:postgresql16\r\e[0K"
|
- echo -e "\e[0Ksection_end:`date +%s`:postgresql16\r\e[0K"
|
||||||
- psql -h postgres -U $POSTGRES_USER -c 'create database gitlabhq_test;'
|
- psql -h postgres -U $POSTGRES_USER -c 'create database gitlabhq_test;'
|
||||||
- psql -h postgres -U $POSTGRES_USER -c 'create database gitlabhq_ci_test;'
|
- psql -h postgres -U $POSTGRES_USER -c 'create database gitlabhq_ci_test;'
|
||||||
- psql -h postgres -U $POSTGRES_USER -q < pg_dumpall.sql > /dev/null
|
- psql -h postgres -U $POSTGRES_USER -d gitlabhq_test -q < structure.sql > /dev/null
|
||||||
|
- psql -h postgres -U $POSTGRES_USER -d gitlabhq_ci_test -q < structure.sql > /dev/null
|
||||||
- cp gems/gitlab-backup-cli/spec/fixtures/config/database.yml config/
|
- cp gems/gitlab-backup-cli/spec/fixtures/config/database.yml config/
|
||||||
- "sed -i \"s/username: postgres$/username: $POSTGRES_USER/g\" config/database.yml"
|
- "sed -i \"s/username: postgres$/username: $POSTGRES_USER/g\" config/database.yml"
|
||||||
- "sed -i \"s/password:\\s*$/password: $POSTGRES_PASSWORD/g\" config/database.yml"
|
- "sed -i \"s/password:\\s*$/password: $POSTGRES_PASSWORD/g\" config/database.yml"
|
||||||
|
|
|
@ -15,6 +15,8 @@ require_relative 'validation/fixers/missing_index'
|
||||||
require_relative 'validation/validators/different_definition_indexes'
|
require_relative 'validation/validators/different_definition_indexes'
|
||||||
require_relative 'validation/validators/extra_indexes'
|
require_relative 'validation/validators/extra_indexes'
|
||||||
require_relative 'validation/validators/missing_indexes'
|
require_relative 'validation/validators/missing_indexes'
|
||||||
|
|
||||||
|
require_relative 'validation/validators/different_sequence_owners'
|
||||||
require_relative 'validation/validators/missing_sequences'
|
require_relative 'validation/validators/missing_sequences'
|
||||||
|
|
||||||
require_relative 'validation/validators/extra_table_columns'
|
require_relative 'validation/validators/extra_table_columns'
|
||||||
|
|
|
@ -26,7 +26,9 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def statement
|
def statement
|
||||||
"CREATE SEQUENCE #{name}"
|
statements = "CREATE SEQUENCE #{name};"
|
||||||
|
statements += "\nALTER SEQUENCE #{name} OWNED BY #{owner}" if owner
|
||||||
|
statements
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -23,7 +23,8 @@ module Gitlab
|
||||||
DifferentDefinitionTables,
|
DifferentDefinitionTables,
|
||||||
DifferentDefinitionIndexes,
|
DifferentDefinitionIndexes,
|
||||||
DifferentDefinitionTriggers,
|
DifferentDefinitionTriggers,
|
||||||
DifferentDefinitionForeignKeys
|
DifferentDefinitionForeignKeys,
|
||||||
|
DifferentSequenceOwners
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module Schema
|
||||||
|
module Validation
|
||||||
|
module Validators
|
||||||
|
class DifferentSequenceOwners < Base
|
||||||
|
ERROR_MESSAGE = "The sequence %s has a different owner between structure.sql and database"
|
||||||
|
|
||||||
|
def execute
|
||||||
|
structure_sql.sequences.filter_map do |sequence|
|
||||||
|
database_sequence = database.fetch_sequence_by_name(sequence.name)
|
||||||
|
|
||||||
|
next if database_sequence.nil?
|
||||||
|
next if database_sequence.owner == sequence.owner
|
||||||
|
|
||||||
|
build_inconsistency(self.class, sequence, database_sequence)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,10 @@
|
||||||
CREATE SEQUENCE missing_sequence;
|
CREATE SEQUENCE missing_sequence;
|
||||||
CREATE SEQUENCE shared_audit_event_id_seq;
|
CREATE SEQUENCE shared_audit_event_id_seq;
|
||||||
CREATE SEQUENCE abuse_events_id_seq;
|
CREATE SEQUENCE abuse_events_id_seq;
|
||||||
|
CREATE SEQUENCE zoekt_repositories_id_seq;
|
||||||
|
|
||||||
|
ALTER SEQUENCE abuse_events_id_seq OWNED by abuse_events.id;
|
||||||
|
ALTER SEQUENCE zoekt_repositories_id_seq OWNED by zoekt_repositories.id;
|
||||||
|
|
||||||
CREATE INDEX missing_index ON events USING btree (created_at, author_id);
|
CREATE INDEX missing_index ON events USING btree (created_at, author_id);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ RSpec.describe Gitlab::Schema::Validation::Validators::Base, feature_category: :
|
||||||
Gitlab::Schema::Validation::Validators::DifferentDefinitionTables,
|
Gitlab::Schema::Validation::Validators::DifferentDefinitionTables,
|
||||||
Gitlab::Schema::Validation::Validators::DifferentDefinitionIndexes,
|
Gitlab::Schema::Validation::Validators::DifferentDefinitionIndexes,
|
||||||
Gitlab::Schema::Validation::Validators::DifferentDefinitionTriggers,
|
Gitlab::Schema::Validation::Validators::DifferentDefinitionTriggers,
|
||||||
Gitlab::Schema::Validation::Validators::DifferentDefinitionForeignKeys
|
Gitlab::Schema::Validation::Validators::DifferentDefinitionForeignKeys,
|
||||||
|
Gitlab::Schema::Validation::Validators::DifferentSequenceOwners
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::Schema::Validation::Validators::DifferentSequenceOwners, feature_category: :database do
|
||||||
|
wrong_sequence_owners = %w[
|
||||||
|
public.zoekt_repositories_id_seq
|
||||||
|
]
|
||||||
|
|
||||||
|
include_examples 'sequence validators', described_class, wrong_sequence_owners
|
||||||
|
end
|
|
@ -5,7 +5,6 @@ require 'spec_helper'
|
||||||
RSpec.describe Gitlab::Schema::Validation::Validators::MissingSequences, feature_category: :database do
|
RSpec.describe Gitlab::Schema::Validation::Validators::MissingSequences, feature_category: :database do
|
||||||
missing_sequences = %w[
|
missing_sequences = %w[
|
||||||
public.missing_sequence
|
public.missing_sequence
|
||||||
public.shared_audit_event_id_seq
|
|
||||||
public.abuse_events_id_seq
|
public.abuse_events_id_seq
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -4,30 +4,68 @@ require 'spec_helper'
|
||||||
|
|
||||||
RSpec.shared_examples 'sequence validators' do |validator, expected_result|
|
RSpec.shared_examples 'sequence validators' do |validator, expected_result|
|
||||||
let(:structure_file_path) { 'spec/fixtures/structure.sql' }
|
let(:structure_file_path) { 'spec/fixtures/structure.sql' }
|
||||||
let(:database_sequences) do
|
|
||||||
%w[
|
|
||||||
wrong_sequence
|
|
||||||
extra_sequence
|
|
||||||
shared_audit_event_id_seq
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:inconsistency_type) { validator.name }
|
let(:inconsistency_type) { validator.name }
|
||||||
let(:connection_class) { class_double(Class, name: 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter') }
|
let(:connection_class) { class_double(Class, name: 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter') }
|
||||||
# rubocop:disable RSpec/VerifiedDoubleReference
|
# rubocop:disable RSpec/VerifiedDoubleReference
|
||||||
let(:connection) do
|
let(:connection) do
|
||||||
instance_double('connection', class: connection_class, current_schema: 'public')
|
instance_double('connection', class: connection_class, exec_query: database_sequences, current_schema: 'public')
|
||||||
end
|
end
|
||||||
# rubocop:enable RSpec/VerifiedDoubleReference
|
# rubocop:enable RSpec/VerifiedDoubleReference
|
||||||
|
|
||||||
let(:schema) { 'public' }
|
let(:schema) { 'public' }
|
||||||
let(:database) { Gitlab::Schema::Validation::Sources::Database.new(connection) }
|
let(:database) { Gitlab::Schema::Validation::Sources::Database.new(connection) }
|
||||||
let(:structure_file) { Gitlab::Schema::Validation::Sources::StructureSql.new(structure_file_path, schema) }
|
let(:structure_file) { Gitlab::Schema::Validation::Sources::StructureSql.new(structure_file_path, schema) }
|
||||||
|
let(:database_sequences) do
|
||||||
before do
|
[
|
||||||
allow(database).to receive(:sequence_exists?) do |sequence_name|
|
{
|
||||||
database_sequences.include?(sequence_name)
|
'sequence_name' => 'wrong_sequence',
|
||||||
end
|
'schema' => schema,
|
||||||
|
'user_owner' => 'gitlab',
|
||||||
|
'start_value' => '1',
|
||||||
|
'increment_by' => '1',
|
||||||
|
'min_value' => '1',
|
||||||
|
'max_value' => '9223372036854775807',
|
||||||
|
'cycle' => 'f',
|
||||||
|
'cache_size' => '1',
|
||||||
|
'owned_by_column' => 'some_table.id'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'sequence_name' => 'extra_sequence',
|
||||||
|
'schema' => schema,
|
||||||
|
'user_owner' => 'gitlab',
|
||||||
|
'start_value' => '1',
|
||||||
|
'increment_by' => '1',
|
||||||
|
'min_value' => '1',
|
||||||
|
'max_value' => '9223372036854775807',
|
||||||
|
'cycle' => 'f',
|
||||||
|
'cache_size' => '1',
|
||||||
|
'owned_by_column' => 'extra_table.id'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'sequence_name' => 'zoekt_repositories_id_seq',
|
||||||
|
'schema' => schema,
|
||||||
|
'user_owner' => 'gitlab',
|
||||||
|
'start_value' => '1',
|
||||||
|
'increment_by' => '1',
|
||||||
|
'min_value' => '1',
|
||||||
|
'max_value' => '9223372036854775807',
|
||||||
|
'cycle' => 'f',
|
||||||
|
'cache_size' => '1',
|
||||||
|
'owned_by_column' => "wrong_table.id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'sequence_name' => 'shared_audit_event_id_seq',
|
||||||
|
'schema' => schema,
|
||||||
|
'user_owner' => 'gitlab',
|
||||||
|
'start_value' => '1',
|
||||||
|
'increment_by' => '1',
|
||||||
|
'min_value' => '1',
|
||||||
|
'max_value' => '9223372036854775807',
|
||||||
|
'cycle' => 'f',
|
||||||
|
'cache_size' => '1',
|
||||||
|
'owned_by_column' => nil
|
||||||
|
}
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
subject(:result) { validator.new(structure_file, database).execute }
|
subject(:result) { validator.new(structure_file, database).execute }
|
||||||
|
|
|
@ -8,17 +8,17 @@ module Sidebars
|
||||||
|
|
||||||
override :link
|
override :link
|
||||||
def link
|
def link
|
||||||
profile_chat_names_path
|
user_settings_integration_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
override :title
|
override :title
|
||||||
def title
|
def title
|
||||||
_('Chat')
|
s_('Integrations|Integration accounts')
|
||||||
end
|
end
|
||||||
|
|
||||||
override :sprite_icon
|
override :sprite_icon
|
||||||
def sprite_icon
|
def sprite_icon
|
||||||
'comment'
|
'connected'
|
||||||
end
|
end
|
||||||
|
|
||||||
override :active_routes
|
override :active_routes
|
||||||
|
|
|
@ -3548,9 +3548,6 @@ msgstr ""
|
||||||
msgid "Active Sessions"
|
msgid "Active Sessions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Active chat names"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Active group access tokens"
|
msgid "Active group access tokens"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -12728,9 +12725,6 @@ msgstr ""
|
||||||
msgid "Characters over limit"
|
msgid "Characters over limit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Chat"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
|
msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -18799,9 +18793,6 @@ msgstr ""
|
||||||
msgid "Could not apply iteration command. There are multiple cadences but no cadence is specified."
|
msgid "Could not apply iteration command. There are multiple cadences but no cadence is specified."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Could not authorize chat nickname. Try again!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Could not be moved. Select another project or try again."
|
msgid "Could not be moved. Select another project or try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -18826,7 +18817,7 @@ msgstr ""
|
||||||
msgid "Could not create wiki template"
|
msgid "Could not create wiki template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Could not delete chat nickname %{chat_name}."
|
msgid "Could not delete account nickname %{chat_name}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Could not delete the label %{labelName}. Please try again."
|
msgid "Could not delete the label %{labelName}. Please try again."
|
||||||
|
@ -21591,7 +21582,7 @@ msgstr ""
|
||||||
msgid "Deleted"
|
msgid "Deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Deleted chat nickname: %{chat_name}!"
|
msgid "Deleted account nickname: %{chat_name}!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Deleted commits:"
|
msgid "Deleted commits:"
|
||||||
|
@ -21633,7 +21624,7 @@ msgstr ""
|
||||||
msgid "DeletionSettings|Period that deleted groups and projects will remain restorable for."
|
msgid "DeletionSettings|Period that deleted groups and projects will remain restorable for."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Denied authorization of chat nickname %{user_name}."
|
msgid "Denied authorization of account nickname %{user_name}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Deny"
|
msgid "Deny"
|
||||||
|
@ -30389,6 +30380,9 @@ msgstr ""
|
||||||
msgid "Group Git LFS status:"
|
msgid "Group Git LFS status:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Group Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
|
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -30488,9 +30482,6 @@ msgstr ""
|
||||||
msgid "Group milestone"
|
msgid "Group milestone"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Group name"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Group name (your organization)"
|
msgid "Group name (your organization)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -33671,6 +33662,9 @@ msgstr ""
|
||||||
msgid "Integrations|Confirm %{type} exclusion removal"
|
msgid "Integrations|Confirm %{type} exclusion removal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Integrations|Connected integration accounts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|Connection details"
|
msgid "Integrations|Connection details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -33680,6 +33674,9 @@ msgstr ""
|
||||||
msgid "Integrations|Connection successful."
|
msgid "Integrations|Connection successful."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Integrations|Could not authorize integration account nickname. Try again!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|Create new issue in Jira"
|
msgid "Integrations|Create new issue in Jira"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -33758,6 +33755,9 @@ msgstr ""
|
||||||
msgid "Integrations|Instance-level integration management"
|
msgid "Integrations|Instance-level integration management"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Integrations|Integration accounts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|Integration cannot be reset."
|
msgid "Integrations|Integration cannot be reset."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -33770,6 +33770,9 @@ msgstr ""
|
||||||
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
|
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Integrations|Manage your integration accounts in GitLab. Use these connected integrations to perform actions in GitLab."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|Mattermost slash commands"
|
msgid "Integrations|Mattermost slash commands"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -33866,6 +33869,9 @@ msgstr ""
|
||||||
msgid "Integrations|You can use this alias in your Slack commands"
|
msgid "Integrations|You can use this alias in your Slack commands"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Integrations|You do not have any connected integration accounts."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|You haven't activated any integrations yet."
|
msgid "Integrations|You haven't activated any integrations yet."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -48460,6 +48466,9 @@ msgstr ""
|
||||||
msgid "Project ID"
|
msgid "Project ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Project Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Project Security Status"
|
msgid "Project Security Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -53232,6 +53241,9 @@ msgstr ""
|
||||||
msgid "Runners|Configuration"
|
msgid "Runners|Configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Runners|Container"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Runners|Containers"
|
msgid "Runners|Containers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -53648,6 +53660,9 @@ msgstr ""
|
||||||
msgid "Runners|Only administrators can view this."
|
msgid "Runners|Only administrators can view this."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Runners|Operating System"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Runners|Operating systems"
|
msgid "Runners|Operating systems"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -54151,6 +54166,9 @@ msgstr ""
|
||||||
msgid "Runners|View installation instructions"
|
msgid "Runners|View installation instructions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Runners|View instructions in %{helpLink}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Runners|View metrics"
|
msgid "Runners|View metrics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -54202,6 +54220,9 @@ msgstr ""
|
||||||
msgid "Runners|Zone must have the right format."
|
msgid "Runners|Zone must have the right format."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Runners|documentation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Runner|1 day selected"
|
msgid "Runner|1 day selected"
|
||||||
msgid_plural "Runner|%d days selected"
|
msgid_plural "Runner|%d days selected"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
|
@ -72607,9 +72628,6 @@ msgstr ""
|
||||||
msgid "You don't have any WebAuthn devices registered yet."
|
msgid "You don't have any WebAuthn devices registered yet."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "You don't have any active chat names."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "You don't have any applications."
|
msgid "You don't have any applications."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Search
|
|
||||||
# Cop that prevents checking migration_has_finished? on deprecated migrations
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
#
|
|
||||||
# # bad
|
|
||||||
# def disable_project_joins_for_blob?
|
|
||||||
# Elastic::DataMigrationService
|
|
||||||
# .migration_has_finished?(:backfill_archived_on_issues)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# def disable_project_joins_for_blob?
|
|
||||||
# Elastic::DataMigrationService.migration_has_finished?(:backfill_archived_on_issues)
|
|
||||||
# end
|
|
||||||
|
|
||||||
class AvoidCheckingFinishedOnDeprecatedMigrations < RuboCop::Cop::Base
|
|
||||||
MSG = 'Migration is deprecated and can not be used with `migration_has_finished?`.'
|
|
||||||
DEPRECATED_MIGRATIONS = [
|
|
||||||
:backfill_archived_on_issues
|
|
||||||
].freeze
|
|
||||||
|
|
||||||
def_node_matcher :deprecated_migration?, <<~PATTERN
|
|
||||||
(send
|
|
||||||
(const (const {nil? cbase} :Elastic) :DataMigrationService) :migration_has_finished?
|
|
||||||
(sym {#{DEPRECATED_MIGRATIONS.map { |m| ":#{m}" }.join(' ')}}))
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
RESTRICT_ON_SEND = %i[migration_has_finished?].freeze
|
|
||||||
|
|
||||||
def on_send(node)
|
|
||||||
add_offense(node) if deprecated_migration?(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Search
|
||||||
|
# Cop that prevents checking migration_has_finished? on obsolete or non-existing migrations
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad - obsolete migration
|
||||||
|
# def disable_project_joins_for_blob?
|
||||||
|
# Elastic::DataMigrationService
|
||||||
|
# .migration_has_finished?(:backfill_archived_on_issues)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # bad - non-existing migration
|
||||||
|
# def disable_project_joins_for_blob?
|
||||||
|
# Elastic::DataMigrationService
|
||||||
|
# .migration_has_finished?(:non_existing_migration)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good - valid migration
|
||||||
|
# def disable_project_joins_for_blob?
|
||||||
|
# Elastic::DataMigrationService.migration_has_finished?(:backfill_work_items_incorrect_data)
|
||||||
|
# end
|
||||||
|
|
||||||
|
class AvoidCheckingFinishedOnInvalidMigrations < RuboCop::Cop::Base
|
||||||
|
MSG_OBSOLETE = 'Migration is obsolete and can not be used with `migration_has_finished?`.'
|
||||||
|
MSG_NON_EXISTING = 'Migration does not exist and can not be used with `migration_has_finished?`.'
|
||||||
|
MSG_MISSING_IMPLEMENTATION = 'Migration implementation file is missing.'
|
||||||
|
|
||||||
|
DOCS_PATH = 'ee/elastic/docs'
|
||||||
|
MIGRATIONS_PATH = 'ee/elastic/migrate'
|
||||||
|
MIGRATION_REGEXP = /\A([0-9]+)_([_a-z0-9]*)\.rb\z/
|
||||||
|
|
||||||
|
# @!method migration_has_finished?(node)
|
||||||
|
def_node_matcher :migration_has_finished?, <<~PATTERN
|
||||||
|
(send
|
||||||
|
(const (const {nil? cbase} :Elastic) :DataMigrationService) :migration_has_finished?
|
||||||
|
(sym $_))
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
RESTRICT_ON_SEND = %i[migration_has_finished?].freeze
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
return unless migrations_available?
|
||||||
|
|
||||||
|
migration_has_finished?(node) do |migration_name|
|
||||||
|
check_migration(node, migration_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
alias_method :on_csend, :on_send
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def migrations_available?
|
||||||
|
Dir.exist?(DOCS_PATH) && Dir.exist?(MIGRATIONS_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_migration(node, migration_name)
|
||||||
|
migration_info = find_migration_info(migration_name)
|
||||||
|
|
||||||
|
if migration_info.nil?
|
||||||
|
add_offense(node, message: MSG_NON_EXISTING)
|
||||||
|
elsif migration_info[:obsolete]
|
||||||
|
add_offense(node, message: MSG_OBSOLETE)
|
||||||
|
elsif !migration_file_exists?(migration_name)
|
||||||
|
add_offense(node, message: MSG_MISSING_IMPLEMENTATION)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_migration_info(migration_name)
|
||||||
|
return @migration_cache[migration_name] if @migration_cache&.key?(migration_name)
|
||||||
|
|
||||||
|
@migration_cache ||= load_migrations
|
||||||
|
@migration_cache[migration_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def migration_file_exists?(migration_name)
|
||||||
|
migration_files_cache.include?(migration_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def migration_files_cache
|
||||||
|
@migration_files_cache ||= load_migration_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_migration_files
|
||||||
|
migration_files = Set.new
|
||||||
|
|
||||||
|
Dir.glob("#{MIGRATIONS_PATH}/*.rb").each do |file|
|
||||||
|
filename = File.basename(file, '.rb')
|
||||||
|
migration_files.add(::Regexp.last_match(1).to_sym) if filename =~ /\A[0-9]+_(.+)\z/
|
||||||
|
end
|
||||||
|
|
||||||
|
migration_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_migrations
|
||||||
|
migrations = {}
|
||||||
|
|
||||||
|
migration_files = Dir.glob("#{DOCS_PATH}/*.yml")
|
||||||
|
|
||||||
|
migration_files.each do |file|
|
||||||
|
yaml_content = YAML.safe_load_file(file)
|
||||||
|
next unless yaml_content.is_a?(Hash)
|
||||||
|
|
||||||
|
name = yaml_content['name']
|
||||||
|
next unless name
|
||||||
|
|
||||||
|
# Convert CamelCase to snake_case to match the symbol format used in code
|
||||||
|
snake_case_name = name.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
||||||
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
||||||
|
.downcase
|
||||||
|
.to_sym
|
||||||
|
|
||||||
|
migrations[snake_case_name] = {
|
||||||
|
obsolete: yaml_content['obsolete'] == true,
|
||||||
|
version: yaml_content['version'],
|
||||||
|
milestone: yaml_content['milestone']
|
||||||
|
}
|
||||||
|
rescue StandardError => e
|
||||||
|
# Skip files that can't be parsed, but log for debugging
|
||||||
|
warn "Warning: Could not parse migration documentation file #{file}: #{e.message}"
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
migrations
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,86 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Profiles::ChatNamesController, feature_category: :integrations do
|
||||||
|
let_it_be(:user) { create(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #create' do
|
||||||
|
let(:token) { 'valid_token' }
|
||||||
|
let(:chat_name_token_double) { instance_double(Gitlab::ChatNameToken) }
|
||||||
|
let(:chat_name_params) do
|
||||||
|
{
|
||||||
|
team_id: 'T123',
|
||||||
|
chat_id: 'U123',
|
||||||
|
chat_name: 'test_user'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(Gitlab::ChatNameToken).to receive(:new).with(token).and_return(chat_name_token_double)
|
||||||
|
allow(chat_name_token_double).to receive(:get).and_return(chat_name_params)
|
||||||
|
allow(chat_name_token_double).to receive(:delete)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when save succeeds' do
|
||||||
|
it 'sets success flash message and redirects' do
|
||||||
|
post :create, params: { token: token }
|
||||||
|
|
||||||
|
expect(flash[:notice]).to include('Authorized test_user')
|
||||||
|
expect(response).to redirect_to(user_settings_integration_accounts_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when save fails' do
|
||||||
|
it 'sets error flash message and redirects' do
|
||||||
|
allow_next_instance_of(ChatName) do |instance|
|
||||||
|
allow(instance).to receive(:save).and_return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
post :create, params: { token: token }
|
||||||
|
|
||||||
|
expect(flash[:alert]).to eq('Could not authorize integration account nickname. Try again!')
|
||||||
|
expect(response).to redirect_to(user_settings_integration_accounts_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE #destroy' do
|
||||||
|
let_it_be(:chat_name) { create(:chat_name, user: user) }
|
||||||
|
|
||||||
|
it 'destroys the chat_name' do
|
||||||
|
expect { delete :destroy, params: { id: chat_name.id } }
|
||||||
|
.to change { ChatName.count }.by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'redirects to the integration accounts page' do
|
||||||
|
delete :destroy, params: { id: chat_name.id }
|
||||||
|
|
||||||
|
expect(response).to redirect_to(user_settings_integration_accounts_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when destroy fails' do
|
||||||
|
it 'sets error flash message and redirects' do
|
||||||
|
mock_chat_name = instance_double(ChatName)
|
||||||
|
allow(mock_chat_name).to receive_messages(
|
||||||
|
destroy: false,
|
||||||
|
chat_name: chat_name.chat_name
|
||||||
|
)
|
||||||
|
|
||||||
|
# As chat_names_controller finds the real db object, #destroy would rarely fail naturally
|
||||||
|
# Hence, we're intercepting the controller-find process to return failing mock
|
||||||
|
allow(controller).to receive(:chat_names).and_return(user.chat_names)
|
||||||
|
allow(user.chat_names).to receive(:find).with(chat_name.id.to_s).and_return(mock_chat_name)
|
||||||
|
|
||||||
|
delete :destroy, params: { id: chat_name.id }
|
||||||
|
|
||||||
|
expect(flash[:alert]).to eq("Could not delete account nickname #{chat_name.chat_name}.")
|
||||||
|
expect(response).to redirect_to(user_settings_integration_accounts_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -138,7 +138,7 @@ RSpec.describe 'Database schema',
|
||||||
merge_requests_compliance_violations: %w[target_project_id],
|
merge_requests_compliance_violations: %w[target_project_id],
|
||||||
merge_request_diffs: %w[project_id],
|
merge_request_diffs: %w[project_id],
|
||||||
merge_request_diff_files: %w[project_id],
|
merge_request_diff_files: %w[project_id],
|
||||||
merge_request_diff_commits: %w[commit_author_id committer_id merge_request_commits_metadata_id],
|
merge_request_diff_commits: %w[project_id commit_author_id committer_id merge_request_commits_metadata_id],
|
||||||
# merge_request_diff_commits_b5377a7a34 is the temporary table for the merge_request_diff_commits partitioning
|
# merge_request_diff_commits_b5377a7a34 is the temporary table for the merge_request_diff_commits partitioning
|
||||||
# backfill. It will get foreign keys after the partitioning is finished.
|
# backfill. It will get foreign keys after the partitioning is finished.
|
||||||
merge_request_diff_commits_b5377a7a34: %w[merge_request_diff_id commit_author_id committer_id project_id],
|
merge_request_diff_commits_b5377a7a34: %w[merge_request_diff_id commit_author_id committer_id project_id],
|
||||||
|
|
|
@ -62,7 +62,7 @@ RSpec.describe 'Profile > Chat', feature_category: :integrations do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'goes to list of chat names and see chat account' do
|
it 'goes to list of chat names and see chat account' do
|
||||||
expect(page).to have_current_path(profile_chat_names_path, ignore_query: true)
|
expect(page).to have_current_path(user_settings_integration_accounts_path, ignore_query: true)
|
||||||
expect(page).to have_content('my_chat_team')
|
expect(page).to have_content('my_chat_team')
|
||||||
expect(page).to have_content('my_chat_user')
|
expect(page).to have_content('my_chat_user')
|
||||||
end
|
end
|
||||||
|
@ -80,7 +80,7 @@ RSpec.describe 'Profile > Chat', feature_category: :integrations do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'goes to list of chat names and do not see chat account' do
|
it 'goes to list of chat names and do not see chat account' do
|
||||||
expect(page).to have_current_path(profile_chat_names_path, ignore_query: true)
|
expect(page).to have_current_path(user_settings_integration_accounts_path, ignore_query: true)
|
||||||
expect(page).not_to have_content('my_chat_team')
|
expect(page).not_to have_content('my_chat_team')
|
||||||
expect(page).not_to have_content('my_chat_user')
|
expect(page).not_to have_content('my_chat_user')
|
||||||
end
|
end
|
||||||
|
@ -97,7 +97,7 @@ RSpec.describe 'Profile > Chat', feature_category: :integrations do
|
||||||
let_it_be(:chat_name) { create(:chat_name, user: user) }
|
let_it_be(:chat_name) { create(:chat_name, user: user) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
visit profile_chat_names_path
|
visit user_settings_integration_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sees chat user' do
|
it 'sees chat user' do
|
||||||
|
@ -108,7 +108,7 @@ RSpec.describe 'Profile > Chat', feature_category: :integrations do
|
||||||
it 'removes chat account' do
|
it 'removes chat account' do
|
||||||
click_link 'Remove'
|
click_link 'Remove'
|
||||||
|
|
||||||
expect(page).to have_content("You don't have any active chat names.")
|
expect(page).to have_content("You do not have any connected integration accounts.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -182,7 +182,7 @@ RSpec.describe "Compare", :js, feature_category: :source_code_management do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "compare view of tags" do
|
describe "compare view of tags" do
|
||||||
it "compares tags" do
|
it "compares tags", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/547846' do
|
||||||
visit project_compare_index_path(project, from: "master", to: "master")
|
visit project_compare_index_path(project, from: "master", to: "master")
|
||||||
|
|
||||||
select_using_dropdown "from", "v1.0.0"
|
select_using_dropdown "from", "v1.0.0"
|
||||||
|
|
|
@ -332,4 +332,20 @@ describe('GkeRegistrationInstructions', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when isWidget is true', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent({
|
||||||
|
props: { isWidget: true },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display h2 headings', () => {
|
||||||
|
expect(wrapper.find('h2').exists()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display token message', () => {
|
||||||
|
expect(findTokenMessage().exists()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -48,6 +48,7 @@ describe('GoogleCloudRegistrationInstructions', () => {
|
||||||
const findZoneLink = () => wrapper.findByTestId('zone-link');
|
const findZoneLink = () => wrapper.findByTestId('zone-link');
|
||||||
const findMachineTypeLink = () => wrapper.findByTestId('machine-types-link');
|
const findMachineTypeLink = () => wrapper.findByTestId('machine-types-link');
|
||||||
const findToken = () => wrapper.findByTestId('runner-token');
|
const findToken = () => wrapper.findByTestId('runner-token');
|
||||||
|
const findTokenMessage = () => wrapper.findByTestId('runner-token-message');
|
||||||
const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
|
const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
|
||||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||||
const findInstructionsButton = () => wrapper.findByTestId('show-instructions-button');
|
const findInstructionsButton = () => wrapper.findByTestId('show-instructions-button');
|
||||||
|
@ -327,4 +328,20 @@ describe('GoogleCloudRegistrationInstructions', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when isWidget is true', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent({
|
||||||
|
props: { isWidget: true },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display h2 headings', () => {
|
||||||
|
expect(wrapper.find('h2').exists()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display token message', () => {
|
||||||
|
expect(findTokenMessage().exists()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -82,6 +82,7 @@ describe('RegistrationInstructions', () => {
|
||||||
propsData: {
|
propsData: {
|
||||||
runnerId: mockRunnerId,
|
runnerId: mockRunnerId,
|
||||||
platform: DEFAULT_PLATFORM,
|
platform: DEFAULT_PLATFORM,
|
||||||
|
isWidget: false,
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
stubs: {
|
stubs: {
|
||||||
|
@ -360,6 +361,7 @@ describe('RegistrationInstructions', () => {
|
||||||
token: mockAuthenticationToken,
|
token: mockAuthenticationToken,
|
||||||
groupPath: 'mock/group/path',
|
groupPath: 'mock/group/path',
|
||||||
projectPath: null,
|
projectPath: null,
|
||||||
|
isWidget: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -377,6 +379,7 @@ describe('RegistrationInstructions', () => {
|
||||||
token: mockAuthenticationToken,
|
token: mockAuthenticationToken,
|
||||||
projectPath: 'mock/project/path',
|
projectPath: 'mock/project/path',
|
||||||
groupPath: null,
|
groupPath: null,
|
||||||
|
isWidget: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -412,6 +415,7 @@ describe('RegistrationInstructions', () => {
|
||||||
token: mockAuthenticationToken,
|
token: mockAuthenticationToken,
|
||||||
groupPath: 'mock/group/path',
|
groupPath: 'mock/group/path',
|
||||||
projectPath: null,
|
projectPath: null,
|
||||||
|
isWidget: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -429,6 +433,7 @@ describe('RegistrationInstructions', () => {
|
||||||
token: mockAuthenticationToken,
|
token: mockAuthenticationToken,
|
||||||
projectPath: 'mock/project/path',
|
projectPath: 'mock/project/path',
|
||||||
groupPath: null,
|
groupPath: null,
|
||||||
|
isWidget: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { GlSprintf } from '@gitlab/ui';
|
||||||
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
|
import WizardOperatingSystemInstruction from '~/ci/runner/components/registration/wizard_operating_system_instruction.vue';
|
||||||
|
import PlatformsDrawer from '~/ci/runner/components/registration/platforms_drawer.vue';
|
||||||
|
import CliCommand from '~/ci/runner/components/registration/cli_command.vue';
|
||||||
|
import { EXECUTORS_HELP_URL, SERVICE_COMMANDS_HELP_URL } from '~/ci/runner/constants';
|
||||||
|
|
||||||
|
describe('New Runner Registration Operation Systems Instructions', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const createComponent = () => {
|
||||||
|
wrapper = shallowMountExtended(WizardOperatingSystemInstruction, {
|
||||||
|
propsData: {
|
||||||
|
token: 'token-123',
|
||||||
|
title: 'Linux',
|
||||||
|
platform: 'linux',
|
||||||
|
},
|
||||||
|
stubs: {
|
||||||
|
GlSprintf,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent();
|
||||||
|
});
|
||||||
|
|
||||||
|
const findPlatformsDrawer = () => wrapper.findComponent(PlatformsDrawer);
|
||||||
|
const findStep1Section = () => wrapper.findByTestId('step-1');
|
||||||
|
const findStep2Section = () => wrapper.findByTestId('step-2');
|
||||||
|
const findStep3Section = () => wrapper.findByTestId('step-3');
|
||||||
|
const findExecutorsHelpLink = () => wrapper.findByTestId('executors-help-link');
|
||||||
|
const findServiceCommandsHelpLink = () => wrapper.findByTestId('service-commands-help-link');
|
||||||
|
|
||||||
|
describe('platform installation drawer instructions', () => {
|
||||||
|
it('opens and closes the drawer', async () => {
|
||||||
|
expect(findPlatformsDrawer().props('open')).toBe(false);
|
||||||
|
|
||||||
|
expect(wrapper.findByTestId('how-to-install-btn').exists()).toBe(true);
|
||||||
|
|
||||||
|
await wrapper.findByTestId('how-to-install-btn').vm.$emit('click');
|
||||||
|
expect(findPlatformsDrawer().props('open')).toBe(true);
|
||||||
|
|
||||||
|
await findPlatformsDrawer().vm.$emit('close');
|
||||||
|
expect(findPlatformsDrawer().props('open')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders step 1', () => {
|
||||||
|
expect(findStep1Section().findComponent(CliCommand).props()).toMatchObject({
|
||||||
|
command: ['gitlab-runner register', ` --url ${TEST_HOST}`, ` --token token-123`],
|
||||||
|
prompt: '$',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders step 2', () => {
|
||||||
|
expect(findStep2Section().exists()).toBe(true);
|
||||||
|
expect(findExecutorsHelpLink().attributes('href')).toBe(EXECUTORS_HELP_URL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders step 3', () => {
|
||||||
|
expect(findStep3Section().findComponent(CliCommand).props()).toMatchObject({
|
||||||
|
command: 'gitlab-runner run',
|
||||||
|
prompt: '$',
|
||||||
|
});
|
||||||
|
expect(findServiceCommandsHelpLink().attributes('href')).toBe(SERVICE_COMMANDS_HELP_URL);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1611,7 +1611,7 @@ RSpec.describe GitlabSchema.types['Project'], feature_category: :groups_and_proj
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'fields with :ai_workflows scope' do
|
describe 'fields with :ai_workflows scope' do
|
||||||
%w[id fullPath workItems].each do |field_name|
|
%w[id fullPath workItems languages].each do |field_name|
|
||||||
it "includes :ai_workflows scope for the #{field_name} field" do
|
it "includes :ai_workflows scope for the #{field_name} field" do
|
||||||
field = described_class.fields[field_name]
|
field = described_class.fields[field_name]
|
||||||
expect(field.instance_variable_get(:@scopes)).to include(:ai_workflows)
|
expect(field.instance_variable_get(:@scopes)).to include(:ai_workflows)
|
||||||
|
|
|
@ -12,4 +12,19 @@ RSpec.describe Types::Projects::RepositoryLanguageType do
|
||||||
:color
|
:color
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.authorization_scopes' do
|
||||||
|
it 'allows ai_workflows scope token' do
|
||||||
|
expect(described_class.authorization_scopes).to include(:ai_workflows)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'fields with :ai_workflows scope' do
|
||||||
|
%w[name share].each do |field_name|
|
||||||
|
it "includes :ai_workflows scope for the #{field_name} field" do
|
||||||
|
field = described_class.fields[field_name]
|
||||||
|
expect(field.instance_variable_get(:@scopes)).to include(:ai_workflows)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -929,6 +929,7 @@ project:
|
||||||
- approval_policies
|
- approval_policies
|
||||||
- project_requirement_compliance_statuses
|
- project_requirement_compliance_statuses
|
||||||
- analyzer_statuses
|
- analyzer_statuses
|
||||||
|
- configured_ai_catalog_items
|
||||||
award_emoji:
|
award_emoji:
|
||||||
- awardable
|
- awardable
|
||||||
- user
|
- user
|
||||||
|
|
|
@ -4,9 +4,9 @@ require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Sidebars::UserSettings::Menus::ChatMenu, feature_category: :navigation do
|
RSpec.describe Sidebars::UserSettings::Menus::ChatMenu, feature_category: :navigation do
|
||||||
it_behaves_like 'User settings menu',
|
it_behaves_like 'User settings menu',
|
||||||
link: '/-/profile/chat',
|
link: '/-/user_settings/integration_accounts',
|
||||||
title: _('Chat'),
|
title: _('Integration accounts'),
|
||||||
icon: 'comment',
|
icon: 'connected',
|
||||||
active_routes: { controller: :chat_names }
|
active_routes: { controller: :chat_names }
|
||||||
|
|
||||||
it_behaves_like 'User settings menu #render? method'
|
it_behaves_like 'User settings menu #render? method'
|
||||||
|
|
|
@ -26,7 +26,7 @@ RSpec.describe Slack::BlockKit::AppHomeOpened, feature_category: :integrations d
|
||||||
{
|
{
|
||||||
type: 'button',
|
type: 'button',
|
||||||
text: include({ text: 'Connect your GitLab account' }),
|
text: include({ text: 'Connect your GitLab account' }),
|
||||||
url: include(Gitlab::Routing.url_helpers.new_profile_chat_name_url)
|
url: include(Gitlab::Routing.url_helpers.new_user_settings_integration_account_url)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rubocop_spec_helper'
|
|
||||||
require_relative '../../../../rubocop/cop/search/avoid_checking_finished_on_deprecated_migrations'
|
|
||||||
|
|
||||||
RSpec.describe RuboCop::Cop::Search::AvoidCheckingFinishedOnDeprecatedMigrations, feature_category: :global_search do
|
|
||||||
context 'when a deprecated class is used with migration_has_finished?' do
|
|
||||||
it 'flags it as an offense' do
|
|
||||||
expect_offense <<~SOURCE
|
|
||||||
return if Elastic::DataMigrationService.migration_has_finished?(:backfill_archived_on_issues)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Migration is deprecated and can not be used with `migration_has_finished?`.
|
|
||||||
SOURCE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when a non deprecated class is used with migration_has_finished?' do
|
|
||||||
it 'does not flag it as an offense' do
|
|
||||||
expect_no_offenses <<~SOURCE
|
|
||||||
return if Elastic::DataMigrationService.migration_has_finished?(:backfill_project_permissions_in_blobs)
|
|
||||||
SOURCE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when migration_has_finished? method is called on another class' do
|
|
||||||
it 'does not flag it as an offense' do
|
|
||||||
expect_no_offenses <<~SOURCE
|
|
||||||
return if Klass.migration_has_finished?(:backfill_archived_on_issues)
|
|
||||||
SOURCE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rubocop_spec_helper'
|
||||||
|
require_relative '../../../../rubocop/cop/search/avoid_checking_finished_on_invalid_migrations'
|
||||||
|
|
||||||
|
RSpec.describe RuboCop::Cop::Search::AvoidCheckingFinishedOnInvalidMigrations, feature_category: :global_search do
|
||||||
|
# Only run these tests if the migration directories are present
|
||||||
|
if Dir.exist?('ee/elastic/docs') && Dir.exist?('ee/elastic/migrate')
|
||||||
|
context 'when an obsolete migration is used with migration_has_finished?' do
|
||||||
|
it 'flags it as an offense' do
|
||||||
|
expect_offense <<~RUBY
|
||||||
|
return if Elastic::DataMigrationService.migration_has_finished?(:backfill_archived_on_issues)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Migration is obsolete and can not be used with `migration_has_finished?`.
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a non-existing migration is used with migration_has_finished?' do
|
||||||
|
it 'flags it as an offense' do
|
||||||
|
expect_offense <<~RUBY
|
||||||
|
return if Elastic::DataMigrationService.migration_has_finished?(:non_existing_migration)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Migration does not exist and can not be used with `migration_has_finished?`.
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a valid migration is used with migration_has_finished?' do
|
||||||
|
it 'does not flag it as an offense' do
|
||||||
|
expect_no_offenses <<~RUBY
|
||||||
|
return if Elastic::DataMigrationService.migration_has_finished?(:backfill_work_items_incorrect_data)
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when an obsolete migration (that was documented) is used' do
|
||||||
|
it 'flags it as an offense' do
|
||||||
|
expect_offense <<~RUBY
|
||||||
|
return if Elastic::DataMigrationService.migration_has_finished?(:apply_max_analyzed_offset)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Migration is obsolete and can not be used with `migration_has_finished?`.
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when migration_has_finished? method is called on another class' do
|
||||||
|
it 'does not flag it as an offense' do
|
||||||
|
expect_no_offenses <<~RUBY
|
||||||
|
return if Klass.migration_has_finished?(:backfill_archived_on_issues)
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when migration exists in docs but missing implementation file' do
|
||||||
|
it 'flags it as an offense' do
|
||||||
|
# Mock the migration info to exist but file to be missing
|
||||||
|
allow(cop).to receive_messages(
|
||||||
|
find_migration_info: { obsolete: false, version: '1.0', milestone: '14.0' },
|
||||||
|
migration_file_exists?: false
|
||||||
|
)
|
||||||
|
|
||||||
|
expect_offense <<~RUBY
|
||||||
|
return if Elastic::DataMigrationService.migration_has_finished?(:missing_implementation)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Migration implementation file is missing.
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when YAML parsing fails' do
|
||||||
|
it 'handles errors gracefully' do
|
||||||
|
# Mock Dir.glob to return a file that will cause YAML parsing to fail
|
||||||
|
allow(Dir).to receive(:glob).with('ee/elastic/docs/*.yml').and_return(['invalid_file.yml'])
|
||||||
|
allow(YAML).to receive(:safe_load_file).and_raise(StandardError.new('Invalid YAML'))
|
||||||
|
|
||||||
|
# Capture the warning message
|
||||||
|
expect { cop.send(:load_migrations) }.to output(
|
||||||
|
/Warning: Could not parse migration documentation file/
|
||||||
|
).to_stderr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue