Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-22 15:09:52 +00:00
parent ae567e129f
commit 4136fdda4c
125 changed files with 1447 additions and 979 deletions

View File

@ -3,8 +3,6 @@
mutation createHttpIntegration($projectPath: ID!, $name: String!, $active: Boolean!) {
httpIntegrationCreate(input: { projectPath: $projectPath, name: $name, active: $active }) {
errors
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}

View File

@ -3,8 +3,6 @@
mutation destroyHttpIntegration($id: ID!) {
httpIntegrationDestroy(input: { id: $id }) {
errors
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}

View File

@ -3,8 +3,6 @@
mutation resetHttpIntegrationToken($id: ID!) {
httpIntegrationResetToken(input: { id: $id }) {
errors
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}

View File

@ -3,8 +3,6 @@
mutation updateHttpIntegration($id: ID!, $name: String!, $active: Boolean!) {
httpIntegrationUpdate(input: { id: $id, name: $name, active: $active }) {
errors
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}

View File

@ -2,8 +2,6 @@
mutation createBoardList($boardId: BoardID!, $backlog: Boolean, $labelId: LabelID) {
boardListCreate(input: { boardId: $boardId, backlog: $backlog, labelId: $labelId }) {
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
list {
...BoardListFragment
}

View File

@ -2,8 +2,6 @@
mutation UpdateBoardList($listId: ID!, $position: Int, $collapsed: Boolean) {
updateBoardList(input: { listId: $listId, position: $position, collapsed: $collapsed }) {
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
list {
...BoardListFragment
}

View File

@ -13,8 +13,6 @@ query BoardLists(
id
hideBacklogList
lists(issueFilters: $filters) {
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...BoardListFragment
}
@ -27,8 +25,6 @@ query BoardLists(
id
hideBacklogList
lists(issueFilters: $filters) {
# We have ID in a deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...BoardListFragment
}

View File

@ -9,11 +9,11 @@ import {
} from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { getParentByTagName } from '~/lib/utils/dom_utils';
import codeBlockLanguageLoader from '../services/code_block_language_loader';
import CodeBlockHighlight from '../extensions/code_block_highlight';
import Diagram from '../extensions/diagram';
import Frontmatter from '../extensions/frontmatter';
import EditorStateObserver from './editor_state_observer.vue';
import codeBlockLanguageLoader from '../../services/code_block_language_loader';
import CodeBlockHighlight from '../../extensions/code_block_highlight';
import Diagram from '../../extensions/diagram';
import Frontmatter from '../../extensions/frontmatter';
import EditorStateObserver from '../editor_state_observer.vue';
const CODE_BLOCK_NODE_TYPES = [CodeBlockHighlight.name, Diagram.name, Frontmatter.name];

View File

@ -1,13 +1,13 @@
<script>
import { GlButtonGroup } from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { BUBBLE_MENU_TRACKING_ACTION } from '../constants';
import trackUIControl from '../services/track_ui_control';
import Code from '../extensions/code';
import CodeBlockHighlight from '../extensions/code_block_highlight';
import Diagram from '../extensions/diagram';
import Frontmatter from '../extensions/frontmatter';
import ToolbarButton from './toolbar_button.vue';
import { BUBBLE_MENU_TRACKING_ACTION } from '../../constants';
import trackUIControl from '../../services/track_ui_control';
import Code from '../../extensions/code';
import CodeBlockHighlight from '../../extensions/code_block_highlight';
import Diagram from '../../extensions/diagram';
import Frontmatter from '../../extensions/frontmatter';
import ToolbarButton from '../toolbar_button.vue';
export default {
components: {

View File

@ -4,8 +4,8 @@ import { createContentEditor } from '../services/create_content_editor';
import ContentEditorAlert from './content_editor_alert.vue';
import ContentEditorProvider from './content_editor_provider.vue';
import EditorStateObserver from './editor_state_observer.vue';
import FormattingBubbleMenu from './formatting_bubble_menu.vue';
import CodeBlockBubbleMenu from './code_block_bubble_menu.vue';
import FormattingBubbleMenu from './bubble_menus/formatting.vue';
import CodeBlockBubbleMenu from './bubble_menus/code_block.vue';
import TopToolbar from './top_toolbar.vue';
import LoadingIndicator from './loading_indicator.vue';

View File

@ -1,3 +0,0 @@
<template>
<span class="gl-mx-3 gl-border-r-solid gl-border-r-1 gl-border-gray-200"></span>
</template>

View File

@ -42,7 +42,7 @@ export default {
size: {
type: String,
required: false,
default: 'small',
default: 'medium',
},
},
data() {

View File

@ -1,6 +1,5 @@
<script>
import trackUIControl from '../services/track_ui_control';
import Divider from './divider.vue';
import ToolbarButton from './toolbar_button.vue';
import ToolbarImageButton from './toolbar_image_button.vue';
import ToolbarLinkButton from './toolbar_link_button.vue';
@ -14,7 +13,6 @@ export default {
ToolbarLinkButton,
ToolbarTableButton,
ToolbarImageButton,
Divider,
},
methods: {
trackToolbarControlExecution({ contentType, value }) {
@ -25,13 +23,13 @@ export default {
</script>
<template>
<div
class="gl-display-flex gl-justify-content-end gl-pb-3 gl-pt-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
class="gl-display-flex gl-flex-wrap gl-pb-3 gl-pt-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
>
<toolbar-text-style-dropdown
data-testid="text-styles"
class="gl-mr-3"
@execute="trackToolbarControlExecution"
/>
<divider />
<toolbar-button
data-testid="bold"
content-type="bold"
@ -69,7 +67,6 @@ export default {
@execute="trackToolbarControlExecution"
/>
<toolbar-link-button data-testid="link" @execute="trackToolbarControlExecution" />
<divider />
<toolbar-image-button
ref="imageButton"
data-testid="image"

View File

@ -3,7 +3,6 @@
mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
designManagementUpload(input: { projectPath: $projectPath, iid: $iid, files: $files }) {
# eslint-disable-next-line @graphql-eslint/require-id-when-available
designs {
...DesignItem
versions {

View File

@ -13,7 +13,6 @@ query getDesign(
id
designCollection {
designs(atVersion: $atVersion, filenames: $filenames) {
# eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...DesignItem
issue {

View File

@ -1,4 +1,5 @@
fragment TimelogFragment on Timelog {
id
timeSpent
user {
id

View File

@ -1,4 +1,3 @@
# eslint-disable-next-line @graphql-eslint/require-id-when-available
fragment UserAvailability on User {
status {
availability

View File

@ -1,4 +1,3 @@
# eslint-disable-next-line @graphql-eslint/require-id-when-available
fragment IncidentFields on Issue {
severity
escalationStatus

View File

@ -54,15 +54,15 @@ export default {
return {
message: this.defaultMessage,
openMergeRequest: false,
targetBranch: this.currentBranch,
sourceBranch: this.currentBranch,
};
},
computed: {
isCommitFormFilledOut() {
return this.message && this.targetBranch;
return this.message && this.sourceBranch;
},
isCurrentBranchTarget() {
return this.targetBranch === this.currentBranch;
isCurrentBranchSourceBranch() {
return this.sourceBranch === this.currentBranch;
},
isSubmitDisabled() {
return !this.isCommitFormFilledOut || (!this.hasUnsavedChanges && !this.isNewCiConfigFile);
@ -79,7 +79,7 @@ export default {
onSubmit() {
this.$emit('submit', {
message: this.message,
targetBranch: this.targetBranch,
sourceBranch: this.sourceBranch,
openMergeRequest: this.openMergeRequest,
});
},
@ -93,7 +93,7 @@ export default {
},
i18n: {
commitMessage: __('Commit message'),
targetBranch: __('Target Branch'),
sourceBranch: __('Branch'),
startMergeRequest: __('Start a %{new_merge_request} with these changes'),
newMergeRequest: __('new merge request'),
commitChanges: __('Commit changes'),
@ -120,20 +120,20 @@ export default {
/>
</gl-form-group>
<gl-form-group
id="target-branch-group"
:label="$options.i18n.targetBranch"
id="source-branch-group"
:label="$options.i18n.sourceBranch"
label-cols-sm="2"
label-for="target-branch-field"
label-for="source-branch-field"
>
<gl-form-input
id="target-branch-field"
v-model="targetBranch"
id="source-branch-field"
v-model="sourceBranch"
class="gl-font-monospace!"
required
data-qa-selector="target_branch_field"
data-qa-selector="source_branch_field"
/>
<gl-form-checkbox
v-if="!isCurrentBranchTarget"
v-if="!isCurrentBranchSourceBranch"
v-model="openMergeRequest"
data-testid="new-mr-checkbox"
data-qa-selector="new_mr_checkbox"

View File

@ -75,7 +75,7 @@ export default {
},
},
methods: {
async onCommitSubmit({ message, targetBranch, openMergeRequest }) {
async onCommitSubmit({ message, sourceBranch, openMergeRequest }) {
this.isSaving = true;
try {
@ -88,7 +88,7 @@ export default {
variables: {
action: this.action,
projectPath: this.projectFullPath,
branch: targetBranch,
branch: sourceBranch,
startBranch: this.currentBranch,
message,
filePath: this.ciConfigPath,
@ -104,12 +104,11 @@ export default {
if (errors?.length) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: errors });
} else {
const commitBranch = targetBranch;
const params = openMergeRequest
? {
type: COMMIT_SUCCESS_WITH_REDIRECT,
params: {
sourceBranch: commitBranch,
sourceBranch,
targetBranch: this.currentBranch,
},
}
@ -119,10 +118,10 @@ export default {
...params,
});
this.updateLastCommitBranch(targetBranch);
this.updateCurrentBranch(targetBranch);
this.updateLastCommitBranch(sourceBranch);
this.updateCurrentBranch(sourceBranch);
if (this.currentBranch === targetBranch) {
if (this.currentBranch === sourceBranch) {
this.$emit('updateCommitSha');
}
}

View File

@ -1,8 +1,6 @@
#import "ee_else_ce/runner/graphql/details/runner_details.fragment.graphql"
query getRunner($id: CiRunnerID!) {
# We have an id in deeply nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
runner(id: $id) {
...RunnerDetails
}

View File

@ -5,8 +5,6 @@
mutation runnerUpdate($input: RunnerUpdateInput!) {
runnerUpdate(input: $input) {
# We have an id in deep nested fragment
# eslint-disable-next-line @graphql-eslint/require-id-when-available
runner {
...RunnerDetails
}

View File

@ -87,6 +87,7 @@ export default {
:get-active-token-value="getActiveAuthor"
:default-suggestions="defaultAuthors"
:preloaded-suggestions="preloadedAuthors"
v-bind="$attrs"
@fetch-suggestions="fetchAuthors"
v-on="$listeners"
>

View File

@ -65,6 +65,7 @@ export default {
:suggestions="branches"
:suggestions-loading="loading"
:get-active-token-value="getActiveBranch"
v-bind="$attrs"
@fetch-suggestions="fetchBranches"
v-on="$listeners"
>

View File

@ -67,6 +67,7 @@ export default {
:suggestions="emojis"
:suggestions-loading="loading"
:get-active-token-value="getActiveEmoji"
v-bind="$attrs"
@fetch-suggestions="fetchEmojis"
v-on="$listeners"
>

View File

@ -104,6 +104,7 @@ export default {
:suggestions="labels"
:get-active-token-value="getActiveLabel"
:default-suggestions="defaultLabels"
v-bind="$attrs"
@fetch-suggestions="fetchLabels"
v-on="$listeners"
>

View File

@ -84,6 +84,7 @@ export default {
:suggestions="milestones"
:suggestions-loading="loading"
:get-active-token-value="getActiveMilestone"
v-bind="$attrs"
@fetch-suggestions="fetchMilestones"
v-on="$listeners"
>

View File

@ -66,6 +66,7 @@ export default {
:suggestions="releases"
:suggestions-loading="loading"
:get-active-token-value="getActiveRelease"
v-bind="$attrs"
@fetch-suggestions="fetchReleases"
v-on="$listeners"
>

View File

@ -3,7 +3,7 @@
class Profiles::GpgKeysController < Profiles::ApplicationController
before_action :set_gpg_key, only: [:destroy, :revoke]
feature_category :users
feature_category :source_code_management
def index
@gpg_keys = current_user.gpg_keys.with_subkeys

View File

@ -23,19 +23,24 @@ module Mutations
null: true,
description: 'Runner token after mutation.'
def resolve(**args)
def resolve(type:, id: nil)
scope = authorized_find!(type: type, id: id)
new_token = reset_token(scope)
{
token: reset_token(**args),
errors: []
token: new_token,
errors: errors_on_object(scope)
}
end
private
def find_object(type:, **args)
id = args[:id]
def find_object(type:, id: nil)
case type
when 'instance_type'
raise Gitlab::Graphql::Errors::ArgumentError, "id must not be specified for '#{type}' scope" if id.present?
ApplicationSetting.current
when 'group_type'
GitlabSchema.object_from_id(id, expected_type: ::Group)
when 'project_type'
@ -43,20 +48,7 @@ module Mutations
end
end
def reset_token(type:, **args)
id = args[:id]
scope = nil
case type
when 'instance_type'
raise Gitlab::Graphql::Errors::ArgumentError, "id must not be specified for '#{type}' scope" if id.present?
scope = ApplicationSetting.current
authorize!(scope)
when 'group_type', 'project_type'
scope = authorized_find!(type: type, id: id)
end
def reset_token(scope)
::Ci::Runners::ResetRegistrationTokenService.new(scope, current_user).execute if scope
end
end

View File

@ -0,0 +1,35 @@
# frozen_string_literal: true
module Mutations
module Timelogs
class Delete < Mutations::BaseMutation
graphql_name 'TimelogDelete'
field :timelog,
Types::TimelogType,
null: true,
description: 'Deleted timelog.'
argument :id,
::Types::GlobalIDType[::Timelog],
required: true,
description: 'Global ID of the timelog.'
authorize :admin_timelog
def resolve(id:)
timelog = authorized_find!(id: id)
result = ::Timelogs::DeleteService.new(timelog, current_user).execute
# Return the result payload, not the loaded timelog, so that it returns null in case of unauthorized access
{ timelog: result.payload, errors: result.errors }
end
def find_object(id:)
# TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id = ::Types::GlobalIDType[::Timelog].coerce_isolated_input(id)
GitlabSchema.find_by_gid(id)
end
end
end
end

View File

@ -88,6 +88,7 @@ module Types
mount_mutation Mutations::Terraform::State::Delete
mount_mutation Mutations::Terraform::State::Lock
mount_mutation Mutations::Terraform::State::Unlock
mount_mutation Mutations::Timelogs::Delete
mount_mutation Mutations::Todos::Create
mount_mutation Mutations::Todos::MarkDone
mount_mutation Mutations::Todos::Restore

View File

@ -6,6 +6,11 @@ module Types
authorize :read_issue
field :id,
GraphQL::Types::ID,
null: false,
description: 'Internal ID of the timelog.'
field :spent_at,
Types::TimeType,
null: true,

View File

@ -39,7 +39,7 @@ module ClustersHelper
base_domain: cluster.base_domain,
application_ingress_external_ip: cluster.application_ingress_external_ip,
auto_devops_help_path: help_page_path('topics/autodevops/index'),
external_endpoint_help_path: help_page_path('user/project/clusters/index.md', anchor: 'base-domain')
external_endpoint_help_path: help_page_path('user/project/clusters/gitlab_managed_clusters.md', anchor: 'base-domain')
}
end

View File

@ -2,4 +2,11 @@
class TimelogPolicy < BasePolicy
delegate { @subject.issuable }
desc "User who created the timelog"
condition(:is_author) { @user && @subject.user == @user }
rule { is_author | can?(:maintainer_access) }.policy do
enable :admin_timelog
end
end

View File

@ -111,6 +111,21 @@ module SystemNoteService
::SystemNotes::TimeTrackingService.new(noteable: noteable, project: project, author: author).change_time_spent
end
# Called when a timelog is removed from a Noteable
#
# noteable - Noteable object
# project - Project owning the noteable
# author - User performing the change
# timelog - The removed timelog
#
# Example Note text:
# "deleted 2h 30m of time spent from 22-03-2022"
#
# Returns the created Note object
def remove_timelog(noteable, project, author, timelog)
::SystemNotes::TimeTrackingService.new(noteable: noteable, project: project, author: author).remove_timelog(timelog)
end
def close_after_error_tracking_resolve(issue, project, author)
::SystemNotes::IssuablesService.new(noteable: issue, project: project, author: author).close_after_error_tracking_resolve
end

View File

@ -76,6 +76,18 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
end
def remove_timelog(timelog)
time_spent = timelog.time_spent
spent_at = timelog.spent_at&.to_date
parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent)
body = "deleted #{parsed_time} of spent time"
body += " from #{spent_at}" if spent_at
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
end
private
def issue_activity_counter

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module Timelogs
class BaseService
include BaseServiceUtility
include Gitlab::Utils::StrongMemoize
attr_accessor :timelog, :current_user
def initialize(timelog, user)
@timelog = timelog
@current_user = user
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Timelogs
class DeleteService < Timelogs::BaseService
def execute
unless can?(current_user, :admin_timelog, timelog)
return ServiceResponse.error(
message: "Timelog doesn't exist or you don't have permission to delete it",
http_status: 404)
end
if timelog.destroy
issuable = timelog.issuable
if issuable
# Add a system note for the timelog removal
SystemNoteService.remove_timelog(issuable, issuable.project, current_user, timelog)
end
ServiceResponse.success(payload: timelog)
else
ServiceResponse.error(message: 'Failed to remove timelog', http_status: 400)
end
end
end
end

View File

@ -32,6 +32,7 @@
- continuous_integration
- continuous_integration_scaling
- continuous_verification
- credential_management
- database
- dataops
- delivery
@ -87,6 +88,7 @@
- package_registry
- pages
- performance_testing
- permissions
- pipeline_authoring
- planning_analytics
- portfolio_management
@ -118,8 +120,10 @@
- static_application_security_testing
- static_site_editor
- subgroups
- system_access
- team_planning
- tracing
- user_management
- users
- utilization
- value_stream_management

View File

@ -11,6 +11,8 @@
[agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. [How do I migrate?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
GitLab self-managed customers can still use the feature [with a feature flag](https://docs.gitlab.com/ee/update/deprecations.html#self-managed-certificate-based-integration-with-kubernetes).
stage: Configure
tiers: [Free, Premium, Ultimate]
issue_url: 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8'

View File

@ -90,22 +90,22 @@
image_url: https://img.youtube.com/vi/-1MuKzWJXKQ/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
- title: CI/CD Tunnel for Kubernetes clusters
- title: CI/CD workflow for Kubernetes clusters
body: |
Until now, connecting Kubernetes clusters to GitLab CI/CD required users to open up their clusters towards GitLab. Some organizations do not encourage opening up their firewall externally due to security concerns.
Until now, connecting Kubernetes clusters to GitLab CI/CD required you to open up your clusters towards GitLab. Some organizations do not encourage opening up their firewall externally due to security concerns.
GitLab now ships with a CI/CD Tunnel that connects GitLab Runners with your Kubernetes cluster using the [GitLab Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/). This enables versatile GitOps workflows where the deployment logic can be coded in the pipeline.
GitLab now ships with a CI/CD functionality that connects runners with your Kubernetes cluster by using the [GitLab agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/). This enables versatile GitOps workflows where the deployment logic can be coded in the pipeline.
You and your team can safely use your preferred tool to run the deployment itself using `kubectl`, `helm`, `kpt`, `tanka`, or anything else without security concerns.
To use the tunnel, define the `kubecontext` in your CI/CD pipeline to connect with your agent. To simplify this process, we plan to [automatically inject the `kubecontext`](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) into the CI/CD environment in a future iteration.
Define the `kubecontext` in your CI/CD pipeline to connect with your agent. To simplify this process, we plan to [automatically inject the `kubecontext`](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) into the CI/CD environment in a future iteration.
The CI/CD tunnel is currently supported only from the project where the agent was configured but we are working on [adding group-level support](https://gitlab.com/groups/gitlab-org/-/epics/5784). You can safely start using the tunnel on GitLab SaaS and self-managed instances.
This type of connection is currently supported only from the project where the agent was configured but we are working on [adding group-level support](https://gitlab.com/groups/gitlab-org/-/epics/5784). You can safely start using CI/CD in your jobs on GitLab SaaS and self-managed instances.
stage: Configure
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_tunnel.html
url: https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html
image_url: https://img.youtube.com/vi/eXxM4ScqiJs/hqdefault.jpg
published_at: 2021-07-22
release: 14.1

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class DeleteFailedResetDuplicateCiRunnersTokenMigrationRecords < Gitlab::Database::Migration[1.0]
def up
# Delete remaining records of botched migrations before we start the new migrations
Gitlab::Database::BackgroundMigrationJob
.for_migration_class('ResetDuplicateCiRunnersTokenValuesOnProjects')
.delete_all
Gitlab::Database::BackgroundMigrationJob
.for_migration_class('ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects')
.delete_all
end
def down
# no-op
end
end

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
class Schedule20220328ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects < Gitlab::Database::Migration[1.0]
MIGRATION = 'ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects'
BATCH_SIZE = 2_000
DELAY_INTERVAL = 2.minutes
disable_ddl_transaction!
class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
include ::EachBatch
self.table_name = 'projects'
scope :base_query, -> { where.not(runners_token_encrypted: nil) }
end
def up
queue_background_migration_jobs_by_range_at_intervals(
Project.base_query,
MIGRATION,
DELAY_INTERVAL,
batch_size: BATCH_SIZE,
track_jobs: true
)
end
def down
# no-op
end
end

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
class Schedule20220328ResetDuplicateCiRunnersTokenValuesOnProjects < Gitlab::Database::Migration[1.0]
MIGRATION = 'ResetDuplicateCiRunnersTokenValuesOnProjects'
BATCH_SIZE = 2_000
DELAY_INTERVAL = 2.minutes
disable_ddl_transaction!
class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
include ::EachBatch
self.table_name = 'projects'
scope :base_query, -> { where.not(runners_token: nil) }
end
def up
queue_background_migration_jobs_by_range_at_intervals(
Project.base_query,
MIGRATION,
DELAY_INTERVAL,
batch_size: BATCH_SIZE,
track_jobs: true
)
end
def down
# no-op
end
end

View File

@ -0,0 +1 @@
4d75e2180a30d3cdd4efa3b6a7d107e146b755faf0316e985a8813a85644af35

View File

@ -0,0 +1 @@
a27caa521761ff1f4513318eb4ce3ea0e29d101f260493598caf4c8cb0fcc931

View File

@ -0,0 +1 @@
954217de622b1ee360edbd89dd31c5a051001cf6879ce97c7b49c228321d48d7

View File

@ -181,67 +181,6 @@ _The artifacts are stored by default in
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
### OpenStack example
See [the available connection settings for OpenStack](object_storage.md#openstack-compatible-connection-settings).
**In Omnibus installations:**
_The uploads are stored by default in
`/var/opt/gitlab/gitlab-rails/shared/artifacts`._
1. Edit `/etc/gitlab/gitlab.rb` and add the following lines, substituting
the values you want:
```ruby
gitlab_rails['artifacts_enabled'] = true
gitlab_rails['artifacts_object_store_enabled'] = true
gitlab_rails['artifacts_object_store_remote_directory'] = "artifacts"
gitlab_rails['artifacts_object_store_connection'] = {
'provider' => 'OpenStack',
'openstack_username' => 'OS_USERNAME',
'openstack_api_key' => 'OS_PASSWORD',
'openstack_temp_url_key' => 'OS_TEMP_URL_KEY',
'openstack_auth_url' => 'https://auth.cloud.ovh.net',
'openstack_region' => 'GRA',
'openstack_tenant_id' => 'OS_TENANT_ID',
}
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
---
**In installations from source:**
_The uploads are stored by default in
`/home/git/gitlab/shared/artifacts`._
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
lines:
```yaml
uploads:
object_store:
enabled: true
direct_upload: false
background_upload: true
proxy_download: false
remote_directory: "artifacts"
connection:
provider: OpenStack
openstack_username: OS_USERNAME
openstack_api_key: OS_PASSWORD
openstack_temp_url_key: OS_TEMP_URL_KEY
openstack_auth_url: 'https://auth.cloud.ovh.net'
openstack_region: GRA
openstack_tenant_id: OS_TENANT_ID
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
### Migrating to object storage
After [configuring the object storage](#using-object-storage), use the following task to

View File

@ -19,7 +19,7 @@ GitLab has been tested by vendors and customers on a number of object storage pr
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatible mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors, whose list is not officially established.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@ -386,52 +386,6 @@ If you are using a custom Azure storage domain,
configuration. This information is exchanged in an API call between
GitLab Rails and Workhorse.
#### OpenStack-compatible connection settings
Although OpenStack Swift provides S3 compatibility, some users may want to use
the [Swift API](https://docs.openstack.org/swift/latest/api/object_api_v1_overview.html).
This isn't compatible with the consolidated object storage form. OpenStack Swift
is supported only with the storage-specific form. If you want to use the
consolidated form, see the [S3 settings](#s3-compatible-connection-settings).
Here are the valid connection settings for the Swift API, provided by
[fog-openstack](https://github.com/fog/fog-openstack):
| Setting | Description | Default |
|--------------------------|----------------------|---------|
| `provider` | Always `OpenStack` for compatible hosts. | `OpenStack` |
| `openstack_username` | OpenStack username. | |
| `openstack_api_key` | OpenStack API key. | |
| `openstack_temp_url_key` | OpenStack key for generating temporary URLs | |
| `openstack_auth_url` | OpenStack authentication endpoint | |
| `openstack_region` | OpenStack region. | |
| `openstack_tenant` | OpenStack tenant ID. | |
#### Rackspace Cloud Files
The following table describes the valid connection parameters for
Rackspace Cloud, provided by [fog-rackspace](https://github.com/fog/fog-rackspace/).
This isn't compatible with the consolidated object storage form.
Rackspace Cloud is supported only with the storage-specific form.
| Setting | Description | Example |
|--------------------------|----------------|-------------|
| `provider` | Provider name. | `Rackspace` |
| `rackspace_username` | Username of the Rackspace account with access to the container. | `joe.smith` |
| `rackspace_api_key` | API key of the Rackspace account with access to the container. | `ABC123DEF456ABC123DEF456ABC123DE` |
| `rackspace_region` | Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://docs.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/). | `iad` |
| `rackspace_temp_url_key` | Private key you set in the Rackspace API for [temporary URLs](https://docs.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl). | `ABC123DEF456ABC123DEF456ABC123DE` |
Regardless of whether the container has public access enabled or disabled, Fog
uses the TempURL method to grant access to LFS objects. If you see error
messages in logs that refer to instantiating storage with a `temp-url-key`,
be sure you have set the key properly both in the Rackspace API and in
`gitlab.rb`. You can verify the value of the key Rackspace has set by sending a
GET request with token header to the service access endpoint URL and comparing
the output of the returned headers.
### Object-specific configuration
The following YAML shows how the `object_store` section defines
@ -799,3 +753,46 @@ to run the following command:
```ruby
Feature.disable(:s3_multithreaded_uploads)
```
## Migrate objects to a different object storage provider
You may need to migrate GitLab data in object storage to a different object storage provider. The following steps show you how do this using [Rclone](https://rclone.org/).
The steps assume you are moving the `uploads` bucket, but the same process works for other buckets.
Prerequisites:
- Choose the computer to run Rclone on. Depending on how much data you are migrating, Rclone may have to run for a long time so you should avoid using a laptop or desktop computer that can go into power saving. You can use your GitLab server to run Rclone.
1. [Install](https://rclone.org/downloads/) Rclone.
1. Configure Rclone by running the following:
```shell
rclone config
```
The configuration process is interactive. Add at least two "remotes": one for the object storage provider your data is currently on (`old`), and one for the provider you are moving to (`new`).
1. Verify that you can read the old data. The following example refers to the `uploads` bucket , but your bucket may have a different name:
```shell
rclone ls old:uploads | head
```
This should print a partial list of the objects currently stored in your `uploads` bucket. If you get an error, or if
the list is empty, go back and update your Rclone configuration using `rclone config`.
1. Perform an initial copy. You do not need to take your GitLab server offline for this step.
```shell
rclone sync -P old:uploads new:uploads
```
1. After the first sync completes, use the web UI or command-line interface of your new object storage provider to
verify that there are objects in the new bucket. If there are none, or if you encounter an error while running `rclone
sync`, check your Rclone configuration and try again.
After you have done at least one successful Rclone copy from the old location to the new location, schedule maintenance and take your GitLab server offline. During your maintenance window you must do two things:
1. Perform a final `rclone sync` run, knowing that your users cannot add new objects so you will not leave any behind in the old bucket.
1. Update the object storage configuration of your GitLab server to use the new provider for `uploads`.

View File

@ -88,8 +88,8 @@ components:
> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1 (`tags`).
Queue matching query works upon the worker attributes, described in [Sidekiq
style guide](../../development/sidekiq_style_guide.md). We support querying
Queue matching query works upon the worker attributes, described in
[Sidekiq style guide](../../development/sidekiq/index.md). We support querying
based on a subset of worker attributes:
- `feature_category` - the [GitLab feature

View File

@ -2169,7 +2169,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](http://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.

View File

@ -2173,7 +2173,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](http://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.

View File

@ -891,7 +891,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](http://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.

View File

@ -2108,7 +2108,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](http://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.

View File

@ -2189,7 +2189,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](http://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.

View File

@ -2108,7 +2108,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](http://www.digitalocean.com/products/spaces)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [OpenStack Swift (S3 compatibility mode)](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.

View File

@ -798,6 +798,39 @@ To find features that can be toggled, run `pp p.project_feature`.
Available permission levels are listed in
[concerns/featurable.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/featurable.rb).
### Get all error messages associated with groups, subgroups, members, and requesters
Collect error messages associated with groups, subgroups, members, and requesters. This
captures error messages that may not appear in the Web interface. This can be especially helpful
for troubleshooting issues with [LDAP group sync](../auth/ldap/ldap_synchronization.md#group-sync)
and unexpected behavior with users and their membership in groups and subgroups.
```ruby
# Find the group and subgroup
group = Group.find_by_full_path("parent_group")
subgroup = Group.find_by_full_path("parent_group/child_group")
# Group and subgroup errors
group.valid?
group.errors.map(&:full_messages)
subgroup.valid?
subgroup.errors.map(&:full_messages)
# Group and subgroup errors for the members AND requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)
group.members_and_requesters.map(&:errors).map(&:full_messages)
subgroup.requesters.map(&:valid?)
subgroup.requesters.map(&:errors).map(&:full_messages)
subgroup.members.map(&:valid?)
subgroup.members.map(&:errors).map(&:full_messages)
subgroup.members_and_requesters.map(&:errors).map(&:full_messages)
```
## Authentication
### Re-enable standard web sign-in form

View File

@ -130,60 +130,3 @@ _The uploads are stored by default in
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
#### OpenStack example
**In Omnibus installations:**
_The uploads are stored by default in
`/var/opt/gitlab/gitlab-rails/uploads`._
1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with
the values you want:
```ruby
gitlab_rails['uploads_object_store_remote_directory'] = "OPENSTACK_OBJECT_CONTAINER_NAME"
gitlab_rails['uploads_object_store_connection'] = {
'provider' => 'OpenStack',
'openstack_username' => 'OPENSTACK_USERNAME',
'openstack_api_key' => 'OPENSTACK_PASSWORD',
'openstack_temp_url_key' => 'OPENSTACK_TEMP_URL_KEY',
'openstack_auth_url' => 'https://auth.cloud.ovh.net/v2.0/',
'openstack_region' => 'DE1',
'openstack_tenant' => 'TENANT_ID',
}
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
---
**In installations from source:**
_The uploads are stored by default in
`/home/git/gitlab/public/uploads`._
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
lines:
```yaml
uploads:
object_store:
enabled: true
direct_upload: false
background_upload: true
proxy_download: false
remote_directory: OPENSTACK_OBJECT_CONTAINER_NAME
connection:
provider: OpenStack
openstack_username: OPENSTACK_USERNAME
openstack_api_key: OPENSTACK_PASSWORD
openstack_temp_url_key: OPENSTACK_TEMP_URL_KEY
openstack_auth_url: 'https://auth.cloud.ovh.net/v2.0/'
openstack_region: DE1
openstack_tenant: 'TENANT_ID'
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).

View File

@ -24,7 +24,7 @@ The following API resources are available in the project context:
| Resource | Available endpoints |
|:------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
| [Access tokens](resource_access_tokens.md) | `/projects/:id/access_tokens` (also available for groups) |
| [Access tokens](project_access_tokens.md) | `/projects/:id/access_tokens` (also available for groups) |
| [Agents](cluster_agents.md) | `/projects/:id/cluster_agents` |
| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |

View File

@ -4543,6 +4543,25 @@ Input type: `TimelineEventUpdateInput`
| <a id="mutationtimelineeventupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationtimelineeventupdatetimelineevent"></a>`timelineEvent` | [`TimelineEventType`](#timelineeventtype) | Timeline event. |
### `Mutation.timelogDelete`
Input type: `TimelogDeleteInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationtimelogdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationtimelogdeleteid"></a>`id` | [`TimelogID!`](#timelogid) | Global ID of the timelog. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationtimelogdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationtimelogdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationtimelogdeletetimelog"></a>`timelog` | [`Timelog`](#timelog) | Deleted timelog. |
### `Mutation.todoCreate`
Input type: `TodoCreateInput`
@ -16591,6 +16610,7 @@ Describes an incident management timeline event.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="timelogid"></a>`id` | [`ID!`](#id) | Internal ID of the timelog. |
| <a id="timelogissue"></a>`issue` | [`Issue`](#issue) | Issue that logged time was added to. |
| <a id="timelogmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request that logged time was added to. |
| <a id="timelognote"></a>`note` | [`Note`](#note) | Note where the quick action was executed to add the logged time. |
@ -19824,6 +19844,12 @@ For example: "2021-03-09T14:58:50+00:00".
See `https://www.iso.org/iso-8601-date-and-time-format.html`.
### `TimelogID`
A `TimelogID` is a global ID. It is encoded as a string.
An example `TimelogID` is: `"gid://gitlab/Timelog/1"`.
### `TodoID`
A `TodoID` is a global ID. It is encoded as a string.

View File

@ -1,11 +0,0 @@
---
redirect_to: 'project_access_tokens.md'
remove_date: '2022-04-06'
---
This document was moved to [another location](project_access_tokens.md).
<!-- This redirect file can be deleted after <2022-04-06>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,11 +0,0 @@
---
redirect_to: 'gitlab_experiment.md'
remove_date: '2022-04-13'
---
This document was moved to [another location](gitlab_experiment.md).
<!-- This redirect file can be deleted after <2022-04-13>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -4,13 +4,13 @@ group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Markdown developer documentation **(FREE)**
# GitLab Flavored Markdown (GLFM) developer documentation **(FREE)**
This page contains the MVC for the developer documentation for GitLab Flavored Markdown.
This page contains the MVC for the developer documentation for GitLab Flavored Markdown (GLFM).
For the user documentation about Markdown in GitLab, refer to
[GitLab Flavored Markdown](../../user/markdown.md).
## GitLab Flavored Markdown specification guide
## GitLab Flavored Markdown (GLFM) specification guide
The [specification guide](specification_guide/index.md) includes:
@ -18,3 +18,4 @@ The [specification guide](specification_guide/index.md) includes:
- [Parsing and rendering](specification_guide/index.md#parsing-and-rendering).
- [Goals](specification_guide/index.md#goals).
- [Implementation](specification_guide/index.md#implementation) of the spec.
- [Workflows](specification_guide/index.md#workflows).

View File

@ -385,20 +385,57 @@ subgraph output:<br/>GLFM specification files
end
```
#### `canonicalize-html.rb` script
The `scripts/glfm/canonicalize-html.rb` handles the
["canonicalization" of HTML](#canonicalization-of-html). It is a pipe-through
helper script which takes as input a static or WYSIWYG HTML string containing
extra HTML, and outputs a canonical HTML string.
It is implemented as a standalone, modular, single-purpose script, based on the
[Unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy#:~:text=The%20Unix%20philosophy%20emphasizes%20building,developers%20other%20than%20its%20creators.).
It's easy to use when running the standard CommonMark `spec_tests.py`
script, which expects canonical HTML, against the GitLab renderer implementations.
#### `run-spec-tests.sh` script
`scripts/glfm/run-spec-tests.sh` is a convenience shell script which runs
conformance specs via the CommonMark standard `spec_tests.py` script,
which uses the `glfm_specification/output/spec.txt` file and `scripts/glfm/canonicalize-html.rb`
helper script to test the GLFM renderer implementations' support for rendering Markdown
specification examples to canonical HTML.
```mermaid
graph LR
subgraph scripts:
A{run-spec-tests.sh} --> C
subgraph specification testing process
B[canonicalize-html.sh] --> C
C[spec_tests.py]
end
end
subgraph input
D[spec.txt GLFM specification] --> C
E((GLFM static<br/>renderer implementation)) --> B
F((GLFM WYSIWYG<br/>renderer implementation)) --> B
end
subgraph output:<br/>test results/output
C --> G[spec_tests.py output]
end
```
#### `update-example-snapshots.rb` script
The `scripts/glfm/update-example-snapshots.rb` script uses input specification
files to update example snapshots:
The `scripts/glfm/update-example-snapshots.rb` script uses the GLFM `spec.txt` specification
file to update example snapshots:
```mermaid
graph LR
subgraph script:
A{update-example-snapshots.rb}
end
subgraph input:<br/>input specification files
B[downloaded gfm_spec_v_0.29.txt] --> A
C[glfm_canonical_examples.txt] --> A
D[glfm_example_status.yml] --> A
subgraph input:<br/>input specification file
B[spec.txt] --> A
end
subgraph output:<br/>example snapshot files
A --> E[examples_index.yml]
@ -437,7 +474,7 @@ code. It contains only shell scripting commands for the relevant
graph LR
subgraph script:
A{run-snapshopt-tests.sh} --> B
B[relevant rspec/jest test files]
B[relevant rspec+jest test files]
end
subgraph input:<br/>YAML
C[examples_index.yml] --> B
@ -450,45 +487,6 @@ subgraph output:<br/>test results/output
end
```
#### `canonicalize-html.rb` script
The `scripts/glfm/canonicalize-html.rb` handles the
["canonicalization" of HTML](#canonicalization-of-html). It is a pipe-through
helper script which takes as input a static or WYSIWYG HTML string containing
extra HTML, and outputs a canonical HTML string.
It is implemented as a standalone, modular, single-purpose script, based on the
[Unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy#:~:text=The%20Unix%20philosophy%20emphasizes%20building,developers%20other%20than%20its%20creators.).
It's easy to use when running the standard CommonMark `spec_tests.py`
script, which expects canonical HTML, against the GitLab renderer implementations.
#### `run-spec-tests.sh` script
`scripts/glfm/run-spec-tests.sh` is a convenience shell script which runs
conformance specs via the CommonMark standard `spec_tests.py` script,
which uses the `glfm_specification/output/spec.txt` file and `scripts/glfm/canonicalize-html.rb`
helper script to test the GLFM renderer implementations' support for rendering Markdown
specification examples to canonical HTML.
```mermaid
graph LR
subgraph scripts:
A{run-spec-tests.sh} --> C
subgraph specification testing process
B[canonicalize-html.sh] --> C
C[spec_tests.py]
end
end
subgraph input
D[spec.txt GLFM specification] --> C
E((GLFM static<br/>renderer implementation)) --> B
F((GLFM WYSIWYG<br/>renderer implementation)) --> B
end
subgraph output:<br/>test results/output
C --> G[spec_tests.py output]
end
```
### Specification files
These files represent the GLFM specification itself. They are all
@ -528,12 +526,14 @@ updated, as in the case of all GFM files.
```yaml
07_99_an_example_with_incomplete_wysiwyg_implementation_1:
skip_update_example_snapshots: true
skip_running_snapshot_static_html_tests: false
skip_running_snapshot_wysiwyg_html_tests: true
skip_running_snapshot_prosemirror_json_tests: true
skip_update_example_snapshots: false
skip_update_example_snapshot_html_static: false
skip_update_example_snapshot_html_wysiwyg: false
skip_running_conformance_static_tests: false
skip_running_conformance_wysiwyg_tests: true
skip_running_conformance_wysiwyg_tests: false
skip_running_snapshot_static_html_tests: false
skip_running_snapshot_wysiwyg_html_tests: false
skip_running_snapshot_prosemirror_json_tests: false
```
#### Output specification files
@ -634,7 +634,7 @@ for each entry in `spec/fixtures/glfm/example_snapshots/examples_index.yml`
`spec/fixtures/glfm/example_snapshots/markdown.yml` sample entry:
```yaml
06_04_inlines_emphasis_and_strong_emphasis_1: |-
06_04_inlines_emphasis_and_strong_emphasis_1: |
*foo bar*
```
@ -670,11 +670,11 @@ Any exceptions or failures which occur when generating HTML are replaced with an
```yaml
06_04_inlines_emphasis_and_strong_emphasis_1:
canonical: |-
canonical: |
<p><em>foo bar</em></p>
static: |-
static: |
<p data-sourcepos="1:1-1:9" dir="auto"><strong>foo bar</strong></p>
wysiwyg: |-
wysiwyg: |
<p><strong>foo bar</strong></p>
```
@ -715,3 +715,28 @@ JSON for each entry in `spec/fixtures/glfm/example_snapshots/examples_index.yml`
]
}
```
## Workflows
This section describes how the scripts can be used to manage the GLFM specification and tests.
### Update the GLFM specification and run conformance tests
1. Run [`update-specification.rb`](#update-specificationrb-script) to update the GLFM specification [output specification files](#output-specification-files).
1. Visually inspect and confirm any resulting changes to the [output specification files](#output-specification-files).
1. Run [`run-spec-tests.sh`](http://gdk.test:3005/ee/development/gitlab_flavored_markdown/specification_guide/index.html#run-spec-testssh-script) to run the conformance tests against the canonicalized GLFM specification.
1. Commit any changes to the [output specification files](#output-specification-files).
### Update the example snapshots and run snapshot tests
1. If you are working on an in-progress feature or bug, make any necessary manual updates to the [input specification files](#input-specification-files). This may include:
1. Updating the canonical Markdown or HTML examples in `glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt`.
1. Updating `glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml` to reflect the current status of the examples or tests.
1. Run [`update-specification.rb`](#update-specificationrb-script) to update the `spec.txt` to reflect any changes which were made to the [input specification files](#input-specification-files).
1. Visually inspect and confirm any resulting changes to the [output specification files](#output-specification-files).
1. Run [`update-example-snapshots.rb`](#update-example-snapshotsrb-script) to update the [example snapshot files](#example-snapshot-files).
1. Visually inspect and confirm any resulting changes to the [example snapshot files](#example-snapshot-files).
1. Run [`run-snapshot-tests.sh`](#run-snapshot-testssh-script) as a convenience script to run all relevant frontend (RSpec) and backend (Jest) tests which use the example snapshots.
1. Any frontend or backend snapshot test may also be run individually.
1. All frontend and backend tests are also run as part of the continuous integration suite, as they normally are.
1. Commit any changes to the [input specification files](#input-specification-files), [output specification files](#output-specification-files), or [example snapshot files](#example-snapshot-files).

View File

@ -54,7 +54,7 @@ webserver, and can lead to a denial-of-service (DoS) attack in GitLab as
the Kubernetes cluster response times are outside of our control.
The easiest way to ensure your calls happen a background process is to
delegate any such work to happen in a [Sidekiq worker](sidekiq_style_guide.md).
delegate any such work to happen in a [Sidekiq worker](sidekiq/index.md).
You may want to make calls to Kubernetes and return the response, but a background
worker isn't a good fit. Consider using

View File

@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab uses [Redis](https://redis.io) for the following distinct purposes:
- Caching (mostly via `Rails.cache`).
- As a job processing queue with [Sidekiq](sidekiq_style_guide.md).
- As a job processing queue with [Sidekiq](sidekiq/index.md).
- To manage the shared application state.
- To store CI trace chunks.
- As a Pub/Sub queue backend for ActionCable.

View File

@ -1,11 +0,0 @@
---
redirect_to: 'sidekiq/index.md'
remove_date: '2022-04-13'
---
This document was moved to [another location](sidekiq/index.md).
<!-- This redirect file can be deleted after <2022-04-13>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -431,7 +431,7 @@ applications.
| `HELM_UPGRADE_EXTRA_ARGS` | Allows extra options in `helm upgrade` commands when deploying the application. Note that using quotes doesn't prevent word splitting. |
| `INCREMENTAL_ROLLOUT_MODE` | If present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. Set to `manual` for manual deployment jobs or `timed` for automatic rollout deployments with a 5 minute delay each one. |
| `K8S_SECRET_*` | Any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) is made available by Auto DevOps as environment variables to the deployed application. |
| `KUBE_CONTEXT` | From GitLab 14.5, can be used to select a context to use from `KUBECONFIG`. When `KUBE_CONTEXT` is blank, the default context in `KUBECONFIG` (if any) is used. A context must be selected when used [with the agent for Kubernetes](../../user/clusters/agent/ci_cd_tunnel.md). |
| `KUBE_CONTEXT` | From GitLab 14.5, can be used to select a context to use from `KUBECONFIG`. When `KUBE_CONTEXT` is blank, the default context in `KUBECONFIG` (if any) is used. A context must be selected when used [with the agent for Kubernetes](../../user/clusters/agent/ci_cd_workflow.md). |
| `KUBE_INGRESS_BASE_DOMAIN` | Can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/gitlab_managed_clusters.md#base-domain) for more information. |
| `KUBE_NAMESPACE` | The namespace used for deployments. When using certificate-based clusters, [this value should not be overwritten directly](../../user/project/clusters/deploy_to_cluster.md#custom-namespace). |
| `KUBECONFIG` | The kubeconfig to use for deployments. User-provided values take priority over GitLab-provided values. |

View File

@ -37,7 +37,7 @@ approach to manage Kubernetes deployments.
#### Deploy to Kubernetes from GitLab CI/CD
With the [GitLab agent for Kubernetes](../user/clusters/agent/install/index.md), you can perform [push-based
deployments](../user/clusters/agent/ci_cd_tunnel.md) from GitLab CI/CD. The agent provides
deployments](../user/clusters/agent/ci_cd_workflow.md) from GitLab CI/CD. The agent provides
a secure and reliable connection between GitLab and your Kubernetes cluster.
### Deploy to AWS with GitLab CI/CD

View File

@ -20,7 +20,7 @@ and running quickly.
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Use GitLab for DevOps](https://www.youtube.com/watch?v=7q9Y1Cv-ib0) (12m 34s) | Use GitLab through the entire DevOps lifecycle, from planning to monitoring. | **{star}** |
| [Use Markdown at GitLab](../user/markdown.md) | GitLab Flavored Markdown (GLFM) is used in many areas of GitLab, for example, in merge requests. | **{star}** |
| [GitLab 201](https://gitlab.edcast.com/pathways/ECL-44010cf6-7a9c-4b9b-b684-fa08508a3252) | Go beyond the basics to learn more about using GitLab for your work. | |
| Learn GitLab project | You might already have the **Learn GitLab** project, which has tutorial-style issues to help you learn GitLab. If not, download [this export file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/project_templates/learn_gitlab_ultimate.tar.gz) and [import it to a new project](../user/project/settings/import_export.md#import-a-project-and-its-data). | |
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Learn GitLab project walkthrough](https://www.youtube.com/watch?v=-oaI2WEKdI4&list=PL05JrBw4t0KofkHq4GZJ05FnNGa11PQ4d) (59m 2s) | Step through the tutorial-style issues in the **Learn GitLab** project. If you don't have this project, download [the export file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/project_templates/learn_gitlab_ultimate.tar.gz) and [import it to a new project](../user/project/settings/import_export.md#import-a-project-and-its-data). | |
| [Productivity tips](https://about.gitlab.com/blog/2021/02/18/improve-your-gitlab-productivity-with-these-10-tips/) | Get tips to help make you a productive GitLab user. | |
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Structure a multi-team organization](https://www.youtube.com/watch?v=KmASFwSap7c) (37m 37s) | Learn to use issues, milestones, epics, labels, and more to plan and manage your work. | |

View File

@ -1349,6 +1349,8 @@ For a more robust, secure, forthcoming, and reliable integration with Kubernetes
For updates and details about this deprecation, follow [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
GitLab self-managed customers can still use the feature [with a feature flag](https://docs.gitlab.com/ee/update/deprecations.html#self-managed-certificate-based-integration-with-kubernetes).
**Planned removal milestone: 15.0 (2022-05-22)**
### Self-managed certificate-based integration with Kubernetes

View File

@ -1,261 +1,11 @@
---
stage: Configure
group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
redirect_to: 'ci_cd_workflow.md'
remove_date: '2022-07-20'
---
# Using a GitLab CI/CD workflow for Kubernetes **(FREE)**
This document was moved to [another location](ci_cd_workflow.md).
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327409) in GitLab 14.1.
> - The pre-configured `KUBECONFIG` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) in GitLab 14.2.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) the `ci_access` attribute in GitLab 14.3.
> - The ability to authorize groups was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
> - Support for Omnibus installations was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5686) in GitLab 14.5.
> - The ability to switch between certificate-based clusters and agents was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335089) in GitLab 14.9. The certificate-based cluster context is always called `gitlab-deploy`.
You can use a GitLab CI/CD workflow to safely deploy to and update your Kubernetes clusters.
To do so, you must first [install an agent in your cluster](install/index.md). When done, you have a Kubernetes context and can
run Kubernetes API commands in your GitLab CI/CD pipeline.
To ensure access to your cluster is safe:
- Each agent has a separate context (`kubecontext`).
- Only the project where the agent is configured, and any additional projects you authorize, can access the agent in your cluster.
You do not need to have a runner in the cluster with the agent.
## GitLab CI/CD workflow steps
To update a Kubernetes cluster by using GitLab CI/CD, complete the following steps.
1. Ensure you have a working Kubernetes cluster and the manifests are in a GitLab project.
1. In the same GitLab project, [register and install the GitLab agent](install/index.md).
1. [Update your `.gitlab-ci.yml` file](#update-your-gitlab-ciyml-file-to-run-kubectl-commands) to
select the agent's Kubernetes context and run the Kubernetes API commands.
1. Run your pipeline to deploy to or update the cluster.
If you have multiple GitLab projects that contain Kubernetes manifests:
1. [Install the GitLab agent](install/index.md) in its own project, or in one of the
GitLab projects where you keep Kubernetes manifests.
1. [Authorize the agent](#authorize-the-agent) to access your GitLab projects.
1. Optional. For added security, [use impersonation](#use-impersonation-to-restrict-project-and-group-access).
1. [Update your `.gitlab-ci.yml` file](#update-your-gitlab-ciyml-file-to-run-kubectl-commands) to
select the agent's Kubernetes context and run the Kubernetes API commands.
1. Run your pipeline to deploy to or update the cluster.
## Authorize the agent
You must authorize the agent to access the project where you keep your Kubernetes manifests.
You can authorize the agent to access individual projects, or authorize a group or subgroup,
so all projects within have access. For added security, you can also
[use impersonation](#use-impersonation-to-restrict-project-and-group-access).
### Authorize the agent to access your projects
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327850) in GitLab 14.4.
To authorize the agent to access the GitLab project where you keep Kubernetes manifests:
1. On the top bar, select **Menu > Projects** and find the project that contains the agent configuration file (`config.yaml`).
1. Edit the file. Under the `ci_access` keyword, add the `projects` attribute.
1. For the `id`, add the path:
```yaml
ci_access:
projects:
- id: path/to/project
```
- The Kubernetes projects must be in the same group hierarchy as the project where the agent's configuration is.
- You can install additional agents into the same cluster to accommodate additional hierarchies.
- You can authorize up to 100 projects.
All CI/CD jobs now include a `KUBECONFIG` with contexts for every shared agent connection.
Choose the context to run `kubectl` commands from your CI/CD scripts.
### Authorize the agent to access projects in your groups
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
To authorize the agent to access all of the GitLab projects in a group or subgroup:
1. On the top bar, select **Menu > Projects** and find the project that contains the agent configuration file (`config.yaml`).
1. Edit the file. Under the `ci_access` keyword, add the `groups` attribute.
1. For the `id`, add the path:
```yaml
ci_access:
groups:
- id: path/to/group/subgroup
```
- The Kubernetes projects must be in the same group hierarchy as the project where the agent's configuration is.
- You can install additional agents into the same cluster to accommodate additional hierarchies.
- All of the subgroups of an authorized group also have access to the same agent (without being specified individually).
- You can authorize up to 100 groups.
All the projects that belong to the group and its subgroups are now authorized to access the agent.
All CI/CD jobs now include a `KUBECONFIG` with contexts for every shared agent connection.
Choose the context to run `kubectl` commands from your CI/CD scripts.
## Update your `.gitlab-ci.yml` file to run `kubectl` commands
In the project where you want to run Kubernetes commands, edit your project's `.gitlab-ci.yml` file.
In the first command under the `script` keyword, set your agent's context.
Use the format `path/to/agent/repository:agent-name`. For example:
```yaml
deploy:
image:
name: bitnami/kubectl:latest
entrypoint: [""]
script:
- kubectl config get-contexts
- kubectl config use-context path/to/agent/repository:agent-name
- kubectl get pods
```
If you are not sure what your agent's context is, open a terminal and connect to your cluster.
Run `kubectl config get-contexts`.
### Environments with both certificate-based and agent-based connections
When you deploy to an environment that has both a [certificate-based
cluster](../../infrastructure/clusters/index.md) (deprecated) and an agent connection:
- The certificate-based cluster's context is called `gitlab-deploy`. This context
is always selected by default.
- In GitLab 14.9 and later, agent contexts are included in the
`KUBECONFIG`. You can select them by using `kubectl config use-context
path/to/agent/repository:agent-name`.
- In GitLab 14.8 and earlier, you can still use agent connections, but for environments that
already have a certificate-based cluster, the agent connections are not included in the `KUBECONFIG`.
To use an agent connection when certificate-based connections are present, you can manually configure a new `kubectl`
configuration context. For example:
```yaml
deploy:
variables:
KUBE_CONTEXT: my-context # The name to use for the new context
AGENT_ID: 1234 # replace with your agent's numeric ID
K8S_PROXY_URL: wss://kas.gitlab.com/k8s-proxy/ # replace with your agent server (KAS) Kubernetes proxy URL
# ... any other variables you have configured
before_script:
- kubectl config set-credentials agent:$AGENT_ID --token="ci:${AGENT_ID}:${CI_JOB_TOKEN}"
- kubectl config set-cluster gitlab --server="${K8S_PROXY_URL}"
- kubectl config set-context "$KUBE_CONTEXT" --cluster=gitlab --user="agent:${AGENT_ID}"
- kubectl config use-context "$KUBE_CONTEXT"
# ... rest of your job configuration
```
## Use impersonation to restrict project and group access **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345014) in GitLab 14.5.
By default, your CI/CD job inherits all the permissions from the service account used to install the
agent in the cluster.
To restrict access to your cluster, you can use [impersonation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation).
To specify impersonations, use the `access_as` attribute in your agent configuration file and use Kubernetes RBAC rules to manage impersonated account permissions.
You can impersonate:
- The agent itself (default).
- The CI/CD job that accesses the cluster.
- A specific user or system account defined within the cluster.
### Impersonate the agent
The agent is impersonated by default. You don't need to do anything to impersonate it.
### Impersonate the CI/CD job that accesses the cluster
To impersonate the CI/CD job that accesses the cluster, under the `access_as` key, add the `ci_job: {}` key-value.
When the agent makes the request to the actual Kubernetes API, it sets the
impersonation credentials in the following way:
- `UserName` is set to `gitlab:ci_job:<job id>`. Example: `gitlab:ci_job:1074499489`.
- `Groups` is set to:
- `gitlab:ci_job` to identify all requests coming from CI jobs.
- The list of IDs of groups the project is in.
- The project ID.
- The slug of the environment this job belongs to.
Example: for a CI job in `group1/group1-1/project1` where:
- Group `group1` has ID 23.
- Group `group1/group1-1` has ID 25.
- Project `group1/group1-1/project1` has ID 150.
- Job running in a prod environment.
Group list would be `[gitlab:ci_job, gitlab:group:23, gitlab:group:25, gitlab:project:150, gitlab:project_env:150:prod]`.
- `Extra` carries extra information about the request. The following properties are set on the impersonated identity:
| Property | Description |
| -------- | ----------- |
| `agent.gitlab.com/id` | Contains the agent ID. |
| `agent.gitlab.com/config_project_id` | Contains the agent's configuration project ID. |
| `agent.gitlab.com/project_id` | Contains the CI project ID. |
| `agent.gitlab.com/ci_pipeline_id` | Contains the CI pipeline ID. |
| `agent.gitlab.com/ci_job_id` | Contains the CI job ID. |
| `agent.gitlab.com/username` | Contains the username of the user the CI job is running as. |
| `agent.gitlab.com/environment_slug` | Contains the slug of the environment. Only set if running in an environment. |
Example to restrict access by the CI/CD job's identity:
```yaml
ci_access:
projects:
- id: path/to/project
access_as:
ci_job: {}
```
### Impersonate a static identity
For a given connection, you can use a static identity for the impersonation.
Under the `access_as` key, add the `impersonate` key to make the request using the provided identity.
The identity can be specified with the following keys:
- `username` (required)
- `uid`
- `groups`
- `extra`
See the [official Kubernetes documentation for details](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation).
## Troubleshooting
### `kubectl` commands not supported
The commands `kubectl exec`, `kubectl cp`, and `kubectl attach` are not supported.
Anything that uses these API endpoints does not work, because they use the deprecated
SPDY protocol.
[An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/346248) to add support for these commands.
### Grant write permissions to `~/.kube/cache`
Tools like `kubectl`, Helm, `kpt`, and `kustomize` cache information about
the cluster in `~/.kube/cache`. If this directory is not writable, the tool fetches information on each invocation,
making interactions slower and creating unnecessary load on the cluster. For the best experience, in the
image you use in your .`gitlab-ci.yml` file, ensure this directory is writable.
### Enable TLS
If you are on a self-managed GitLab instance, ensure your instance is configured with Transport Layer Security (TLS).
If you attempt to use `kubectl` without TLS, you might get an error like:
```shell
$ kubectl get pods
error: You must be logged in to the server (the server has asked for the client to provide credentials)
```
<!-- This redirect file can be deleted after <2022-07-20>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -0,0 +1,261 @@
---
stage: Configure
group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Using a GitLab CI/CD workflow for Kubernetes **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327409) in GitLab 14.1.
> - The pre-configured `KUBECONFIG` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) in GitLab 14.2.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) the `ci_access` attribute in GitLab 14.3.
> - The ability to authorize groups was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
> - Support for Omnibus installations was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5686) in GitLab 14.5.
> - The ability to switch between certificate-based clusters and agents was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335089) in GitLab 14.9. The certificate-based cluster context is always called `gitlab-deploy`.
You can use a GitLab CI/CD workflow to safely deploy to and update your Kubernetes clusters.
To do so, you must first [install an agent in your cluster](install/index.md). When done, you have a Kubernetes context and can
run Kubernetes API commands in your GitLab CI/CD pipeline.
To ensure access to your cluster is safe:
- Each agent has a separate context (`kubecontext`).
- Only the project where the agent is configured, and any additional projects you authorize, can access the agent in your cluster.
You do not need to have a runner in the cluster with the agent.
## GitLab CI/CD workflow steps
To update a Kubernetes cluster by using GitLab CI/CD, complete the following steps.
1. Ensure you have a working Kubernetes cluster and the manifests are in a GitLab project.
1. In the same GitLab project, [register and install the GitLab agent](install/index.md).
1. [Update your `.gitlab-ci.yml` file](#update-your-gitlab-ciyml-file-to-run-kubectl-commands) to
select the agent's Kubernetes context and run the Kubernetes API commands.
1. Run your pipeline to deploy to or update the cluster.
If you have multiple GitLab projects that contain Kubernetes manifests:
1. [Install the GitLab agent](install/index.md) in its own project, or in one of the
GitLab projects where you keep Kubernetes manifests.
1. [Authorize the agent](#authorize-the-agent) to access your GitLab projects.
1. Optional. For added security, [use impersonation](#use-impersonation-to-restrict-project-and-group-access).
1. [Update your `.gitlab-ci.yml` file](#update-your-gitlab-ciyml-file-to-run-kubectl-commands) to
select the agent's Kubernetes context and run the Kubernetes API commands.
1. Run your pipeline to deploy to or update the cluster.
## Authorize the agent
You must authorize the agent to access the project where you keep your Kubernetes manifests.
You can authorize the agent to access individual projects, or authorize a group or subgroup,
so all projects within have access. For added security, you can also
[use impersonation](#use-impersonation-to-restrict-project-and-group-access).
### Authorize the agent to access your projects
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327850) in GitLab 14.4.
To authorize the agent to access the GitLab project where you keep Kubernetes manifests:
1. On the top bar, select **Menu > Projects** and find the project that contains the agent configuration file (`config.yaml`).
1. Edit the file. Under the `ci_access` keyword, add the `projects` attribute.
1. For the `id`, add the path:
```yaml
ci_access:
projects:
- id: path/to/project
```
- The Kubernetes projects must be in the same group hierarchy as the project where the agent's configuration is.
- You can install additional agents into the same cluster to accommodate additional hierarchies.
- You can authorize up to 100 projects.
All CI/CD jobs now include a `KUBECONFIG` with contexts for every shared agent connection.
Choose the context to run `kubectl` commands from your CI/CD scripts.
### Authorize the agent to access projects in your groups
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
To authorize the agent to access all of the GitLab projects in a group or subgroup:
1. On the top bar, select **Menu > Projects** and find the project that contains the agent configuration file (`config.yaml`).
1. Edit the file. Under the `ci_access` keyword, add the `groups` attribute.
1. For the `id`, add the path:
```yaml
ci_access:
groups:
- id: path/to/group/subgroup
```
- The Kubernetes projects must be in the same group hierarchy as the project where the agent's configuration is.
- You can install additional agents into the same cluster to accommodate additional hierarchies.
- All of the subgroups of an authorized group also have access to the same agent (without being specified individually).
- You can authorize up to 100 groups.
All the projects that belong to the group and its subgroups are now authorized to access the agent.
All CI/CD jobs now include a `KUBECONFIG` with contexts for every shared agent connection.
Choose the context to run `kubectl` commands from your CI/CD scripts.
## Update your `.gitlab-ci.yml` file to run `kubectl` commands
In the project where you want to run Kubernetes commands, edit your project's `.gitlab-ci.yml` file.
In the first command under the `script` keyword, set your agent's context.
Use the format `path/to/agent/repository:agent-name`. For example:
```yaml
deploy:
image:
name: bitnami/kubectl:latest
entrypoint: [""]
script:
- kubectl config get-contexts
- kubectl config use-context path/to/agent/repository:agent-name
- kubectl get pods
```
If you are not sure what your agent's context is, open a terminal and connect to your cluster.
Run `kubectl config get-contexts`.
### Environments with both certificate-based and agent-based connections
When you deploy to an environment that has both a [certificate-based
cluster](../../infrastructure/clusters/index.md) (deprecated) and an agent connection:
- The certificate-based cluster's context is called `gitlab-deploy`. This context
is always selected by default.
- In GitLab 14.9 and later, agent contexts are included in the
`KUBECONFIG`. You can select them by using `kubectl config use-context
path/to/agent/repository:agent-name`.
- In GitLab 14.8 and earlier, you can still use agent connections, but for environments that
already have a certificate-based cluster, the agent connections are not included in the `KUBECONFIG`.
To use an agent connection when certificate-based connections are present, you can manually configure a new `kubectl`
configuration context. For example:
```yaml
deploy:
variables:
KUBE_CONTEXT: my-context # The name to use for the new context
AGENT_ID: 1234 # replace with your agent's numeric ID
K8S_PROXY_URL: wss://kas.gitlab.com/k8s-proxy/ # replace with your agent server (KAS) Kubernetes proxy URL
# ... any other variables you have configured
before_script:
- kubectl config set-credentials agent:$AGENT_ID --token="ci:${AGENT_ID}:${CI_JOB_TOKEN}"
- kubectl config set-cluster gitlab --server="${K8S_PROXY_URL}"
- kubectl config set-context "$KUBE_CONTEXT" --cluster=gitlab --user="agent:${AGENT_ID}"
- kubectl config use-context "$KUBE_CONTEXT"
# ... rest of your job configuration
```
## Use impersonation to restrict project and group access **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345014) in GitLab 14.5.
By default, your CI/CD job inherits all the permissions from the service account used to install the
agent in the cluster.
To restrict access to your cluster, you can use [impersonation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation).
To specify impersonations, use the `access_as` attribute in your agent configuration file and use Kubernetes RBAC rules to manage impersonated account permissions.
You can impersonate:
- The agent itself (default).
- The CI/CD job that accesses the cluster.
- A specific user or system account defined within the cluster.
### Impersonate the agent
The agent is impersonated by default. You don't need to do anything to impersonate it.
### Impersonate the CI/CD job that accesses the cluster
To impersonate the CI/CD job that accesses the cluster, under the `access_as` key, add the `ci_job: {}` key-value.
When the agent makes the request to the actual Kubernetes API, it sets the
impersonation credentials in the following way:
- `UserName` is set to `gitlab:ci_job:<job id>`. Example: `gitlab:ci_job:1074499489`.
- `Groups` is set to:
- `gitlab:ci_job` to identify all requests coming from CI jobs.
- The list of IDs of groups the project is in.
- The project ID.
- The slug of the environment this job belongs to.
Example: for a CI job in `group1/group1-1/project1` where:
- Group `group1` has ID 23.
- Group `group1/group1-1` has ID 25.
- Project `group1/group1-1/project1` has ID 150.
- Job running in a prod environment.
Group list would be `[gitlab:ci_job, gitlab:group:23, gitlab:group:25, gitlab:project:150, gitlab:project_env:150:prod]`.
- `Extra` carries extra information about the request. The following properties are set on the impersonated identity:
| Property | Description |
| -------- | ----------- |
| `agent.gitlab.com/id` | Contains the agent ID. |
| `agent.gitlab.com/config_project_id` | Contains the agent's configuration project ID. |
| `agent.gitlab.com/project_id` | Contains the CI project ID. |
| `agent.gitlab.com/ci_pipeline_id` | Contains the CI pipeline ID. |
| `agent.gitlab.com/ci_job_id` | Contains the CI job ID. |
| `agent.gitlab.com/username` | Contains the username of the user the CI job is running as. |
| `agent.gitlab.com/environment_slug` | Contains the slug of the environment. Only set if running in an environment. |
Example to restrict access by the CI/CD job's identity:
```yaml
ci_access:
projects:
- id: path/to/project
access_as:
ci_job: {}
```
### Impersonate a static identity
For a given connection, you can use a static identity for the impersonation.
Under the `access_as` key, add the `impersonate` key to make the request using the provided identity.
The identity can be specified with the following keys:
- `username` (required)
- `uid`
- `groups`
- `extra`
See the [official Kubernetes documentation for details](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation).
## Troubleshooting
### `kubectl` commands not supported
The commands `kubectl exec`, `kubectl cp`, and `kubectl attach` are not supported.
Anything that uses these API endpoints does not work, because they use the deprecated
SPDY protocol.
[An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/346248) to add support for these commands.
### Grant write permissions to `~/.kube/cache`
Tools like `kubectl`, Helm, `kpt`, and `kustomize` cache information about
the cluster in `~/.kube/cache`. If this directory is not writable, the tool fetches information on each invocation,
making interactions slower and creating unnecessary load on the cluster. For the best experience, in the
image you use in your .`gitlab-ci.yml` file, ensure this directory is writable.
### Enable TLS
If you are on a self-managed GitLab instance, ensure your instance is configured with Transport Layer Security (TLS).
If you attempt to use `kubectl` without TLS, you might get an error like:
```shell
$ kubectl get pods
error: You must be logged in to the server (the server has asked for the client to provide credentials)
```

View File

@ -35,7 +35,7 @@ In a [**GitOps** workflow](gitops.md), you keep your Kubernetes manifests in Git
any time you update your manifests, the agent updates the cluster. This workflow is fully driven with Git and is considered pull-based,
because the cluster is pulling updates from your GitLab repository.
In a [**CI/CD** workflow](ci_cd_tunnel.md), you use GitLab CI/CD to query and update your cluster by using the Kubernetes API.
In a [**CI/CD** workflow](ci_cd_workflow.md), you use GitLab CI/CD to query and update your cluster by using the Kubernetes API.
This workflow is considered push-based, because GitLab is pushing requests from GitLab CI/CD to your cluster.
## Supported cluster versions
@ -65,7 +65,7 @@ Read about how to [migrate to the agent for Kubernetes](../../infrastructure/clu
## Related topics
- [GitOps workflow](gitops.md)
- [GitLab CI/CD workflow](ci_cd_tunnel.md)
- [GitLab CI/CD workflow](ci_cd_workflow.md)
- [Install the agent](install/index.md)
- [Work with the agent](repository.md)
- [Troubleshooting](troubleshooting.md)

View File

@ -44,7 +44,7 @@ In GitLab 14.10, a [flag](../../../../administration/feature_flags.md) named `ce
Prerequisites:
- For a [GitLab CI/CD workflow](../ci_cd_tunnel.md), ensure that
- For a [GitLab CI/CD workflow](../ci_cd_workflow.md), ensure that
[GitLab CI/CD is enabled](../../../../ci/enable_or_disable_ci.md#enable-cicd-in-a-project).
To register an agent with GitLab:
@ -68,7 +68,7 @@ The agent is configured through a configuration file. This file is optional. Wit
You need a configuration file if:
- You want to use [a GitOps workflow](../gitops.md#gitops-configuration-reference).
- You want to authorize a different project to use the agent for a [GitLab CI/CD workflow](../ci_cd_tunnel.md#authorize-the-agent).
- You want to authorize a different project to use the agent for a [GitLab CI/CD workflow](../ci_cd_workflow.md#authorize-the-agent).
To create an agent configuration file, go to the GitLab project. In the repository, create a file called `config.yaml` at this path:

View File

@ -32,7 +32,7 @@ If you have already configured the agent and connected a cluster with GitLab:
1. [Create a project from the cluster management project template](#create-a-project-based-on-the-cluster-management-project-template).
1. In the project where you configured your agent,
[grant the agent access to the new project](agent/ci_cd_tunnel.md#authorize-the-agent).
[grant the agent access to the new project](agent/ci_cd_workflow.md#authorize-the-agent).
1. In the new project, create an
[environment variable](../../ci/variables/index.md#add-a-cicd-variable-to-a-project) named `$KUBE_CONTEXT`
and set the value to `path/to/agent-configuration-project:your-agent-name`.

View File

@ -67,5 +67,5 @@ The concept of [project-level](../../project/clusters/index.md),
[instance-level](../../instance/clusters/index.md) clusters becomes
extinct in the new model, although the functionality remains to some extent.
The agent is always configured in a single GitLab project and you can expose the cluster connection to other projects and groups to [access it from GitLab CI/CD](../../clusters/agent/ci_cd_tunnel.md).
The agent is always configured in a single GitLab project and you can expose the cluster connection to other projects and groups to [access it from GitLab CI/CD](../../clusters/agent/ci_cd_workflow.md).
By doing so, you are granting these projects and groups access to the same cluster, which is similar to group-level clusters' use case.

View File

@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To connect your Kubernetes cluster with GitLab, you can use:
- [A GitOps workflow](../../clusters/agent/gitops.md).
- [A GitLab CI/CD workflow](../../clusters/agent/ci_cd_tunnel.md).
- [A GitLab CI/CD workflow](../../clusters/agent/ci_cd_workflow.md).
- [A certificate-based integration](index.md).
The certificate-based integration is
@ -23,7 +23,7 @@ in GitLab 14.5. The removal dates are:
If you are using the certificate-based integration, you should move to another workflow as soon as possible.
As a general rule, to migrate clusters that rely on GitLab CI/CD,
you can use the [CI/CD workflow](../../clusters/agent/ci_cd_tunnel.md).
you can use the [CI/CD workflow](../../clusters/agent/ci_cd_workflow.md).
This workflow uses an agent to connect to your cluster. The agent:
- Is not exposed to the internet.
@ -41,7 +41,7 @@ Some features are currently available only when using certificate-based integrat
With GitLab-managed clusters, GitLab creates separate service accounts and namespaces
for every branch and deploys by using these resources.
The GitLab agent uses [impersonation](../../clusters/agent/ci_cd_tunnel.md#use-impersonation-to-restrict-project-and-group-access)
The GitLab agent uses [impersonation](../../clusters/agent/ci_cd_workflow.md#use-impersonation-to-restrict-project-and-group-access)
strategies to deploy to your cluster with restricted account access. To do so:
1. Choose the impersonation strategy that suits your needs.
@ -92,7 +92,7 @@ For an example, [view this project](https://gitlab.com/gitlab-examples/ops/gitop
### Migrate generic deployments
Follow the process for the [CI/CD workflow](../../clusters/agent/ci_cd_tunnel.md).
Follow the process for the [CI/CD workflow](../../clusters/agent/ci_cd_workflow.md).
## Migrate from GitLab Managed applications

View File

@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
To connect your cluster to GitLab, use the [GitLab agent](../../clusters/agent/index.md).
To deploy with the agent, use the [CI/CD workflow](../../clusters/agent/ci_cd_tunnel.md).
To deploy with the agent, use the [CI/CD workflow](../../clusters/agent/ci_cd_workflow.md).
A Kubernetes cluster can be the destination for a deployment job. If

View File

@ -52,7 +52,7 @@ self-managed GitLab instance.
pull requests) with matching GitLab users.
- If you're importing to a self-managed GitLab instance, you can alternatively use the
[GitHub Rake task](../../../administration/raketasks/github_import.md) to import
projects without the constraints of a [Sidekiq](../../../development/sidekiq_style_guide.md) worker.
projects without the constraints of a [Sidekiq](../../../development/sidekiq/index.md) worker.
- If you're importing from GitHub Enterprise to your self-managed GitLab instance:
- You must first enable [GitHub integration](../../../integration/github.md).
- To import projects from GitHub Enterprise to GitLab.com, use the [Import API](../../../api/import.md).

View File

@ -114,6 +114,18 @@ so if you remove more time than already entered, GitLab ignores the subtraction.
To remove all the time spent at once, use the `/remove_time_spent` [quick action](quick_actions.md).
### Delete time spent
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356796) in GitLab 15.0.
A timelog is a single entry of time spent, either positive or negative.
Prerequisites:
- You must be the author of the timelog or have at least the Maintainer role for the project.
You can [delete timelogs](../../api/graphql/reference/index.md#mutationtimelogdelete) using the GraphQL API.
## View a time tracking report
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271409) in GitLab 13.12.

View File

@ -6,12 +6,14 @@ module API
before { authenticate! }
feature_category :authentication_and_authorization
urgency :low
helpers ::API::Helpers::MembersHelpers
%w[group project].each do |source_type|
{
"group" => :subgroups,
"project" => :projects
}.each do |source_type, feature_category|
params do
requires :id, type: String, desc: "The #{source_type} ID"
end
@ -27,7 +29,7 @@ module API
use :pagination
end
get ":id/members" do
get ":id/members", feature_category: feature_category do
source = find_source(source_type, params[:id])
members = paginate(retrieve_members(source, params: params))
@ -46,7 +48,7 @@ module API
use :pagination
end
get ":id/members/all" do
get ":id/members/all", feature_category: feature_category do
source = find_source(source_type, params[:id])
members = paginate(retrieve_members(source, params: params, deep: true))
@ -61,7 +63,7 @@ module API
requires :user_id, type: Integer, desc: 'The user ID of the member'
end
# rubocop: disable CodeReuse/ActiveRecord
get ":id/members/:user_id" do
get ":id/members/:user_id", feature_category: feature_category do
source = find_source(source_type, params[:id])
members = source_members(source)
@ -78,7 +80,7 @@ module API
requires :user_id, type: Integer, desc: 'The user ID of the member'
end
# rubocop: disable CodeReuse/ActiveRecord
get ":id/members/all/:user_id" do
get ":id/members/all/:user_id", feature_category: feature_category do
source = find_source(source_type, params[:id])
members = find_all_members(source)
@ -100,7 +102,7 @@ module API
optional :tasks_project_id, type: Integer, desc: 'The project ID in which to create the task issues'
end
post ":id/members" do
post ":id/members", feature_category: feature_category do
source = find_source(source_type, params[:id])
authorize_admin_source!(source_type, source)
@ -123,7 +125,7 @@ module API
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
end
# rubocop: disable CodeReuse/ActiveRecord
put ":id/members/:user_id" do
put ":id/members/:user_id", feature_category: feature_category do
source = find_source(source_type, params.delete(:id))
authorize_admin_source!(source_type, source)
@ -152,7 +154,7 @@ module API
desc: 'Flag indicating if the removed member should be unassigned from any issues or merge requests within given group or project'
end
# rubocop: disable CodeReuse/ActiveRecord
delete ":id/members/:user_id" do
delete ":id/members/:user_id", feature_category: feature_category do
source = find_source(source_type, params[:id])
member = source_members(source).find_by!(user_id: params[:user_id])

View File

@ -729,7 +729,7 @@ module API
params do
requires :id, type: String, desc: 'ID of a project'
end
get ':id/storage', feature_category: :projects do
get ':id/storage', feature_category: :source_code_management do
authenticated_as_admin!
present user_project, with: Entities::ProjectRepositoryStorage, current_user: current_user

View File

@ -5,24 +5,24 @@ module Gitlab
# A job to nullify duplicate runners_token_encrypted values in projects table in batches
class ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects
class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
include ::EachBatch
include EachBatch
self.table_name = 'projects'
scope :base_query, -> do
where.not(runners_token_encrypted: nil)
end
scope :base_query, -> { where.not(runners_token_encrypted: nil) }
end
def perform(start_id, end_id)
# Reset duplicate runner tokens that would prevent creating an unique index.
batch_records = Project.base_query.where(id: start_id..end_id)
duplicate_tokens = Project.base_query
.where(id: start_id..end_id)
.where(runners_token_encrypted: batch_records.select(:runners_token_encrypted).distinct)
.group(:runners_token_encrypted)
.having('COUNT(*) > 1')
.pluck(:runners_token_encrypted)
Project.where(runners_token_encrypted: duplicate_tokens).update_all(runners_token_encrypted: nil) if duplicate_tokens.any?
batch_records.where(runners_token_encrypted: duplicate_tokens).update_all(runners_token_encrypted: nil) if duplicate_tokens.any?
mark_job_as_succeeded(start_id, end_id)
end
@ -30,7 +30,10 @@ module Gitlab
private
def mark_job_as_succeeded(*arguments)
Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects', arguments)
::Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
self.class.name.demodulize,
arguments
)
end
end
end

View File

@ -5,24 +5,24 @@ module Gitlab
# A job to nullify duplicate ci_runners_token values in projects table in batches
class ResetDuplicateCiRunnersTokenValuesOnProjects
class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
include ::EachBatch
include EachBatch
self.table_name = 'projects'
scope :base_query, -> do
where.not(runners_token: nil)
end
scope :base_query, -> { where.not(runners_token: nil) }
end
def perform(start_id, end_id)
# Reset duplicate runner tokens that would prevent creating an unique index.
batch_records = Project.base_query.where(id: start_id..end_id)
duplicate_tokens = Project.base_query
.where(id: start_id..end_id)
.where(runners_token: batch_records.select(:runners_token).distinct)
.group(:runners_token)
.having('COUNT(*) > 1')
.pluck(:runners_token)
Project.where(runners_token: duplicate_tokens).update_all(runners_token: nil) if duplicate_tokens.any?
batch_records.where(runners_token: duplicate_tokens).update_all(runners_token: nil) if duplicate_tokens.any?
mark_job_as_succeeded(start_id, end_id)
end
@ -30,7 +30,10 @@ module Gitlab
private
def mark_job_as_succeeded(*arguments)
Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('ResetDuplicateCiRunnerValuesTokensOnProjects', arguments)
::Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
self.class.name.demodulize,
arguments
)
end
end
end

View File

@ -57,7 +57,7 @@
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "2.8.0",
"@gitlab/ui": "38.8.1",
"@gitlab/ui": "39.0.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-7",
"@rails/ujs": "6.1.4-7",
@ -205,7 +205,7 @@
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
"@gitlab/eslint-plugin": "12.0.1",
"@gitlab/stylelint-config": "4.0.0",
"@graphql-eslint/eslint-plugin": "3.0.0",
"@graphql-eslint/eslint-plugin": "3.10.2",
"@testing-library/dom": "^7.16.2",
"@types/jest": "^26.0.24",
"@vue/test-utils": "1.3.0",

View File

@ -12,7 +12,7 @@ module QA
end
view 'app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue' do
element :target_branch_field, required: true
element :source_branch_field, required: true
end
view 'app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue' do
@ -57,8 +57,8 @@ module QA
wait_for_requests
end
def target_branch_name
find_element(:target_branch_field).value
def source_branch_name
find_element(:source_branch_field).value
end
def editing_content
@ -76,8 +76,8 @@ module QA
wait_for_requests
end
def set_target_branch(name)
find_element(:target_branch_field).fill_in(with: name)
def set_source_branch(name)
find_element(:source_branch_field).fill_in(with: name)
end
def current_branch

View File

@ -73,7 +73,7 @@ module QA
show.select_branch_from_dropdown(random_test_string)
aggregate_failures do
expect(show.target_branch_name).to eq(random_test_string), 'Target branch field is not showing expected branch name.'
expect(show.source_branch_name).to eq(random_test_string), 'Branch field is not showing expected branch name.'
expect(show.editing_content).to have_content(random_test_string), 'Editor content does not include expected test string.'
end
@ -81,7 +81,7 @@ module QA
show.select_branch_from_dropdown(project.default_branch)
aggregate_failures do
expect(show.target_branch_name).to eq(project.default_branch), 'Target branch field is not showing expected branch name.'
expect(show.source_branch_name).to eq(project.default_branch), 'Branch field is not showing expected branch name.'
expect(show.editing_content).to have_content(project.default_branch), 'Editor content does not include expected test string.'
end
end

View File

@ -34,8 +34,8 @@ module QA
expect(show).to have_no_new_mr_checkbox
end
# The new MR checkbox is visible after a new target branch name is set
show.set_target_branch(SecureRandom.hex(10))
# The new MR checkbox is visible after a new branch name is set
show.set_source_branch(SecureRandom.hex(10))
expect(show).to have_new_mr_checkbox
show.select_new_mr_checkbox

View File

@ -53,13 +53,13 @@ module QA
it 'creates new pipeline and target branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349005' do
Page::Project::PipelineEditor::Show.perform do |show|
show.write_to_editor(random_test_string)
show.set_target_branch(random_test_string)
show.set_source_branch(random_test_string)
show.submit_changes
Support::Waiter.wait_until { project.pipelines.size > 1 }
aggregate_failures do
expect(show.target_branch_name).to eq(random_test_string)
expect(show.source_branch_name).to eq(random_test_string)
expect(show.current_branch).to eq(random_test_string)
expect(show.editing_content).to have_content(random_test_string)
expect { show.pipeline_id }.to eventually_eq(project.pipelines.pluck(:id).max).within(max_duration: 60, sleep_interval: 3)

View File

@ -53,7 +53,7 @@ RSpec.describe 'Pipeline Editor', :js do
end
it 'displays new branch as selected after commiting on a new branch' do
find('#target-branch-field').set('new_branch', clear: :backspace)
find('#source-branch-field').set('new_branch', clear: :backspace)
page.within('#source-editor-') do
find('textarea').send_keys '123'
@ -112,7 +112,7 @@ RSpec.describe 'Pipeline Editor', :js do
it 'user who creates a MR is taken to the merge request page without warnings' do
expect(page).not_to have_content('New merge request')
find_field('Target Branch').set 'new_branch'
find_field('Branch').set 'new_branch'
find_field('Start a new merge request with these changes').click
click_button 'Commit changes'

View File

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`content_editor/components/toolbar_button displays tertiary, small button with a provided label and icon 1`] = `
"<b-button-stub size=\\"sm\\" variant=\\"default\\" type=\\"button\\" tag=\\"button\\" aria-label=\\"Bold\\" title=\\"Bold\\" class=\\"gl-button btn-default-tertiary btn-icon\\">
exports[`content_editor/components/toolbar_button displays tertiary, medium button with a provided label and icon 1`] = `
"<b-button-stub size=\\"md\\" variant=\\"default\\" type=\\"button\\" tag=\\"button\\" aria-label=\\"Bold\\" title=\\"Bold\\" class=\\"gl-button btn-default-tertiary btn-icon\\">
<!---->
<gl-icon-stub name=\\"bold\\" size=\\"16\\" class=\\"gl-button-icon\\"></gl-icon-stub>
<!---->

View File

@ -2,13 +2,13 @@ import { BubbleMenu } from '@tiptap/vue-2';
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import Vue from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import CodeBlockBubbleMenu from '~/content_editor/components/code_block_bubble_menu.vue';
import CodeBlockBubbleMenu from '~/content_editor/components/bubble_menus/code_block.vue';
import eventHubFactory from '~/helpers/event_hub_factory';
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
import codeBlockLanguageLoader from '~/content_editor/services/code_block_language_loader';
import { createTestEditor, emitEditorEvent } from '../test_utils';
import { createTestEditor, emitEditorEvent } from '../../test_utils';
describe('content_editor/components/code_block_bubble_menu', () => {
describe('content_editor/components/bubble_menus/code_block', () => {
let wrapper;
let tiptapEditor;
let bubbleMenu;

View File

@ -1,15 +1,15 @@
import { BubbleMenu } from '@tiptap/vue-2';
import { mockTracking } from 'helpers/tracking_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import FormattingBubbleMenu from '~/content_editor/components/formatting_bubble_menu.vue';
import FormattingBubbleMenu from '~/content_editor/components/bubble_menus/formatting.vue';
import {
BUBBLE_MENU_TRACKING_ACTION,
CONTENT_EDITOR_TRACKING_LABEL,
} from '~/content_editor/constants';
import { createTestEditor } from '../test_utils';
import { createTestEditor } from '../../test_utils';
describe('content_editor/components/formatting_bubble_menu', () => {
describe('content_editor/components/bubble_menus/formatting', () => {
let wrapper;
let trackingSpy;
let tiptapEditor;

View File

@ -4,7 +4,7 @@ import ContentEditor from '~/content_editor/components/content_editor.vue';
import ContentEditorAlert from '~/content_editor/components/content_editor_alert.vue';
import ContentEditorProvider from '~/content_editor/components/content_editor_provider.vue';
import EditorStateObserver from '~/content_editor/components/editor_state_observer.vue';
import FormattingBubbleMenu from '~/content_editor/components/formatting_bubble_menu.vue';
import FormattingBubbleMenu from '~/content_editor/components/bubble_menus/formatting.vue';
import TopToolbar from '~/content_editor/components/top_toolbar.vue';
import LoadingIndicator from '~/content_editor/components/loading_indicator.vue';
import { emitEditorEvent } from '../test_utils';

View File

@ -46,7 +46,7 @@ describe('content_editor/components/toolbar_button', () => {
wrapper.destroy();
});
it('displays tertiary, small button with a provided label and icon', () => {
it('displays tertiary, medium button with a provided label and icon', () => {
buildWrapper();
expect(findButton().html()).toMatchSnapshot();

View File

@ -21,6 +21,7 @@ describe('Job Status Token', () => {
value: {
data: '',
},
cursorPosition: 'start',
};
const createComponent = () => {

View File

@ -11,7 +11,10 @@ describe('TokenWithLoadingState', () => {
const initWrapper = (props = {}, options) => {
wrapper = shallowMount(TokenWithLoadingState, {
propsData: props,
propsData: {
cursorPosition: 'start',
...props,
},
...options,
});
};

View File

@ -11,7 +11,10 @@ describe('packages_filter', () => {
const mountComponent = ({ attrs, listeners } = {}) => {
wrapper = shallowMount(component, {
attrs,
attrs: {
cursorPosition: 'start',
...attrs,
},
listeners,
});
};

Some files were not shown because too many files have changed in this diff Show More