Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-02-08 12:09:20 +00:00
parent 1c6e8c1498
commit 9e74a704bc
82 changed files with 1299 additions and 971 deletions

View File

@ -1 +1 @@
ac9d905cb3e40b2c7cdd5369d858d608c95cf168
320f41869d84d64ebbec8d3e0febfb37eca05ffb

View File

@ -1,97 +1,50 @@
<script>
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { __, s__ } from '~/locale';
import { ASCENDING_ODER, DESCENDING_ORDER } from '../constants';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import getTableHeaders from '../utils';
import PackageTypeToken from './tokens/package_type_token.vue';
export default {
components: {
GlSorting,
GlSortingItem,
GlFilteredSearch,
},
tokens: [
{
type: 'type',
icon: 'package',
title: s__('PackageRegistry|Type'),
unique: true,
token: PackageTypeToken,
operators: [{ value: '=', description: __('is'), default: 'true' }],
},
],
components: { RegistrySearch },
computed: {
...mapState({
isGroupPage: (state) => state.config.isGroupPage,
orderBy: (state) => state.sorting.orderBy,
sort: (state) => state.sorting.sort,
sorting: (state) => state.sorting,
filter: (state) => state.filter,
}),
internalFilter: {
get() {
return this.filter;
},
set(value) {
this.setFilter(value);
},
},
sortText() {
const field = this.sortableFields.find((s) => s.orderBy === this.orderBy);
return field ? field.label : '';
},
sortableFields() {
return getTableHeaders(this.isGroupPage);
},
isSortAscending() {
return this.sort === ASCENDING_ODER;
},
tokens() {
return [
{
type: 'type',
icon: 'package',
title: s__('PackageRegistry|Type'),
unique: true,
token: PackageTypeToken,
operators: [{ value: '=', description: __('is'), default: 'true' }],
},
];
},
},
methods: {
...mapActions(['setSorting', 'setFilter']),
onDirectionChange() {
const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER;
this.setSorting({ sort });
this.$emit('sort:changed');
},
onSortItemClick(item) {
this.setSorting({ orderBy: item });
this.$emit('sort:changed');
},
clearSearch() {
this.setFilter([]);
this.$emit('filter:changed');
updateSorting(newValue) {
this.setSorting(newValue);
this.$emit('update');
},
},
};
</script>
<template>
<div class="gl-display-flex gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100">
<gl-filtered-search
v-model="internalFilter"
class="gl-mr-4 gl-flex-fill-1"
:placeholder="__('Filter results')"
:available-tokens="tokens"
@submit="$emit('filter:changed')"
@clear="clearSearch"
/>
<gl-sorting
:text="sortText"
:is-ascending="isSortAscending"
@sortDirectionChange="onDirectionChange"
>
<gl-sorting-item
v-for="item in sortableFields"
ref="packageListSortItem"
:key="item.orderBy"
@click="onSortItemClick(item.orderBy)"
>
{{ item.label }}
</gl-sorting-item>
</gl-sorting>
</div>
<registry-search
:filter="filter"
:sorting="sorting"
:tokens="$options.tokens"
:sortable-fields="sortableFields"
@sorting:changed="updateSorting"
@filter:changed="setFilter"
@filter:submit="$emit('update')"
/>
</template>

View File

@ -75,7 +75,7 @@ export default {
<template>
<div>
<package-title :package-help-url="packageHelpUrl" :packages-count="packagesCount" />
<package-search @sort:changed="requestPackagesList" @filter:changed="requestPackagesList" />
<package-search @update="requestPackagesList" />
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
<template #empty-state>

View File

@ -26,9 +26,6 @@ export const LIST_LABEL_PACKAGE_TYPE = __('Type');
export const LIST_LABEL_CREATED_AT = __('Published');
export const LIST_LABEL_ACTIONS = '';
export const ASCENDING_ODER = 'asc';
export const DESCENDING_ORDER = 'desc';
// The following is not translated because it is used to build a JavaScript exception error message
export const MISSING_DELETE_PATH_ERROR = 'Missing delete_api_path link';

View File

@ -128,12 +128,9 @@ export default {
</template>
<template #content>
<terraform-plan
v-for="(plan, key) in plansObject"
:key="key"
:plan="plan"
class="mr-widget-body"
/>
<div class="mr-widget-body gl-pb-1">
<terraform-plan v-for="(plan, key) in plansObject" :key="key" :plan="plan" />
</div>
</template>
</mr-widget-expanable-section>
</section>

View File

@ -64,16 +64,16 @@ export default {
</script>
<template>
<div class="gl-display-flex">
<div class="gl-display-flex gl-pb-3">
<span
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-mr-3 gl-align-self-start gl-mt-1"
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-px-2"
>
<gl-icon :name="iconType" :size="18" data-testid="change-type-icon" />
<gl-icon :name="iconType" :size="16" data-testid="change-type-icon" />
</span>
<div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row">
<div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column">
<p class="gl-m-0 gl-pr-1">
<div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row gl-pl-3">
<div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column gl-pr-3">
<p class="gl-mb-3 gl-line-height-normal">
<gl-sprintf :message="reportHeaderText">
<template #name>
<strong>{{ plan.job_name }}</strong>
@ -81,7 +81,7 @@ export default {
</gl-sprintf>
</p>
<p class="gl-m-0">
<p class="gl-mb-3 gl-line-height-normal">
<gl-sprintf :message="reportChangeText">
<template #addNum>
<strong>{{ addNum }}</strong>

View File

@ -0,0 +1,90 @@
<script>
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
const ASCENDING_ORDER = 'asc';
const DESCENDING_ORDER = 'desc';
export default {
components: {
GlSorting,
GlSortingItem,
GlFilteredSearch,
},
props: {
filter: {
type: Array,
required: true,
},
sorting: {
type: Object,
required: true,
},
tokens: {
type: Array,
required: false,
default: () => [],
},
sortableFields: {
type: Array,
required: true,
},
},
computed: {
internalFilter: {
get() {
return this.filter;
},
set(value) {
this.$emit('filter:changed', value);
},
},
sortText() {
const field = this.sortableFields.find((s) => s.orderBy === this.sorting.orderBy);
return field ? field.label : '';
},
isSortAscending() {
return this.sorting.sort === ASCENDING_ORDER;
},
},
methods: {
onDirectionChange() {
const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ORDER;
this.$emit('sorting:changed', { sort });
},
onSortItemClick(item) {
this.$emit('sorting:changed', { orderBy: item });
},
clearSearch() {
this.$emit('filter:changed', []);
this.$emit('filter:submit');
},
},
};
</script>
<template>
<div class="gl-display-flex gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100">
<gl-filtered-search
v-model="internalFilter"
class="gl-mr-4 gl-flex-fill-1"
:placeholder="__('Filter results')"
:available-tokens="tokens"
@submit="$emit('filter:submit')"
@clear="clearSearch"
/>
<gl-sorting
:text="sortText"
:is-ascending="isSortAscending"
@sortDirectionChange="onDirectionChange"
>
<gl-sorting-item
v-for="item in sortableFields"
ref="packageListSortItem"
:key="item.orderBy"
@click="onSortItemClick(item.orderBy)"
>
{{ item.label }}
</gl-sorting-item>
</gl-sorting>
</div>
</template>

View File

@ -397,6 +397,14 @@ class ProjectsController < Projects::ApplicationController
]
end
def project_setting_attributes
%i[
show_default_award_emojis
squash_option
allow_editing_commit_messages
]
end
def project_params_attributes
[
:allow_merge_on_skipped_pipeline,
@ -434,11 +442,7 @@ class ProjectsController < Projects::ApplicationController
:suggestion_commit_message,
:packages_enabled,
:service_desk_enabled,
project_setting_attributes: %i[
show_default_award_emojis
squash_option
allow_editing_commit_messages
]
project_setting_attributes: project_setting_attributes
] + [project_feature_attributes: project_feature_attributes]
end

View File

@ -1,16 +1,26 @@
# frozen_string_literal: true
# Arguments:
# params:
# project: Project model - Find deployments for this project
# updated_after: DateTime
# updated_before: DateTime
# finished_after: DateTime
# finished_before: DateTime
# environment: String
# status: String (see Deployment.statuses)
# order_by: String (see ALLOWED_SORT_VALUES constant)
# sort: String (asc | desc)
class DeploymentsFinder
attr_reader :project, :params
attr_reader :params
ALLOWED_SORT_VALUES = %w[id iid created_at updated_at ref].freeze
ALLOWED_SORT_VALUES = %w[id iid created_at updated_at ref finished_at].freeze
DEFAULT_SORT_VALUE = 'id'
ALLOWED_SORT_DIRECTIONS = %w[asc desc].freeze
DEFAULT_SORT_DIRECTION = 'asc'
def initialize(project, params = {})
@project = project
def initialize(params = {})
@params = params
end
@ -19,33 +29,20 @@ class DeploymentsFinder
items = by_updated_at(items)
items = by_environment(items)
items = by_status(items)
items = preload_associations(items)
items = by_finished_between(items)
sort(items)
end
private
# rubocop: disable CodeReuse/ActiveRecord
def init_collection
project
.deployments
.includes(
:user,
environment: [],
deployable: {
job_artifacts: [],
pipeline: {
project: {
route: [],
namespace: :route
}
},
project: {
namespace: :route
}
}
)
if params[:project]
params[:project].deployments
else
Deployment.none
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def sort(items)
@ -68,6 +65,12 @@ class DeploymentsFinder
end
end
def by_finished_between(items)
items = items.finished_between(params[:finished_after], params[:finished_before].presence) if params[:finished_after].present?
items
end
def by_status(items)
return items unless params[:status].present?
@ -87,4 +90,27 @@ class DeploymentsFinder
sort_values['id'] = sort_values.delete('created_at') if sort_values['created_at'] # Sorting by `id` produces the same result as sorting by `created_at`
end
end
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(scope)
scope.includes(
:user,
environment: [],
deployable: {
job_artifacts: [],
pipeline: {
project: {
route: [],
namespace: :route
}
},
project: {
namespace: :route
}
}
)
end
# rubocop: enable CodeReuse/ActiveRecord
end
DeploymentsFinder.prepend_if_ee('EE::DeploymentsFinder')

View File

@ -27,11 +27,11 @@ module InProductMarketingHelper
end
def in_product_marketing_logo(track, series)
inline_image_link('mailers/in_product_marketing', "#{track}-#{series}.png", width: '150')
inline_image_link('mailers/in_product_marketing', "#{track}-#{series}.png", { width: '150', style: 'width: 150px;' })
end
def about_link(folder, image, width)
link_to inline_image_link(folder, image, { width: width, alt: s_('InProductMarketing|go to about.gitlab.com') }), 'https://about.gitlab.com/'
link_to inline_image_link(folder, image, { width: width, style: "width: #{width}px;", alt: s_('InProductMarketing|go to about.gitlab.com') }), 'https://about.gitlab.com/'
end
def in_product_marketing_tagline(track, series)
@ -344,7 +344,7 @@ module InProductMarketingHelper
end
def inline_image_link(folder, image, **options)
attachments[image] = File.read(Rails.root.join("app/assets/images", folder, image))
attachments.inline[image] = File.read(Rails.root.join("app/assets/images", folder, image))
image_tag attachments[image].url, **options
end
end

View File

@ -4,8 +4,6 @@ module TreeHelper
include BlobHelper
include WebIdeButtonHelper
FILE_LIMIT = 1_000
# Return an image icon depending on the file type and mode
#
# type - String type of the tree item; either 'folder' or 'file'

View File

@ -228,7 +228,7 @@ module Ci
end
def with_preloads
preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
preload(:job_artifacts_archive, :job_artifacts, :tags, project: [:namespace])
end
end

View File

@ -21,4 +21,4 @@ class ProjectSetting < ApplicationRecord
end
end
ProjectSetting.prepend_if_ee('EE::ProjectSetting')
ProjectSetting.prepend_ee_mod

View File

@ -16,7 +16,7 @@ module Git
wiki.after_post_receive
process_changes
perform_housekeeping if Feature.enabled?(:wiki_housekeeping, wiki.container)
perform_housekeeping
end
private

View File

@ -162,7 +162,7 @@
#main-story.mktEditable{ mktoname: "main-story" }
%table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
%tr
%td{ align: "left", style: "padding: 0px;" }
%td{ align: "left", style: "padding: 0 20px;" }
= about_link('mailers/in_product_marketing', 'gitlab-logo-gray-rgb.png', 200)
%tr
%td{ "aria-hidden" => "true", height: "30", style: "font-size: 0; line-height: 0;" }
@ -187,7 +187,7 @@
%p
= in_product_marketing_progress(@track, @series)
%tr{ style: "background-color: #ffffff;" }
%td{ align: "center", style: "padding:50px 20px 0 20px;" }
%td{ align: "center", style: "padding:75px 20px 25px;" }
= about_link('', 'gitlab_logo.png', 80)
%tr{ style: "background-color: #ffffff;" }
%td{ align: "center", style: "padding:0px ;" }

View File

@ -11,8 +11,8 @@
%h5.gl-mt-0
= _('Add an SSH key')
%p.profile-settings-content
- generate_link_url = help_page_path("ssh/README", anchor: 'generating-a-new-ssh-key-pair')
- existing_link_url = help_page_path("ssh/README", anchor: 'review-existing-ssh-keys')
- generate_link_url = help_page_path("ssh/README", anchor: 'generate-an-ssh-key-pair')
- existing_link_url = help_page_path("ssh/README", anchor: 'see-if-you-have-an-existing-ssh-key-pair')
- generate_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: generate_link_url }
- existing_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: existing_link_url }
= _('To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}.').html_safe % { generate_link_start: generate_link_start, existing_link_start: existing_link_start, link_end: '</a>'.html_safe }

View File

@ -24,3 +24,4 @@
= form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input', data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' }
= form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
= s_('ProjectSettings|All discussions must be resolved')
= render_if_exists 'projects/merge_request_merge_checks_jira_enforcement', form: form, project: @project

View File

@ -0,0 +1,5 @@
---
title: Add tag_list attribute to the JSON output for Jobs API
merge_request: 44859
author: Alon Liszt
type: added

View File

@ -0,0 +1,5 @@
---
title: Update styles for terraform MR widget
merge_request: 52627
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Adds jira issue enforcement field
merge_request: 52896
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Enable housekeeping for project and group wiki repos
merge_request: 53011
author:
type: added

View File

@ -1,8 +1,8 @@
---
name: wiki_housekeeping
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51576
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299343
name: query_deploymenys_via_finished_at_in_vsa
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53050
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300649
milestone: '13.9'
type: development
group: group::editor
group: group::optimize
default_enabled: false

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class AddPreventMergeWithoutJiraIssueToProjectSettings < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
with_lock_retries do
add_column :project_settings, :prevent_merge_without_jira_issue, :boolean, null: false, default: false
end
end
def down
with_lock_retries do
remove_column :project_settings, :prevent_merge_without_jira_issue
end
end
end

View File

@ -0,0 +1 @@
ae84fa35fcc5a0780d86887294a32e250d2ac13dcf607750f834df5828e5bece

View File

@ -16064,6 +16064,7 @@ CREATE TABLE project_settings (
has_confluence boolean DEFAULT false NOT NULL,
has_vulnerabilities boolean DEFAULT false NOT NULL,
allow_editing_commit_messages boolean DEFAULT false NOT NULL,
prevent_merge_without_jira_issue boolean DEFAULT false NOT NULL,
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
);

View File

@ -68,7 +68,7 @@ We have the following documentation to rapidly uplift your GitLab knowledge:
|:--------------------------------------------------------------------------------------------------|:------------|
| [GitLab basics guides](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
| [GitLab workflow overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
| [Get started with GitLab CI/CD](ci/quick_start/README.md) | Quickly implement GitLab CI/CD. |
| [Get started with GitLab CI/CD](ci/quick_start/index.md) | Quickly implement GitLab CI/CD. |
| [Auto DevOps](topics/autodevops/index.md) | Learn more about Auto DevOps in GitLab. |
| [GitLab Markdown](user/markdown.md) | Advanced formatting system (GitLab Flavored Markdown). |

View File

@ -48,7 +48,7 @@ libraries](https://graphql.org/code/#graphql-clients) to consume the
API and avoid manual parsing.
Since there's no fixed endpoints and data model, new abilities can be
added to the API without creating breaking changes. This allows us to
added to the API without creating [breaking changes](../../development/contributing/#breaking-changes). This allows us to
have a versionless API as described in [the GraphQL
documentation](https://graphql.org/learn/best-practices/#versioning).

View File

@ -5737,7 +5737,7 @@ type DastProfileCreatePayload {
"""
The URL of the pipeline that was created. Requires `runAfterCreate` to be set to `true`.
"""
pipelineUrl: String!
pipelineUrl: String
}
"""

View File

@ -15668,13 +15668,9 @@
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null

View File

@ -914,7 +914,7 @@ Autogenerated return type of DastProfileCreate.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `dastProfile` | DastProfile | The created profile. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `pipelineUrl` | String! | The URL of the pipeline that was created. Requires `runAfterCreate` to be set to `true`. |
| `pipelineUrl` | String | The URL of the pipeline that was created. Requires `runAfterCreate` to be set to `true`. |
### DastScannerProfile

View File

@ -54,6 +54,9 @@ Example of response
{"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"}
],
"artifacts_expire_at": "2016-01-23T17:54:27.895Z",
"tag_list": [
"docker runner", "ubuntu18"
],
"id": 7,
"name": "teaspoon",
"pipeline": {
@ -104,6 +107,9 @@ Example of response
"finished_at": "2015-12-24T17:54:24.921Z",
"duration": 0.192,
"artifacts_expire_at": "2016-01-23T17:54:24.921Z",
"tag_list": [
"docker runner", "win10-2004"
],
"id": 6,
"name": "rspec:other",
"pipeline": {
@ -179,6 +185,9 @@ Example of response
"finished_at": "2015-12-24T17:54:24.921Z",
"duration": 0.192,
"artifacts_expire_at": "2016-01-23T17:54:24.921Z",
"tag_list": [
"docker runner", "ubuntu18"
],
"id": 6,
"name": "rspec:other",
"pipeline": {
@ -239,6 +248,9 @@ Example of response
{"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"}
],
"artifacts_expire_at": "2016-01-23T17:54:27.895Z",
"tag_list": [
"docker runner", "ubuntu18"
],
"id": 7,
"name": "teaspoon",
"pipeline": {
@ -399,6 +411,9 @@ Example of response
"finished_at": "2015-12-24T17:54:31.198Z",
"duration": 0.465,
"artifacts_expire_at": "2016-01-23T17:54:31.198Z",
"tag_list": [
"docker runner", "macos-10.15"
],
"id": 8,
"name": "rubocop",
"pipeline": {

View File

@ -55,7 +55,7 @@ at the repository's root. This file creates a [pipeline](pipelines/index.md), wh
To get started with GitLab CI/CD, we recommend you read through
the following documents:
- [Get started with GitLab CI/CD](quick_start/README.md).
- [Get started with GitLab CI/CD](quick_start/index.md).
- [Fundamental pipeline architectures](pipelines/pipeline_architectures.md).
- [GitLab CI/CD basic workflow](introduction/index.md#basic-cicd-workflow).
- [Step-by-step guide for writing `.gitlab-ci.yml` for the first time](../user/project/pages/getting_started/pages_from_scratch.md).
@ -75,7 +75,7 @@ to your needs:
While building your `.gitlab-ci.yml`, you can use the [CI/CD configuration visualization](pipeline_editor/index.md#visualize-ci-configuration) to facilitate your writing experience.
For a broader overview, see the [CI/CD getting started](quick_start/README.md) guide.
For a broader overview, see the [CI/CD getting started](quick_start/index.md) guide.
After you're familiar with how GitLab CI/CD works, see the
[`.gitlab-ci.yml` full reference](yaml/README.md)
@ -107,7 +107,7 @@ GitLab CI/CD supports numerous configuration options:
| [Schedule pipelines](pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-cicd-configuration-path) | Define a custom path for the CI/CD configuration file. |
| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules. |
| [SSH keys for CI/CD](ssh_keys/README.md) | Using SSH keys in your CI pipelines. |
| [SSH keys for CI/CD](ssh_keys/index.md) | Using SSH keys in your CI pipelines. |
| [Pipeline triggers](triggers/README.md) | Trigger pipelines through the API. |
| [Pipelines for Merge Requests](merge_request_pipelines/index.md) | Design a pipeline structure for running a pipeline in merge requests. |
| [Integrate with Kubernetes clusters](../user/project/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
@ -126,12 +126,12 @@ Its feature set is listed on the table below according to DevOps stages.
|:------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|
| **Configure** | |
| [Auto DevOps](../topics/autodevops/index.md) | Set up your app's entire lifecycle. |
| [ChatOps](chatops/README.md) | Trigger CI jobs from chat, with results sent back to the channel. |
| [ChatOps](chatops/index.md) | Trigger CI jobs from chat, with results sent back to the channel. |
|-------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------|
| **Verify** | |
| [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
| [Load Performance Testing](../user/project/merge_requests/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
| [CI services](services/README.md) | Link Docker containers with your base image. |
| [CI services](services/index.md) | Link Docker containers with your base image. |
| [Code Quality](../user/project/merge_requests/code_quality.md) | Analyze your source code quality. |
| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) **(PREMIUM)** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and Bitbucket Cloud. |
| [Interactive Web Terminals](interactive_web_terminal/index.md) **(FREE SELF)** | Open an interactive web terminal to debug the running jobs. |

View File

@ -1,116 +1,8 @@
---
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
type: index, concepts, howto
redirect_to: 'index.md'
---
# GitLab ChatOps **(FREE)**
This document was moved to [another location](index.md).
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Free](https://about.gitlab.com/pricing/) in 11.9.
GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
place in chat services. Having a method to run CI/CD jobs with output
posted back to the channel can significantly augment your team's workflow.
## How GitLab ChatOps works
GitLab ChatOps is built upon [GitLab CI/CD](../README.md) and
[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.md).
ChatOps provides a `run` action for [slash commands](../../integration/slash_commands.md)
with the following arguments:
- A `<job name>` to execute.
- The `<job arguments>`.
ChatOps passes the following [CI/CD variables](../variables/README.md#predefined-environment-variables)
to the job:
- `CHAT_INPUT` contains any additional arguments.
- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
When executed, ChatOps looks up the specified job name and attempts to match it
to a corresponding job in [`.gitlab-ci.yml`](../yaml/README.md). If a matching job
is found on `master`, a pipeline containing only that job is scheduled. After the
job completes:
- If the job completes in *less than 30 minutes*, the ChatOps sends the job's output to Slack.
- If the job completes in *more than 30 minutes*, the job must use the
[Slack API](https://api.slack.com/) to send data to the channel.
To use the `run` command, you must have
[Developer access or above](../../user/permissions.md#project-members-permissions).
If a job shouldn't be able to be triggered from chat, you can set the job to `except: [chat]`.
## Best practices for ChatOps CI jobs
Since ChatOps is built upon GitLab CI/CD, the job has all the same features and
functions available. Consider these best practices when creating ChatOps jobs:
- GitLab strongly recommends you set `only: [chat]` so the job does not run as part
of the standard CI pipeline.
- If the job is set to `when: manual`, ChatOps creates the pipeline, but the job waits to be started.
- ChatOps provides limited support for access control. If the user triggering the
slash command has [Developer access or above](../../user/permissions.md#project-members-permissions)
in the project, the job runs. The job itself can use existing
[CI/CD variables](../variables/README.md#predefined-environment-variables) like
`GITLAB_USER_ID` to perform additional rights validation, but
these variables can be [overridden](../variables/README.md#priority-of-environment-variables).
### Controlling the ChatOps reply
The output for jobs with a single command is sent to the channel as a reply. For
example, the chat reply of the following job is `Hello World` in the channel:
```yaml
hello-world:
stage: chatops
only: [chat]
script:
- echo "Hello World"
```
Jobs that contain multiple commands (or `before_script`) return additional
content in the chat reply. In these cases, both the commands and their output are
included, with the commands wrapped in ANSI color codes.
To selectively reply with the output of one command, its output must be bounded by
the `chat_reply` section. For example, the following job lists the files in the
current directory:
```yaml
ls:
stage: chatops
only: [chat]
script:
- echo "This command will not be shown."
- echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K"
```
## GitLab ChatOps examples
The GitLab.com team created a repository of [common ChatOps scripts](https://gitlab.com/gitlab-com/chatops)
they use to interact with our Production instance of GitLab. Administrators of
other GitLab instances may find them useful. They can serve as inspiration for ChatOps
scripts you can write to interact with your own applications.
## GitLab ChatOps icon
The [official GitLab ChatOps icon](img/gitlab-chatops-icon.png) is available for download.
You can find and download the official GitLab ChatOps icon here.
![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
<!-- This redirect file can be deleted after 2021-05-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->

116
doc/ci/chatops/index.md Normal file
View File

@ -0,0 +1,116 @@
---
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
type: index, concepts, howto
---
# GitLab ChatOps **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Free](https://about.gitlab.com/pricing/) in 11.9.
GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
place in chat services. Having a method to run CI/CD jobs with output
posted back to the channel can significantly augment your team's workflow.
## How GitLab ChatOps works
GitLab ChatOps is built upon [GitLab CI/CD](../README.md) and
[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.md).
ChatOps provides a `run` action for [slash commands](../../integration/slash_commands.md)
with the following arguments:
- A `<job name>` to execute.
- The `<job arguments>`.
ChatOps passes the following [CI/CD variables](../variables/README.md#predefined-environment-variables)
to the job:
- `CHAT_INPUT` contains any additional arguments.
- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
When executed, ChatOps looks up the specified job name and attempts to match it
to a corresponding job in [`.gitlab-ci.yml`](../yaml/README.md). If a matching job
is found on `master`, a pipeline containing only that job is scheduled. After the
job completes:
- If the job completes in *less than 30 minutes*, the ChatOps sends the job's output to Slack.
- If the job completes in *more than 30 minutes*, the job must use the
[Slack API](https://api.slack.com/) to send data to the channel.
To use the `run` command, you must have
[Developer access or above](../../user/permissions.md#project-members-permissions).
If a job shouldn't be able to be triggered from chat, you can set the job to `except: [chat]`.
## Best practices for ChatOps CI jobs
Since ChatOps is built upon GitLab CI/CD, the job has all the same features and
functions available. Consider these best practices when creating ChatOps jobs:
- GitLab strongly recommends you set `only: [chat]` so the job does not run as part
of the standard CI pipeline.
- If the job is set to `when: manual`, ChatOps creates the pipeline, but the job waits to be started.
- ChatOps provides limited support for access control. If the user triggering the
slash command has [Developer access or above](../../user/permissions.md#project-members-permissions)
in the project, the job runs. The job itself can use existing
[CI/CD variables](../variables/README.md#predefined-environment-variables) like
`GITLAB_USER_ID` to perform additional rights validation, but
these variables can be [overridden](../variables/README.md#priority-of-environment-variables).
### Controlling the ChatOps reply
The output for jobs with a single command is sent to the channel as a reply. For
example, the chat reply of the following job is `Hello World` in the channel:
```yaml
hello-world:
stage: chatops
only: [chat]
script:
- echo "Hello World"
```
Jobs that contain multiple commands (or `before_script`) return additional
content in the chat reply. In these cases, both the commands and their output are
included, with the commands wrapped in ANSI color codes.
To selectively reply with the output of one command, its output must be bounded by
the `chat_reply` section. For example, the following job lists the files in the
current directory:
```yaml
ls:
stage: chatops
only: [chat]
script:
- echo "This command will not be shown."
- echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K"
```
## GitLab ChatOps examples
The GitLab.com team created a repository of [common ChatOps scripts](https://gitlab.com/gitlab-com/chatops)
they use to interact with our Production instance of GitLab. Administrators of
other GitLab instances may find them useful. They can serve as inspiration for ChatOps
scripts you can write to interact with your own applications.
## GitLab ChatOps icon
The [official GitLab ChatOps icon](img/gitlab-chatops-icon.png) is available for download.
You can find and download the official GitLab ChatOps icon here.
![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->

View File

@ -41,7 +41,7 @@ repositories:
1. Paste the token into the **Personal access token** field and click **List
Repositories**. Click **Connect** to select the repository.
1. In GitHub, add a `.gitlab-ci.yml` to [configure GitLab CI/CD](../quick_start/README.md).
1. In GitHub, add a `.gitlab-ci.yml` to [configure GitLab CI/CD](../quick_start/index.md).
GitLab:

View File

@ -1,18 +1,8 @@
---
stage: Verify
group: Continuous Integration
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
comments: false
type: index
redirect_to: 'index.md'
---
# Docker integration
This document was moved to [another location](index.md).
GitLab CI/CD can be combined with [Docker](https://www.docker.com) to enable
integration between the two.
The following documentation is available for using GitLab CI/CD with Docker:
- [Building Docker images with GitLab CI/CD](using_docker_build.md).
- [Using Docker images](using_docker_images.md).
- [Building images with kaniko and GitLab CI/CD](using_kaniko.md).
<!-- This redirect file can be deleted after 2021-05-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->

18
doc/ci/docker/index.md Normal file
View File

@ -0,0 +1,18 @@
---
stage: Verify
group: Continuous Integration
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
comments: false
type: index
---
# Docker integration
GitLab CI/CD can be combined with [Docker](https://www.docker.com) to enable
integration between the two.
The following documentation is available for using GitLab CI/CD with Docker:
- [Building Docker images with GitLab CI/CD](using_docker_build.md).
- [Using Docker images](using_docker_images.md).
- [Building images with kaniko and GitLab CI/CD](using_kaniko.md).

View File

@ -91,7 +91,7 @@ Services inherit the same DNS servers, search domains, and additional hosts as
the CI container itself.
You can see some widely used services examples in the relevant documentation of
[CI services examples](../services/README.md).
[CI services examples](../services/index.md).
### How services are linked to the job

View File

@ -13,7 +13,7 @@ To effectively use GitLab CI/CD, you need:
of your project.
- A [runner](runners/README.md) properly set up.
You can read our [quick start guide](quick_start/README.md) to get you started.
You can read our [quick start guide](quick_start/index.md) to get you started.
If you are using an external CI/CD server like Jenkins or Drone CI, it is advised
to disable GitLab CI/CD in order to not have any conflicts with the commits status

View File

@ -544,7 +544,7 @@ services:
...
```
If you wish to test your app with different PHP versions and [database management systems](../../services/README.md), you can define different `image` and `services` keywords for each test job.
If you wish to test your app with different PHP versions and [database management systems](../../services/index.md), you can define different `image` and `services` keywords for each test job.
#### Variables
@ -589,7 +589,7 @@ unit_test:
#### Deploy to production
The job `deploy_production` will deploy the app to the production server.
To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/README.md#ssh-keys-when-using-the-docker-executor).
To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/index.md#ssh-keys-when-using-the-docker-executor).
If the SSH keys have added successfully, we can run Envoy.
As mentioned before, GitLab supports [Continuous Delivery](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery) methods as well.

View File

@ -241,7 +241,7 @@ before_script:
## Access private packages or dependencies
If your test suite needs to access a private repository, you need to configure
the [SSH keys](../ssh_keys/README.md) to be able to clone it.
the [SSH keys](../ssh_keys/index.md) to be able to clone it.
## Use databases or other services
@ -250,7 +250,7 @@ run. If you're using the Docker executor, you can leverage Docker's ability to
link to other containers. With GitLab Runner, this can be achieved by defining
a `service`.
This functionality is covered in [the CI services](../services/README.md)
This functionality is covered in [the CI services](../services/index.md)
documentation.
## Testing things locally

View File

@ -13,7 +13,7 @@ type: reference
> are encouraged to upgrade your GitLab instance if you haven't done already.
> If you are **not** using GitLab 8.12 or higher, you would need to work your way
> around submodules in order to access the sources of e.g., `gitlab.com/group/project`
> with the use of [SSH keys](ssh_keys/README.md).
> with the use of [SSH keys](ssh_keys/index.md).
> - With GitLab 8.12 onward, your permissions are used to evaluate what a CI job
> can access. More information about how this system works can be found in the
> [Jobs permissions model](../user/permissions.md#job-permissions).

View File

@ -15,7 +15,7 @@ comparison to see what's different.
We have collected several resources that you may find useful before starting to migrate.
The [Quick Start Guide](../quick_start/README.md) is a good overview of how GitLab CI/CD works. You may also be interested in [Auto DevOps](../../topics/autodevops/index.md) which can be used to build, test, and deploy your applications with little to no configuration needed at all.
The [Quick Start Guide](../quick_start/index.md) is a good overview of how GitLab CI/CD works. You may also be interested in [Auto DevOps](../../topics/autodevops/index.md) which can be used to build, test, and deploy your applications with little to no configuration needed at all.
For advanced CI/CD teams, [custom project templates](../../user/admin_area/custom_project_templates.md) can enable the reuse of pipeline configurations.

View File

@ -15,11 +15,11 @@ before diving in. Think of this page as a "GitLab CI/CD for Jenkins Users" guide
The following list of recommended steps was created after observing organizations
that were able to quickly complete this migration:
1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/README.md) and [important product differences](#important-product-differences).
1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/index.md) and [important product differences](#important-product-differences).
1. Learn the importance of [managing the organizational transition](#managing-the-organizational-transition).
1. [Add runners](../runners/README.md) to your GitLab instance.
1. Educate and enable your developers to independently perform the following steps in their projects:
1. Review the [Quick Start Guide](../quick_start/README.md) and [Pipeline Configuration Reference](../yaml/README.md).
1. Review the [Quick Start Guide](../quick_start/index.md) and [Pipeline Configuration Reference](../yaml/README.md).
1. Use the [Jenkins Wrapper](#jenkinsfile-wrapper) to temporarily maintain fragile Jenkins jobs.
1. Migrate the build and CI jobs and configure them to show results directly in your merge requests. They can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point, and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#using-components-of-auto-devops) the configuration as needed.
1. Add [Review Apps](../review_apps/index.md).
@ -79,7 +79,7 @@ There are some high level differences between the products worth mentioning:
- from the [GitLab UI](../pipelines/index.md#run-a-pipeline-manually)
- by [API call](../triggers/README.md)
- by [webhook](../triggers/README.md#triggering-a-pipeline-from-a-webhook)
- by [ChatOps](../chatops/README.md)
- by [ChatOps](../chatops/index.md)
- You can control which jobs run in which cases, depending on how they are triggered,
with the [`rules` syntax](../yaml/README.md#rules).

View File

@ -28,7 +28,7 @@ From the pipeline editor page you can:
- [Commit](#commit-changes-to-ci-configuration) the changes to a specific branch.
NOTE:
You must already have [a `.gitlab-ci.yml` file](../quick_start/README.md#create-a-gitlab-ciyml-file)
You must already have [a `.gitlab-ci.yml` file](../quick_start/index.md#create-a-gitlab-ciyml-file)
on the default branch (usually "master") of your project to use the editor.
## Validate CI configuration

View File

@ -20,7 +20,7 @@ to use pipeline features that improve efficiency right away, and get a faster so
development lifecycle earlier.
First ensure you are familiar with [GitLab CI/CD fundamentals](../introduction/index.md)
and understand the [quick start guide](../quick_start/README.md).
and understand the [quick start guide](../quick_start/index.md).
## Identify bottlenecks and common failures
@ -235,7 +235,7 @@ Methods to reduce Docker image size:
to analyze and shrink images.
To simplify Docker image management, you can create a dedicated group for managing
[Docker images](../docker/README.md) and test, build and publish them with CI/CD pipelines.
[Docker images](../docker/index.md) and test, build and publish them with CI/CD pipelines.
## Test, document, and learn

View File

@ -1,157 +1,8 @@
---
stage: Verify
group: Continuous Integration
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
type: reference
redirect_to: 'index.md'
---
# Get started with GitLab CI/CD
This document was moved to [another location](index.md).
Use this document to get started with
GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/).
Before you start, make sure you have:
- A project in GitLab that you would like to use CI/CD for.
- Maintainer or owner access for the project.
If you are migrating from another CI/CD tool, view this documentation:
- [Migrate from CircleCI](../migration/circleci.md).
- [Migrate from Jenkins](../migration/jenkins.md).
## CI/CD process overview
To use GitLab CI/CD:
1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs.
If you don't have a runner, [install GitLab Runner](https://docs.gitlab.com/runner/install/)
and [register a runner](https://docs.gitlab.com/runner/register/) for your instance, project, or group.
1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file)
at the root of your repository. This file is where you define your CI/CD jobs.
When you commit the file to your repository, the runner runs your jobs.
The job results [are displayed in a pipeline](#view-the-status-of-your-pipeline-and-jobs).
### Ensure you have runners available
In GitLab, runners are agents that run your CI/CD jobs.
You might already have runners available for your project, including
[shared runners](../runners/README.md#shared-runners), which are
available to all projects in your GitLab instance.
To view available runners:
- Go to **Settings > CI/CD** and expand **Runners**.
As long as you have at least one runner that's active, with a green circle next to it,
you have a runner available to process your jobs.
If no runners are listed on the **Runners** page in the UI, you or an administrator
must [install GitLab Runner](https://docs.gitlab.com/runner/install/) and
[register](https://docs.gitlab.com/runner/register/) at least one runner.
If you are testing CI/CD, you can install GitLab Runner and register runners on your local machine.
When your CI/CD jobs run, they run on your local machine.
### Create a `.gitlab-ci.yml` file
The `.gitlab-ci.yml` file is a [YAML](https://en.wikipedia.org/wiki/YAML) file where
you configure specific instructions for GitLab CI/CD.
In this file, you define:
- The structure and order of jobs that the runner should execute.
- The decisions the runner should make when specific conditions are encountered.
For example, you might want to run a suite of tests when you commit to
any branch except `master`. When you commit to `master`, you want
to run the same suite, but also publish your application.
All of this is defined in the `.gitlab-ci.yml` file.
To create a `.gitlab-ci.yml` file:
1. Go to **Project overview > Details**.
1. Above the file list, select the branch you want to commit to,
click the plus icon, then select **New file**:
![New file](img/new_file_v13_6.png)
1. For the **Filename**, type `.gitlab-ci.yml` and in the larger window,
paste this sample code:
```yaml
build-job:
stage: build
script:
- echo "Hello, $GITLAB_USER_LOGIN!"
test-job1:
stage: test
script:
- echo "This job tests something"
test-job2:
stage: test
script:
- echo "This job tests something, but takes more time than test-job1."
- echo "After the echo commands complete, it runs the sleep command for 20 seconds"
- echo "which simulates a test that runs 20 seconds longer than test-job1"
- sleep 20
deploy-prod:
stage: deploy
script:
- echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
```
`$GITLAB_USER_LOGIN` and `$CI_COMMIT_BRANCH` are
[predefined variables](../variables/predefined_variables.md)
that populate when the job runs.
1. Click **Commit changes**.
The pipeline starts when the commit is committed.
#### `.gitlab-ci.yml` tips
- If you want the runner to use a Docker image to run the jobs, edit the `.gitlab-ci.yml` file
to include your image name:
```yaml
default:
image: ruby:2.7.2
```
This command tells the runner to use a Ruby image from Docker Hub.
- To validate your `.gitlab-ci.yml` file, use the
[CI Lint tool](../lint.md), which is available in every project.
- You can also use [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration) to
view a graphical representation of your `.gitlab-ci.yml` file.
- For the complete `.gitlab-ci.yml` syntax, see
[the `.gitlab-ci.yml` reference topic](../yaml/README.md).
### View the status of your pipeline and jobs
When you committed your changes, a pipeline started.
To view your pipeline:
- Go **CI/CD > Pipelines**.
A pipeline with three stages should be displayed:
![Three stages](img/three_stages_v13_6.png)
- To view a visual representation of your pipeline, click the pipeline ID.
![Pipeline graph](img/pipeline_graph_v13_6.png)
- To view details of a job, click the job name, for example, `deploy-prod`.
![Job details](img/job_details_v13_6.png)
If the job status is `stuck`, check to ensure a runner is probably configured for the project.
<!-- This redirect file can be deleted after 2021-05-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->

157
doc/ci/quick_start/index.md Normal file
View File

@ -0,0 +1,157 @@
---
stage: Verify
group: Continuous Integration
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
type: reference
---
# Get started with GitLab CI/CD
Use this document to get started with
GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/).
Before you start, make sure you have:
- A project in GitLab that you would like to use CI/CD for.
- Maintainer or owner access for the project.
If you are migrating from another CI/CD tool, view this documentation:
- [Migrate from CircleCI](../migration/circleci.md).
- [Migrate from Jenkins](../migration/jenkins.md).
## CI/CD process overview
To use GitLab CI/CD:
1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs.
If you don't have a runner, [install GitLab Runner](https://docs.gitlab.com/runner/install/)
and [register a runner](https://docs.gitlab.com/runner/register/) for your instance, project, or group.
1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file)
at the root of your repository. This file is where you define your CI/CD jobs.
When you commit the file to your repository, the runner runs your jobs.
The job results [are displayed in a pipeline](#view-the-status-of-your-pipeline-and-jobs).
### Ensure you have runners available
In GitLab, runners are agents that run your CI/CD jobs.
You might already have runners available for your project, including
[shared runners](../runners/README.md#shared-runners), which are
available to all projects in your GitLab instance.
To view available runners:
- Go to **Settings > CI/CD** and expand **Runners**.
As long as you have at least one runner that's active, with a green circle next to it,
you have a runner available to process your jobs.
If no runners are listed on the **Runners** page in the UI, you or an administrator
must [install GitLab Runner](https://docs.gitlab.com/runner/install/) and
[register](https://docs.gitlab.com/runner/register/) at least one runner.
If you are testing CI/CD, you can install GitLab Runner and register runners on your local machine.
When your CI/CD jobs run, they run on your local machine.
### Create a `.gitlab-ci.yml` file
The `.gitlab-ci.yml` file is a [YAML](https://en.wikipedia.org/wiki/YAML) file where
you configure specific instructions for GitLab CI/CD.
In this file, you define:
- The structure and order of jobs that the runner should execute.
- The decisions the runner should make when specific conditions are encountered.
For example, you might want to run a suite of tests when you commit to
any branch except `master`. When you commit to `master`, you want
to run the same suite, but also publish your application.
All of this is defined in the `.gitlab-ci.yml` file.
To create a `.gitlab-ci.yml` file:
1. Go to **Project overview > Details**.
1. Above the file list, select the branch you want to commit to,
click the plus icon, then select **New file**:
![New file](img/new_file_v13_6.png)
1. For the **Filename**, type `.gitlab-ci.yml` and in the larger window,
paste this sample code:
```yaml
build-job:
stage: build
script:
- echo "Hello, $GITLAB_USER_LOGIN!"
test-job1:
stage: test
script:
- echo "This job tests something"
test-job2:
stage: test
script:
- echo "This job tests something, but takes more time than test-job1."
- echo "After the echo commands complete, it runs the sleep command for 20 seconds"
- echo "which simulates a test that runs 20 seconds longer than test-job1"
- sleep 20
deploy-prod:
stage: deploy
script:
- echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
```
`$GITLAB_USER_LOGIN` and `$CI_COMMIT_BRANCH` are
[predefined variables](../variables/predefined_variables.md)
that populate when the job runs.
1. Click **Commit changes**.
The pipeline starts when the commit is committed.
#### `.gitlab-ci.yml` tips
- If you want the runner to use a Docker image to run the jobs, edit the `.gitlab-ci.yml` file
to include your image name:
```yaml
default:
image: ruby:2.7.2
```
This command tells the runner to use a Ruby image from Docker Hub.
- To validate your `.gitlab-ci.yml` file, use the
[CI Lint tool](../lint.md), which is available in every project.
- You can also use [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration) to
view a graphical representation of your `.gitlab-ci.yml` file.
- For the complete `.gitlab-ci.yml` syntax, see
[the `.gitlab-ci.yml` reference topic](../yaml/README.md).
### View the status of your pipeline and jobs
When you committed your changes, a pipeline started.
To view your pipeline:
- Go **CI/CD > Pipelines**.
A pipeline with three stages should be displayed:
![Three stages](img/three_stages_v13_6.png)
- To view a visual representation of your pipeline, click the pipeline ID.
![Pipeline graph](img/pipeline_graph_v13_6.png)
- To view details of a job, click the job name, for example, `deploy-prod`.
![Job details](img/job_details_v13_6.png)
If the job status is `stuck`, check to ensure a runner is probably configured for the project.

View File

@ -1,21 +1,8 @@
---
stage: Verify
group: Runner
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
comments: false
type: index
redirect_to: 'index.md'
---
# GitLab CI services examples
This document was moved to [another location](index.md).
The [`services`](../docker/using_docker_images.md#what-is-a-service)
keyword defines a Docker image that runs during a `job` linked to the
Docker image that the image keyword defines. This allows you to access
the service image during build time.
The service image can run any application, but the most common use
case is to run a database container, for example:
- [Using MySQL](mysql.md)
- [Using PostgreSQL](postgres.md)
- [Using Redis](redis.md)
<!-- This redirect file can be deleted after 2021-05-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->

21
doc/ci/services/index.md Normal file
View File

@ -0,0 +1,21 @@
---
stage: Verify
group: Runner
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
comments: false
type: index
---
# GitLab CI services examples
The [`services`](../docker/using_docker_images.md#what-is-a-service)
keyword defines a Docker image that runs during a `job` linked to the
Docker image that the image keyword defines. This allows you to access
the service image during build time.
The service image can run any application, but the most common use
case is to run a database container, for example:
- [Using MySQL](mysql.md)
- [Using PostgreSQL](postgres.md)
- [Using Redis](redis.md)

View File

@ -1,212 +1,8 @@
---
stage: Verify
group: Continuous Integration
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
type: tutorial
redirect_to: 'index.md'
---
# Using SSH keys with GitLab CI/CD
This document was moved to [another location](index.md).
GitLab currently doesn't have built-in support for managing SSH keys in a build
environment (where the GitLab Runner runs).
The SSH keys can be useful when:
1. You want to checkout internal submodules
1. You want to download private packages using your package manager (e.g., Bundler)
1. You want to deploy your application to your own server, or, for example, Heroku
1. You want to execute SSH commands from the build environment to a remote server
1. You want to rsync files from the build environment to a remote server
If anything of the above rings a bell, then you most likely need an SSH key.
The most widely supported method is to inject an SSH key into your build
environment by extending your `.gitlab-ci.yml`, and it's a solution which works
with any type of [executor](https://docs.gitlab.com/runner/executors/)
(Docker, shell, etc.).
## How it works
1. Create a new SSH key pair locally with [`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)
1. Add the private key as a [variable](../variables/README.md) to
your project
1. Run the [`ssh-agent`](https://linux.die.net/man/1/ssh-agent) during job to load
the private key.
1. Copy the public key to the servers you want to have access to (usually in
`~/.ssh/authorized_keys`) or add it as a [deploy key](../../ssh/README.md#deploy-keys)
if you are accessing a private GitLab repository.
The private key is displayed in the job log, unless you enable
[debug logging](../variables/README.md#debug-logging). You might also want to
check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
## SSH keys when using the Docker executor
When your CI/CD jobs run inside Docker containers (meaning the environment is
contained) and you want to deploy your code in a private server, you need a way
to access it. This is where an SSH key pair comes in handy.
1. You first need to create an SSH key pair. For more information, follow
the instructions to [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
**Do not** add a passphrase to the SSH key, or the `before_script` will
prompt for it.
1. Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables).
As **Key** enter the name `SSH_PRIVATE_KEY` and in the **Value** field paste
the content of your _private_ key that you created earlier.
1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following
example, a Debian based image is assumed. Edit to your needs:
```yaml
before_script:
##
## Install ssh-agent if not already installed, it is required by Docker.
## (change apt-get to yum if you use an RPM-based image)
##
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
##
## Run ssh-agent (inside the build environment)
##
- eval $(ssh-agent -s)
##
## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
## We're using tr to fix line endings which makes ed25519 keys work
## without extra base64 encoding.
## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
##
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
##
## Create the SSH directory and give it the right permissions
##
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
##
## Optionally, if you will be using any Git commands, set the user name and
## and email.
##
# - git config --global user.email "user@example.com"
# - git config --global user.name "User name"
```
The [`before_script`](../yaml/README.md#before_script) can be set globally
or per-job.
1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
1. As a final step, add the _public_ key from the one you created in the first
step to the services that you want to have an access to from within the build
environment. If you are accessing a private GitLab repository you need to add
it as a [deploy key](../../ssh/README.md#deploy-keys).
That's it! You can now have access to private servers or repositories in your
build environment.
## SSH keys when using the Shell executor
If you are using the Shell executor and not Docker, it is easier to set up an
SSH key.
You can generate the SSH key from the machine that GitLab Runner is installed
on, and use that key for all projects that are run on this machine.
1. First, log in to the server that runs your jobs.
1. Then, from the terminal, log in as the `gitlab-runner` user:
```shell
sudo su - gitlab-runner
```
1. Generate the SSH key pair as described in the instructions to
[generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
**Do not** add a passphrase to the SSH key, or the `before_script` will
prompt for it.
1. As a final step, add the _public_ key from the one you created earlier to the
services that you want to have an access to from within the build environment.
If you are accessing a private GitLab repository you need to add it as a
[deploy key](../../ssh/README.md#deploy-keys).
After generating the key, try to sign in to the remote server to accept the
fingerprint:
```shell
ssh example.com
```
For accessing repositories on GitLab.com, you would use `git@gitlab.com`.
## Verifying the SSH host keys
It is a good practice to check the private server's own public key to make sure
you are not being targeted by a man-in-the-middle attack. If anything
suspicious happens, you notice it because the job fails (the SSH
connection fails when the public keys don't match).
To find out the host keys of your server, run the `ssh-keyscan` command from a
trusted network (ideally, from the private server itself):
```shell
## Use the domain name
ssh-keyscan example.com
## Or use an IP
ssh-keyscan 1.2.3.4
```
Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables) with
`SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan`.
If you need to connect to multiple servers, all the server host keys
need to be collected in the **Value** of the variable, one key per line.
NOTE:
By using a variable instead of `ssh-keyscan` directly inside
`.gitlab-ci.yml`, it has the benefit that you don't have to change `.gitlab-ci.yml`
if the host domain name changes for some reason. Also, the values are predefined
by you, meaning that if the host keys suddenly change, the CI/CD job doesn't fail,
so there's something wrong with the server or the network.
Now that the `SSH_KNOWN_HOSTS` variable is created, in addition to the
[content of `.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)
above, here's what more you need to add:
```yaml
before_script:
##
## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
## following two lines.
##
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
##
## Alternatively, use ssh-keyscan to scan the keys of your private server.
## Replace example.com with your private server's domain name. Repeat that
## command if you have more than one server to connect to.
##
# - ssh-keyscan example.com >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
##
## You can optionally disable host key checking. Be aware that by adding that
## you are susceptible to man-in-the-middle attacks.
## WARNING: Use this only with the Docker executor, if you use it with shell
## you will overwrite your user's SSH config.
##
# - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'
```
## Example project
We have set up an [Example SSH Project](https://gitlab.com/gitlab-examples/ssh-private-key/) for your convenience
that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes is picked by a public runner and the job starts.
<!-- This redirect file can be deleted after 2021-05-01. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->

212
doc/ci/ssh_keys/index.md Normal file
View File

@ -0,0 +1,212 @@
---
stage: Verify
group: Continuous Integration
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
type: tutorial
---
# Using SSH keys with GitLab CI/CD
GitLab currently doesn't have built-in support for managing SSH keys in a build
environment (where the GitLab Runner runs).
The SSH keys can be useful when:
1. You want to checkout internal submodules
1. You want to download private packages using your package manager (e.g., Bundler)
1. You want to deploy your application to your own server, or, for example, Heroku
1. You want to execute SSH commands from the build environment to a remote server
1. You want to rsync files from the build environment to a remote server
If anything of the above rings a bell, then you most likely need an SSH key.
The most widely supported method is to inject an SSH key into your build
environment by extending your `.gitlab-ci.yml`, and it's a solution which works
with any type of [executor](https://docs.gitlab.com/runner/executors/)
(Docker, shell, etc.).
## How it works
1. Create a new SSH key pair locally with [`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)
1. Add the private key as a [variable](../variables/README.md) to
your project
1. Run the [`ssh-agent`](https://linux.die.net/man/1/ssh-agent) during job to load
the private key.
1. Copy the public key to the servers you want to have access to (usually in
`~/.ssh/authorized_keys`) or add it as a [deploy key](../../ssh/README.md#deploy-keys)
if you are accessing a private GitLab repository.
The private key is displayed in the job log, unless you enable
[debug logging](../variables/README.md#debug-logging). You might also want to
check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
## SSH keys when using the Docker executor
When your CI/CD jobs run inside Docker containers (meaning the environment is
contained) and you want to deploy your code in a private server, you need a way
to access it. This is where an SSH key pair comes in handy.
1. You first need to create an SSH key pair. For more information, follow
the instructions to [generate an SSH key](../../ssh/README.md#generate-an-ssh-key-pair).
**Do not** add a passphrase to the SSH key, or the `before_script` will
prompt for it.
1. Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables).
As **Key** enter the name `SSH_PRIVATE_KEY` and in the **Value** field paste
the content of your _private_ key that you created earlier.
1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following
example, a Debian based image is assumed. Edit to your needs:
```yaml
before_script:
##
## Install ssh-agent if not already installed, it is required by Docker.
## (change apt-get to yum if you use an RPM-based image)
##
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
##
## Run ssh-agent (inside the build environment)
##
- eval $(ssh-agent -s)
##
## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
## We're using tr to fix line endings which makes ed25519 keys work
## without extra base64 encoding.
## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
##
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
##
## Create the SSH directory and give it the right permissions
##
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
##
## Optionally, if you will be using any Git commands, set the user name and
## and email.
##
# - git config --global user.email "user@example.com"
# - git config --global user.name "User name"
```
The [`before_script`](../yaml/README.md#before_script) can be set globally
or per-job.
1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
1. As a final step, add the _public_ key from the one you created in the first
step to the services that you want to have an access to from within the build
environment. If you are accessing a private GitLab repository you need to add
it as a [deploy key](../../ssh/README.md#deploy-keys).
That's it! You can now have access to private servers or repositories in your
build environment.
## SSH keys when using the Shell executor
If you are using the Shell executor and not Docker, it is easier to set up an
SSH key.
You can generate the SSH key from the machine that GitLab Runner is installed
on, and use that key for all projects that are run on this machine.
1. First, log in to the server that runs your jobs.
1. Then, from the terminal, log in as the `gitlab-runner` user:
```shell
sudo su - gitlab-runner
```
1. Generate the SSH key pair as described in the instructions to
[generate an SSH key](../../ssh/README.md#generate-an-ssh-key-pair).
**Do not** add a passphrase to the SSH key, or the `before_script` will
prompt for it.
1. As a final step, add the _public_ key from the one you created earlier to the
services that you want to have an access to from within the build environment.
If you are accessing a private GitLab repository you need to add it as a
[deploy key](../../ssh/README.md#deploy-keys).
After generating the key, try to sign in to the remote server to accept the
fingerprint:
```shell
ssh example.com
```
For accessing repositories on GitLab.com, you would use `git@gitlab.com`.
## Verifying the SSH host keys
It is a good practice to check the private server's own public key to make sure
you are not being targeted by a man-in-the-middle attack. If anything
suspicious happens, you notice it because the job fails (the SSH
connection fails when the public keys don't match).
To find out the host keys of your server, run the `ssh-keyscan` command from a
trusted network (ideally, from the private server itself):
```shell
## Use the domain name
ssh-keyscan example.com
## Or use an IP
ssh-keyscan 1.2.3.4
```
Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables) with
`SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan`.
If you need to connect to multiple servers, all the server host keys
need to be collected in the **Value** of the variable, one key per line.
NOTE:
By using a variable instead of `ssh-keyscan` directly inside
`.gitlab-ci.yml`, it has the benefit that you don't have to change `.gitlab-ci.yml`
if the host domain name changes for some reason. Also, the values are predefined
by you, meaning that if the host keys suddenly change, the CI/CD job doesn't fail,
so there's something wrong with the server or the network.
Now that the `SSH_KNOWN_HOSTS` variable is created, in addition to the
[content of `.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)
above, here's what more you need to add:
```yaml
before_script:
##
## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
## following two lines.
##
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
##
## Alternatively, use ssh-keyscan to scan the keys of your private server.
## Replace example.com with your private server's domain name. Repeat that
## command if you have more than one server to connect to.
##
# - ssh-keyscan example.com >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
##
## You can optionally disable host key checking. Be aware that by adding that
## you are susceptible to man-in-the-middle attacks.
## WARNING: Use this only with the Docker executor, if you use it with shell
## you will overwrite your user's SSH config.
##
# - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'
```
## Example project
We have set up an [Example SSH Project](https://gitlab.com/gitlab-examples/ssh-private-key/) for your convenience
that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes is picked by a public runner and the job starts.

View File

@ -22,8 +22,8 @@ Kubernetes-specific environment variables are detailed in the
| Variable | GitLab | Runner | Description |
|-----------------------------------------------|--------|--------|-------------|
| `CHAT_CHANNEL` | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/README.md) command. |
| `CHAT_INPUT` | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/README.md) command. |
| `CHAT_CHANNEL` | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/index.md) command. |
| `CHAT_INPUT` | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/index.md) command. |
| `CI` | all | 0.4 | Mark that job is executed in CI environment. |
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
| `CI_BUILDS_DIR` | all | 11.10 | Top-level directory where builds are executed. |

View File

@ -13,7 +13,7 @@ type: reference
This document lists the configuration options for your GitLab `.gitlab-ci.yml` file.
- For a quick introduction to GitLab CI/CD, follow the [quick start guide](../quick_start/README.md).
- For a quick introduction to GitLab CI/CD, follow the [quick start guide](../quick_start/index.md).
- For a collection of examples, see [GitLab CI/CD Examples](../examples/README.md).
- To view a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
@ -543,7 +543,7 @@ Used to specify [a Docker image](../docker/using_docker_images.md#what-is-an-ima
For:
- Usage examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
- Detailed usage information, refer to [Docker integration](../docker/README.md) documentation.
- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
#### `image:name`
@ -564,8 +564,8 @@ Used to specify a [service Docker image](../docker/using_docker_images.md#what-i
For:
- Usage examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
- Detailed usage information, refer to [Docker integration](../docker/README.md) documentation.
- For example services, see [GitLab CI/CD Services](../services/README.md).
- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
- For example services, see [GitLab CI/CD Services](../services/index.md).
##### `services:name`
@ -1253,7 +1253,7 @@ check the value of the `$CI_PIPELINE_SOURCE` variable:
| Value | Description |
|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. |
| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
| `external` | When you use CI services other than GitLab. |
| `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). |
| `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). |
@ -1553,7 +1553,7 @@ In addition, `only` and `except` can use special keywords:
|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
| `branches` | When the Git reference for a pipeline is a branch. |
| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. |
| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
| `external` | When you use CI services other than GitLab. |
| `external_pull_requests` | When an external pull request on GitHub is created or updated (See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests)). |
| `merge_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). |

View File

@ -61,6 +61,6 @@ To request access to ChatOps on GitLab.com:
## See also
- [ChatOps Usage](../ci/chatops/README.md)
- [ChatOps Usage](../ci/chatops/index.md)
- [Understanding EXPLAIN plans](understanding_explain_plans.md)
- [Feature Groups](feature_flags/development.md#feature-groups)

View File

@ -181,11 +181,21 @@ reasons for including it.
`@mention` a maintainer in merge requests that contain:
- More than 500 changes.
- Any major breaking changes.
- Any major [breaking changes](#breaking-changes).
- External libraries.
If you are not sure who to mention, the reviewer will do this for you early in the merge request process.
#### Breaking changes
A "breaking change" is any change that requires users to make a corresponding change to their code, settings, or workflow. "Users" might be humans, API clients, or even code classes that "use" another class. Examples of breaking changes include:
- Removing a user-facing feature without a replacement/workaround.
- Changing the definition of an existing API (by re-naming query parameters, changing routes, etc.).
- Removing a public method from a code class.
A breaking change can be considered "major" if it affects many users, or represents a significant change in behavior.
#### Issues workflow
This [documentation](issue_workflow.md) outlines the current issue workflow:

View File

@ -150,7 +150,7 @@ Commit messages should follow the guidelines below, for reasons explained by Chr
#### Why these standards matter
1. Consistent commit messages that follow these guidelines make the history more readable.
1. Concise standard commit messages helps to identify breaking changes for a deployment or ~"master:broken" quicker when
1. Concise standard commit messages helps to identify [breaking changes](index.md#breaking-changes) for a deployment or ~"master:broken" quicker when
reviewing commits between two points in time.
#### Commit message template

View File

@ -325,7 +325,7 @@ Note that the use of this method requires that we have first [recorded the user
### Enable the experiment
After all merge requests have been merged, use [`chatops`](../../ci/chatops/README.md) in the
After all merge requests have been merged, use [`chatops`](../../ci/chatops/index.md) in the
[appropriate channel](../feature_flags/controls.md#communicate-the-change) to start the experiment for 10% of the users.
The feature flag should have the name of the experiment with the `_experiment_percentage` suffix appended.
For visibility, please also share any commands run against production in the `#s_growth` channel:

View File

@ -37,7 +37,7 @@ easier to measure the impact of both separately.
The GitLab feature library (using
[Flipper](https://github.com/jnunemaker/flipper), and covered in the [Feature
Flags process](process.md) guide) supports rolling out changes to a percentage of
time to users. This in turn can be controlled using [GitLab ChatOps](../../ci/chatops/README.md).
time to users. This in turn can be controlled using [GitLab ChatOps](../../ci/chatops/index.md).
For an up to date list of feature flag commands please see [the source
code](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb).

View File

@ -75,5 +75,10 @@ This section describes how to add new metrics for self-monitoring
1. Select the appropriate name for your metric. Refer to the guidelines
for [Prometheus metric names](https://prometheus.io/docs/practices/naming/#metric-names).
1. Update the list of [GitLab Prometheus metrics](../administration/monitoring/prometheus/gitlab_metrics.md).
1. Carefully choose what labels you want to add to your metric. Values with high cardinality,
like `project_path`, or `project_id` are strongly discouraged because they can affect our services
availability due to the fact that each set of labels is exposed as a new entry in the `/metrics` endpoint.
For example, a histogram with 10 buckets and a label with 100 values would generate 1000
entries in the export endpoint.
1. Trigger the relevant page or code that records the new metric.
1. Check that the new metric appears at `/-/metrics`.

View File

@ -26,7 +26,7 @@ Taking the trigger term as `project-name`, the commands are:
| `/project-name issue move <id> to <project>` | Moves issue ID `<id>` to `<project>` |
| `/project-name issue comment <id> <shift+return> <comment>` | Adds a new comment to an issue with ID `<id>` and comment body `<comment>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/README.md) job `<job name>` on `master` |
| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/index.md) job `<job name>` on `master` |
If you are using the [GitLab Slack application](../user/project/integrations/gitlab_slack_application.md) for
your GitLab.com projects, [add the `gitlab` keyword at the beginning of the command](../user/project/integrations/gitlab_slack_application.md#usage).

View File

@ -38,7 +38,7 @@ Create merge requests and review code.
Use the built-in continuous integration in GitLab.
- [Get started with GitLab CI/CD](../ci/quick_start/README.md)
- [Get started with GitLab CI/CD](../ci/quick_start/index.md)
## Install and Update

View File

@ -17,179 +17,145 @@ GitLab remote server without supplying your username or password each time.
This page can help you configure secure SSH keys which you can use to help secure
connections to GitLab repositories.
- If you need information on creating SSH keys, start with our [options for SSH keys](#options-for-ssh-keys).
- If you need information on creating SSH keys, start with our [options for SSH keys](#supported-ssh-key-types).
- If you have SSH keys dedicated for your GitLab account, you may be interested in [Working with non-default SSH key pair paths](#working-with-non-default-ssh-key-pair-paths).
- If you already have an SSH key pair, you can go to how you can [add an SSH key to your GitLab account](#adding-an-ssh-key-to-your-gitlab-account).
- If you already have an SSH key pair, you can go to how you can [add an SSH key to your GitLab account](#add-an-ssh-key-to-your-gitlab-account).
## Requirements
## Prerequisites
To support SSH, GitLab requires the installation of the OpenSSH client, which
comes pre-installed on GNU/Linux and macOS, as well as on Windows 10.
To use SSH to communicate with GitLab, you need:
Make sure that your system includes SSH version 6.5 or newer, as that excludes
the now insecure MD5 signature scheme. The following command returns the version of
SSH installed on your system:
- The OpenSSH client, which comes pre-installed on GNU/Linux, macOS, and Windows 10.
- SSH version 6.5 or later. Earlier versions used an MD5 signature, which is not secure.
```shell
ssh -V
```
To view the version of SSH installed on your system, run `ssh -V`.
While GitLab does [not support installation on Microsoft Windows](../install/requirements.md#microsoft-windows),
you can set up SSH keys to set up Windows [as a client](#options-for-microsoft-windows).
GitLab does [not support installation on Microsoft Windows](../install/requirements.md#microsoft-windows),
but you can set up SSH keys on the Windows [client](#options-for-microsoft-windows).
## Options for SSH keys
## Supported SSH key types
GitLab supports the use of RSA, DSA, ECDSA, and ED25519 keys.
To communicate with GitLab, you can use the following SSH key types:
- GitLab has [deprecated](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) DSA keys in GitLab 11.0.
- As noted in [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-ecdsa), the security issues related to DSA also apply to ECDSA.
- [ED25519](#ed25519-ssh-keys)
- [RSA](#rsa-ssh-keys)
- DSA ([Deprecated](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) in GitLab 11.0.)
- ECDSA (As noted in [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-ecdsa), the security issues related to DSA also apply to ECDSA.)
NOTE:
Available documentation suggests that ED25519 is more secure. If you use an RSA key, the US National Institute of Science and Technology in [Publication 800-57 Part 3 (PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf) recommends a key size of at least 2048 bits.
Therefore, our documentation focuses on the use of ED25519 and RSA keys.
Administrators can [restrict which keys should be permitted and their minimum lengths](../security/ssh_keys_restrictions.md).
## Review existing SSH keys
If you have existing SSH keys, you may be able to use them to help secure connections with GitLab
repositories. By default, SSH keys on Linux and macOS systems are stored in the user's home directory,
in the `.ssh/` subdirectory. The following table includes default filenames for each SSH key algorithm:
| Algorithm | Public key | Private key |
| --------- | ---------- | ----------- |
| ED25519 (preferred) | `id_ed25519.pub` | `id_ed25519` |
| RSA (at least 2048-bit key size) | `id_rsa.pub` | `id_rsa` |
| DSA (deprecated) | `id_dsa.pub` | `id_dsa` |
| ECDSA | `id_ecdsa.pub` | `id_ecdsa` |
For recommendations, see [options for SSH keys](#options-for-ssh-keys).
## Generating a new SSH key pair
If you want to create:
- An ED25519 key, read [ED25519 SSH keys](#ed25519-ssh-keys).
- An RSA key, read [RSA SSH keys](#rsa-ssh-keys).
Administrators can [restrict which keys are permitted and their minimum lengths](../security/ssh_keys_restrictions.md).
### ED25519 SSH keys
The book [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-chapter-5-digital-signatures)
suggests that [ED25519](https://ed25519.cr.yp.to/) keys are more secure and performant than RSA keys.
As OpenSSH 6.5 introduced ED25519 SSH keys in 2014, they should be available on any current
operating system.
You can create and configure an ED25519 key with the following command:
```shell
ssh-keygen -t ed25519 -C "<comment>"
```
The `-C` flag, with a quoted comment such as an email address, is an optional way to label your SSH keys.
You'll see a response similar to:
```plaintext
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
```
For guidance, proceed to the [common steps](#common-steps-for-generating-an-ssh-key-pair).
OpenSSH 6.5 introduced ED25519 SSH keys in 2014 and they should be available on most
operating systems.
### RSA SSH keys
If you use RSA keys for SSH, the US National Institute of Standards and Technology recommends
that you use a key size of [at least 2048 bits](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf).
By default, the `ssh-keygen` command creates an 1024-bit RSA key.
Available documentation suggests that ED25519 is more secure than RSA.
You can create and configure an RSA key with the following command, substituting if desired for the minimum recommended key size of `2048`:
If you use an RSA key, the US National Institute of Science and Technology in
[Publication 800-57 Part 3 (PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)
recommends a key size of at least 2048 bits. The default key size depends on your version of `ssh-keygen`.
Review the `man` page for your installed `ssh-keygen` command for details.
```shell
ssh-keygen -t rsa -b 2048 -C "email@example.com"
```
## See if you have an existing SSH key pair
The `-C` flag, with a quoted comment such as an email address, is an optional way to label your SSH keys.
Before you create a key pair, see if a key pair already exists.
You'll see a response similar to:
1. On Linux or macOS, go to your home directory.
1. Go to the `.ssh/` subdirectory.
1. See if a file with one of the following formats exists:
```plaintext
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
```
| Algorithm | Public key | Private key |
| --------- | ---------- | ----------- |
| ED25519 (preferred) | `id_ed25519.pub` | `id_ed25519` |
| RSA (at least 2048-bit key size) | `id_rsa.pub` | `id_rsa` |
| DSA (deprecated) | `id_dsa.pub` | `id_dsa` |
| ECDSA | `id_ecdsa.pub` | `id_ecdsa` |
For guidance, proceed to the [common steps](#common-steps-for-generating-an-ssh-key-pair).
## Generate an SSH key pair
NOTE:
If you have OpenSSH version 7.8 or below, consider the problems associated
with [encoding](#rsa-keys-and-openssh-from-versions-65-to-78).
If you do not have an existing SSH key pair, generate a new one.
### Common steps for generating an SSH key pair
1. Open a terminal.
1. Type `ssh-keygen -t` followed by the key type and an optional comment.
This comment is included in the `.pub` file that's created.
You may want to use an email address for the comment.
For example, for ED25519:
Whether you're creating a [ED25519](#ed25519-ssh-keys) or an [RSA](#rsa-ssh-keys) key, you've started with the `ssh-keygen` command.
At this point, you'll see the following message in the command line (for ED25519 keys):
```shell
ssh-keygen -t ed25519 -C "<comment>"
```
```plaintext
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
```
For 2048-bit RSA:
If you don't already have an SSH key pair and are not generating a [deploy key](#deploy-keys),
accept the suggested file and directory. Your SSH client uses
the resulting SSH key pair with no additional configuration.
```shell
ssh-keygen -t rsa -b 2048 -C "<comment>"
```
Alternatively, you can save the new SSH key pair in a different location.
You can assign the directory and filename of your choice.
You can also dedicate that SSH key pair to a [specific host](#working-with-non-default-ssh-key-pair-paths).
1. Press Enter. Output similar to the following is displayed:
After assigning a file to save your SSH key, you can set up
a [passphrase](https://www.ssh.com/ssh/passphrase/) for your SSH key:
```plaintext
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
```
```plaintext
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```
1. Accept the suggested filename and directory, unless you are generating a [deploy key](#deploy-keys)
or want to save in a specific directory where you store other keys.
If successful, you'll see confirmation of where the `ssh-keygen` command
saved your identification and private key.
You can also dedicate the SSH key pair to a [specific host](#working-with-non-default-ssh-key-pair-paths).
When needed, you can update the passphrase with the following command:
1. Specify a [passphrase](https://www.ssh.com/ssh/passphrase/):
```shell
ssh-keygen -p -f /path/to/ssh_key
```
```plaintext
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```
### RSA keys and OpenSSH from versions 6.5 to 7.8
1. A confirmation is displayed, including information about where your files are stored.
Before OpenSSH 7.8, the default public key fingerprint for RSA keys was based on MD5,
and is therefore insecure.
A public and private key are generated.
[Add the public SSH key to your GitLab account](#add-an-ssh-key-to-your-gitlab-account) and keep
the private key secure.
If your version of OpenSSH lies between version 6.5 to version 7.8 (inclusive),
run `ssh-keygen` with the `-o` option to save your private SSH keys in the more secure
### Update your SSH key passphrase
You can update the passphrase for your SSH key.
1. Open a terminal and type this command:
```shell
ssh-keygen -p -f /path/to/ssh_key
```
1. At the prompts, type the passphrase and press Enter.
### Upgrade your RSA key pair to a more secure format
If your version of OpenSSH is between 6.5 and 7.8,
you can save your private RSA SSH keys in a more secure
OpenSSH format.
If you already have an RSA SSH key pair to use with GitLab, consider upgrading it
to use the more secure password encryption format. You can do so with the following command:
1. Open a terminal and type this command:
```shell
ssh-keygen -o -f ~/.ssh/id_rsa
```
```shell
ssh-keygen -o -f ~/.ssh/id_rsa
```
Alternatively, you can generate a new RSA key with the more secure encryption format with
the following command:
Alternatively, you can generate a new RSA key with the more secure encryption format with
the following command:
```shell
ssh-keygen -o -t rsa -b 4096 -C "email@example.com"
```
```shell
ssh-keygen -o -t rsa -b 4096 -C "<comment>"
```
NOTE:
As noted in the `ssh-keygen` man page, ED25519 already encrypts keys to the more secure
OpenSSH format.
## Add an SSH key to your GitLab account
## Adding an SSH key to your GitLab account
Now you can copy the SSH key you created to your GitLab account. To do so, follow these steps:
Now you can copy the SSH key you created to your GitLab account.
1. Copy your **public** SSH key to a location that saves information in text format.
The following options saves information for ED25519 keys to the clipboard

View File

@ -842,6 +842,17 @@ The site is validated and an active scan can run against it.
If a validated site profile's target URL is edited, the site is no longer validated.
### Revoke a site validation
To revoke validation from a site profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
1. Select **Manage** in the **DAST Profiles** row.
1. Select **Revoke validation** beside the validated profile.
1. Select **Revoke validation**.
The site profile's validation is revoked. An active scan cannot be run against it or any other profile with the same URL.
#### Validated site profile headers
The following are code samples of how you could provide the required site profile header in your

View File

@ -43,7 +43,7 @@ You can either use the user interface (UI), or connect your local computer
with GitLab [through the command line](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
To configure [GitLab CI/CD](../../../ci/README.md) to build, test, and deploy
your code, add a file called [`.gitlab-ci.yml`](../../../ci/quick_start/README.md)
your code, add a file called [`.gitlab-ci.yml`](../../../ci/quick_start/index.md)
to your repository's root.
**From the user interface:**

View File

@ -36,7 +36,7 @@ module API
get ':id/deployments' do
authorize! :read_deployment, user_project
deployments = DeploymentsFinder.new(user_project, params).execute
deployments = DeploymentsFinder.new(params.merge(project: user_project)).execute
present paginate(deployments), with: Entities::Deployment
end

View File

@ -9,6 +9,9 @@ module API
expose :job_artifacts, as: :artifacts, using: ::API::Entities::Ci::JobArtifact
expose :runner, with: ::API::Entities::Runner
expose :artifacts_expire_at
expose :tag_list do |job|
job.tags.map(&:name).sort
end
end
end
end

View File

@ -45,7 +45,7 @@ module API
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, pipeline: :project)
builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, :tags, pipeline: :project)
present paginate(builds), with: Entities::Ci::Job
end
# rubocop: enable CodeReuse/ActiveRecord

View File

@ -15,9 +15,16 @@ module Gitlab
private
def deployments_count
query = @project.deployments.success.where("created_at >= ?", @from)
query = query.where("created_at <= ?", @to) if @to
query.count
if Feature.enabled?(:query_deploymenys_via_finished_at_in_vsa)
DeploymentsFinder
.new(project: @project, finished_after: @from, finished_before: @to, status: :success)
.execute
.count
else
query = @project.deployments.success.where("created_at >= ?", @from)
query = query.where("created_at <= ?", @to) if @to
query.count
end
end
end
end

View File

@ -48,9 +48,21 @@ namespace :gitlab do
if summary == :client_query
$stdout.puts " - client query"
elsif errs.present?
$stdout.puts " - invalid query"
$stdout.puts " - invalid query".color(:red)
else
$stdout.puts " - complexity: #{defn.complexity(GitlabSchema)}"
complexity = defn.complexity(GitlabSchema)
color = case complexity
when 0..GitlabSchema::DEFAULT_MAX_COMPLEXITY
:green
when GitlabSchema::DEFAULT_MAX_COMPLEXITY..GitlabSchema::AUTHENTICATED_COMPLEXITY
:yellow
when GitlabSchema::AUTHENTICATED_COMPLEXITY..GitlabSchema::ADMIN_COMPLEXITY
:orange
else
:red
end
$stdout.puts " - complexity: #{complexity}".color(color)
end
$stdout.puts ""
@ -72,10 +84,10 @@ namespace :gitlab do
when :client_query
warn("SKIP #{defn.file}: client query")
else
warn("OK #{defn.file}") if errs.empty?
warn("#{'OK'.color(:green)} #{defn.file}") if errs.empty?
errs.each do |err|
warn(<<~MSG)
ERROR #{defn.file}: #{err.message} (at #{err.path.join('.')})
#{'ERROR'.color(:red)} #{defn.file}: #{err.message} (at #{err.path.join('.')})
MSG
end
end

View File

@ -9194,6 +9194,9 @@ msgstr ""
msgid "DastSiteValidation|Could not create validation token. Please try again."
msgstr ""
msgid "DastSiteValidation|Could not revoke validation. Please try again."
msgstr ""
msgid "DastSiteValidation|Download validation text file"
msgstr ""
@ -9203,6 +9206,9 @@ msgstr ""
msgid "DastSiteValidation|Retry validation"
msgstr ""
msgid "DastSiteValidation|Revoke validation"
msgstr ""
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@ -9227,6 +9233,11 @@ msgstr ""
msgid "DastSiteValidation|The validation is in progress. Please wait..."
msgstr ""
msgid "DastSiteValidation|This will affect %d other profile targeting the same URL."
msgid_plural "DastSiteValidation|This will affect %d other profiles targeting the same URL."
msgstr[0] ""
msgstr[1] ""
msgid "DastSiteValidation|Validate"
msgstr ""
@ -9245,6 +9256,9 @@ msgstr ""
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
msgid "DastSiteValidation|You will not be able to run active scans against %{url}."
msgstr ""
msgid "Data is still calculating..."
msgstr ""
@ -23047,6 +23061,9 @@ msgstr ""
msgid "ProjectSettings|Require"
msgstr ""
msgid "ProjectSettings|Require an associated issue from Jira"
msgstr ""
msgid "ProjectSettings|Requirements"
msgstr ""

View File

@ -177,9 +177,9 @@
"docdash": "^1.0.2",
"eslint": "7.19.0",
"eslint-import-resolver-jest": "3.0.0",
"eslint-import-resolver-webpack": "^0.12.1",
"eslint-plugin-jasmine": "^4.1.0",
"eslint-plugin-no-jquery": "^2.3.0",
"eslint-import-resolver-webpack": "0.12.1",
"eslint-plugin-jasmine": "4.1.0",
"eslint-plugin-no-jquery": "2.3.1",
"gettext-extractor": "^3.4.3",
"gettext-extractor-vue": "^4.0.2",
"istanbul-lib-coverage": "^3.0.0",

View File

@ -3,10 +3,10 @@
require 'spec_helper'
RSpec.describe DeploymentsFinder do
subject { described_class.new(project, params).execute }
subject { described_class.new(params).execute }
let(:project) { create(:project, :public, :test_repo) }
let(:params) { {} }
let_it_be(:project) { create(:project, :public, :test_repo) }
let(:params) { { project: project } }
describe "#execute" do
it 'returns all deployments by default' do
@ -14,9 +14,17 @@ RSpec.describe DeploymentsFinder do
is_expected.to match_array(deployments)
end
context 'when project is missing' do
let(:params) { {} }
it 'returns nothing' do
is_expected.to eq([])
end
end
describe 'filtering' do
context 'when updated_at filters are specified' do
let(:params) { { updated_before: 1.day.ago, updated_after: 3.days.ago } }
let(:params) { { project: project, updated_before: 1.day.ago, updated_after: 3.days.ago } }
let!(:deployment_1) { create(:deployment, :success, project: project, updated_at: 2.days.ago) }
let!(:deployment_2) { create(:deployment, :success, project: project, updated_at: 4.days.ago) }
let!(:deployment_3) { create(:deployment, :success, project: project, updated_at: 1.hour.ago) }
@ -37,7 +45,7 @@ RSpec.describe DeploymentsFinder do
create(:deployment, project: project, environment: environment2)
end
let(:params) { { environment: environment1.name } }
let(:params) { { project: project, environment: environment1.name } }
it 'returns deployments for the given environment' do
is_expected.to match_array([deployment1])
@ -47,7 +55,7 @@ RSpec.describe DeploymentsFinder do
context 'when the deployment status is specified' do
let!(:deployment1) { create(:deployment, :success, project: project) }
let!(:deployment2) { create(:deployment, :failed, project: project) }
let(:params) { { status: 'success' } }
let(:params) { { project: project, status: 'success' } }
it 'returns deployments for the given environment' do
is_expected.to match_array([deployment1])
@ -55,36 +63,64 @@ RSpec.describe DeploymentsFinder do
end
context 'when using an invalid deployment status' do
let(:params) { { status: 'kittens' } }
let(:params) { { project: project, status: 'kittens' } }
it 'raises ArgumentError' do
expect { subject }.to raise_error(ArgumentError)
end
end
context 'when filtering by finished time' do
let!(:deployment_1) { create(:deployment, :success, project: project, finished_at: 2.days.ago) }
let!(:deployment_2) { create(:deployment, :success, project: project, finished_at: 4.days.ago) }
let!(:deployment_3) { create(:deployment, :success, project: project, finished_at: 5.hours.ago) }
context 'when filtering by finished_after and finished_before' do
let(:params) { { project: project, finished_after: 3.days.ago, finished_before: 1.day.ago } }
it { is_expected.to match_array([deployment_1]) }
end
context 'when the finished_before parameter is missing' do
let(:params) { { project: project, finished_after: 3.days.ago } }
it { is_expected.to match_array([deployment_1, deployment_3]) }
end
context 'when finished_after is missing' do
let(:params) { { project: project, finished_before: 1.day.ago } }
it 'does not apply any filters on finished time' do
is_expected.to match_array([deployment_1, deployment_2, deployment_3])
end
end
end
end
describe 'ordering' do
using RSpec::Parameterized::TableSyntax
let(:params) { { order_by: order_by, sort: sort } }
let(:params) { { project: project, order_by: order_by, sort: sort } }
let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: 2.days.ago, updated_at: Time.now) }
let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago, updated_at: 2.hours.ago) }
let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'video', created_at: Time.now, updated_at: 1.hour.ago) }
let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: 2.days.ago, updated_at: Time.now, finished_at: 3.hours.ago) }
let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago, updated_at: 2.hours.ago, finished_at: 1.hour.ago) }
let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'video', created_at: Time.now, updated_at: 1.hour.ago, finished_at: 2.hours.ago) }
where(:order_by, :sort, :ordered_deployments) do
'created_at' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
'created_at' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
'id' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
'id' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
'iid' | 'asc' | [:deployment_3, :deployment_1, :deployment_2]
'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
'updated_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
'updated_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
'invalid' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
'iid' | 'err' | [:deployment_3, :deployment_1, :deployment_2]
'created_at' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
'created_at' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
'id' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
'id' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
'iid' | 'asc' | [:deployment_3, :deployment_1, :deployment_2]
'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
'updated_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
'updated_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
'finished_at' | 'asc' | [:deployment_1, :deployment_3, :deployment_2]
'finished_at' | 'desc' | [:deployment_2, :deployment_3, :deployment_1]
'invalid' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
'iid' | 'err' | [:deployment_3, :deployment_1, :deployment_2]
end
with_them do
@ -95,7 +131,7 @@ RSpec.describe DeploymentsFinder do
end
describe 'transform `created_at` sorting to `id` sorting' do
let(:params) { { order_by: 'created_at', sort: 'asc' } }
let(:params) { { project: project, order_by: 'created_at', sort: 'asc' } }
it 'sorts by only one column' do
expect(subject.order_values.size).to eq(1)
@ -107,7 +143,7 @@ RSpec.describe DeploymentsFinder do
end
describe 'tie-breaker for `updated_at` sorting' do
let(:params) { { order_by: 'updated_at', sort: 'asc' } }
let(:params) { { project: project, order_by: 'updated_at', sort: 'asc' } }
it 'sorts by two columns' do
expect(subject.order_values.size).to eq(2)

View File

@ -18,6 +18,7 @@
"web_url",
"artifacts",
"artifacts_expire_at",
"tag_list",
"runner"
],
"properties": {
@ -53,6 +54,9 @@
]
},
"artifacts_expire_at": { "type": ["null", "string"] },
"tag_list": {
"type": "array"
},
"runner": {
"oneOf": [
{ "type": "null" },

View File

@ -93,6 +93,7 @@ describe('packages_list_app', () => {
it('call requestPackagesList on page:changed', () => {
mountComponent();
store.dispatch.mockClear();
const list = findListComponent();
list.vm.$emit('page:changed', 1);
@ -107,14 +108,6 @@ describe('packages_list_app', () => {
expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
});
it('calls requestPackagesList on sort:changed', () => {
mountComponent();
const list = findListComponent();
list.vm.$emit('sort:changed');
expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
});
it('does not call requestPackagesList two times on render', () => {
mountComponent();
@ -142,10 +135,11 @@ describe('packages_list_app', () => {
expect(findPackageSearch().exists()).toBe(true);
});
it.each(['sort:changed', 'filter:changed'])('on %p fetches data from the store', (event) => {
it('on update fetches data from the store', () => {
mountComponent();
store.dispatch.mockClear();
findPackageSearch().vm.$emit(event);
findPackageSearch().vm.$emit('update');
expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
});

View File

@ -1,8 +1,9 @@
import Vuex from 'vuex';
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import component from '~/packages/list/components/package_search.vue';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import PackageTypeToken from '~/packages/list/components/tokens/package_type_token.vue';
import getTableHeaders from '~/packages/list/utils';
const localVue = createLocalVue();
localVue.use(Vuex);
@ -10,12 +11,8 @@ localVue.use(Vuex);
describe('Package Search', () => {
let wrapper;
let store;
let sorting;
let sortingItems;
const findPackageListSorting = () => wrapper.find(GlSorting);
const findSortingItems = () => wrapper.findAll(GlSortingItem);
const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
const findRegistrySearch = () => wrapper.find(RegistrySearch);
const createStore = (isGroupPage) => {
const state = {
@ -40,9 +37,6 @@ describe('Package Search', () => {
wrapper = shallowMount(component, {
localVue,
store,
stubs: {
GlSortingItem,
},
});
};
@ -51,95 +45,63 @@ describe('Package Search', () => {
wrapper = null;
});
describe('searching', () => {
it('has a filtered-search component', () => {
mountComponent();
it('has a registry search component', () => {
mountComponent();
expect(findFilteredSearch().exists()).toBe(true);
});
it('binds the correct props to filtered-search', () => {
mountComponent();
expect(findFilteredSearch().props()).toMatchObject({
value: [],
placeholder: 'Filter results',
availableTokens: wrapper.vm.tokens,
});
});
it('updates vuex when value changes', () => {
mountComponent();
findFilteredSearch().vm.$emit('input', ['foo']);
expect(store.dispatch).toHaveBeenCalledWith('setFilter', ['foo']);
});
it('emits filter:changed on submit event', () => {
mountComponent();
findFilteredSearch().vm.$emit('submit');
expect(wrapper.emitted('filter:changed')).toEqual([[]]);
});
it('emits filter:changed on clear event and reset vuex', () => {
mountComponent();
findFilteredSearch().vm.$emit('clear');
expect(store.dispatch).toHaveBeenCalledWith('setFilter', []);
expect(wrapper.emitted('filter:changed')).toEqual([[]]);
});
it('has a PackageTypeToken token', () => {
mountComponent();
expect(findFilteredSearch().props('availableTokens')).toEqual(
expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
);
expect(findRegistrySearch().exists()).toBe(true);
expect(findRegistrySearch().props()).toMatchObject({
filter: store.state.filter,
sorting: store.state.sorting,
tokens: expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
sortableFields: getTableHeaders(),
});
});
describe('sorting', () => {
describe('when is in projects', () => {
beforeEach(() => {
mountComponent();
sorting = findPackageListSorting();
sortingItems = findSortingItems();
});
it.each`
isGroupPage | page
${false} | ${'project'}
${true} | ${'group'}
`('in a $page page binds the right props', ({ isGroupPage }) => {
mountComponent(isGroupPage);
it('has all the sortable items', () => {
expect(sortingItems).toHaveLength(wrapper.vm.sortableFields.length);
});
it('on sort change set sorting in vuex and emit event', () => {
sorting.vm.$emit('sortDirectionChange');
expect(store.dispatch).toHaveBeenCalledWith('setSorting', { sort: 'asc' });
expect(wrapper.emitted('sort:changed')).toBeTruthy();
});
it('on sort item click set sorting and emit event', () => {
const item = sortingItems.at(0);
const { orderBy } = wrapper.vm.sortableFields[0];
item.vm.$emit('click');
expect(store.dispatch).toHaveBeenCalledWith('setSorting', { orderBy });
expect(wrapper.emitted('sort:changed')).toBeTruthy();
});
expect(findRegistrySearch().props()).toMatchObject({
filter: store.state.filter,
sorting: store.state.sorting,
tokens: expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
sortableFields: getTableHeaders(isGroupPage),
});
});
describe('when is in group', () => {
beforeEach(() => {
mountComponent(true);
sorting = findPackageListSorting();
sortingItems = findSortingItems();
});
it('on sorting:changed emits update event and calls vuex setSorting', () => {
const payload = { sort: 'foo' };
it('has all the sortable items', () => {
expect(sortingItems).toHaveLength(wrapper.vm.sortableFields.length);
});
});
mountComponent();
findRegistrySearch().vm.$emit('sorting:changed', payload);
expect(store.dispatch).toHaveBeenCalledWith('setSorting', payload);
expect(wrapper.emitted('update')).toEqual([[]]);
});
it('on filter:changed calls vuex setFilter', () => {
const payload = ['foo'];
mountComponent();
findRegistrySearch().vm.$emit('filter:changed', payload);
expect(store.dispatch).toHaveBeenCalledWith('setFilter', payload);
});
it('on filter:submit emits update event', () => {
mountComponent();
findRegistrySearch().vm.$emit('filter:submit');
expect(wrapper.emitted('update')).toEqual([[]]);
});
});

View File

@ -0,0 +1,105 @@
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import component from '~/vue_shared/components/registry/registry_search.vue';
describe('Registry Search', () => {
let wrapper;
const findPackageListSorting = () => wrapper.find(GlSorting);
const findSortingItems = () => wrapper.findAll(GlSortingItem);
const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
const defaultProps = {
filter: [],
sorting: { sort: 'asc', orderBy: 'name' },
tokens: ['foo'],
sortableFields: [{ label: 'name', orderBy: 'name' }, { label: 'baz' }],
};
const mountComponent = (propsData = defaultProps) => {
wrapper = shallowMount(component, {
propsData,
stubs: {
GlSortingItem,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('searching', () => {
it('has a filtered-search component', () => {
mountComponent();
expect(findFilteredSearch().exists()).toBe(true);
});
it('binds the correct props to filtered-search', () => {
mountComponent();
expect(findFilteredSearch().props()).toMatchObject({
value: [],
placeholder: 'Filter results',
availableTokens: wrapper.vm.tokens,
});
});
it('emits filter:changed when value changes', () => {
mountComponent();
findFilteredSearch().vm.$emit('input', 'foo');
expect(wrapper.emitted('filter:changed')).toEqual([['foo']]);
});
it('emits filter:submit on submit event', () => {
mountComponent();
findFilteredSearch().vm.$emit('submit');
expect(wrapper.emitted('filter:submit')).toEqual([[]]);
});
it('emits filter:changed and filter:submit on clear event', () => {
mountComponent();
findFilteredSearch().vm.$emit('clear');
expect(wrapper.emitted('filter:changed')).toEqual([[[]]]);
expect(wrapper.emitted('filter:submit')).toEqual([[]]);
});
it('binds tokens prop', () => {
mountComponent();
expect(findFilteredSearch().props('availableTokens')).toEqual(defaultProps.tokens);
});
});
describe('sorting', () => {
it('has all the sortable items', () => {
mountComponent();
expect(findSortingItems()).toHaveLength(defaultProps.sortableFields.length);
});
it('on sort change emits sorting:changed event', () => {
mountComponent();
findPackageListSorting().vm.$emit('sortDirectionChange');
expect(wrapper.emitted('sorting:changed')).toEqual([[{ sort: 'desc' }]]);
});
it('on sort item click emits sorting:changed event ', () => {
mountComponent();
findSortingItems().at(0).vm.$emit('click');
expect(wrapper.emitted('sorting:changed')).toEqual([
[{ orderBy: defaultProps.sortableFields[0].orderBy }],
]);
});
});
});

View File

@ -218,7 +218,7 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
context 'when `to` is given' do
before do
Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) }
Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project, finished_at: Time.zone.now) }
end
it 'finds records created between `from` and `to` range' do
@ -230,12 +230,34 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
end
context 'when `from` and `to` are within a day' do
it 'returns the number of deployments made on that day' do
freeze_time do
create(:deployment, :success, project: project)
options[:from] = options[:to] = Time.now
context 'when query_deploymenys_via_finished_at_in_vsa feature flag is off' do
before do
stub_feature_flags(query_deploymenys_via_finished_at_in_vsa: false)
end
expect(subject).to eq('1')
it 'returns the number of deployments made on that day' do
freeze_time do
create(:deployment, :success, project: project)
options[:from] = options[:to] = Time.zone.now
expect(subject).to eq('1')
end
end
end
context 'when query_deploymenys_via_finished_at_in_vsa feature flag is off' do
before do
stub_feature_flags(query_deploymenys_via_finished_at_in_vsa: true)
end
it 'returns the number of deployments made on that day' do
freeze_time do
create(:deployment, :success, project: project, finished_at: Time.zone.now)
options[:from] = Time.zone.now.at_beginning_of_day
options[:to] = Time.zone.now.at_end_of_day
expect(subject).to eq('1')
end
end
end
end

View File

@ -17,7 +17,7 @@ RSpec.describe API::Jobs do
end
let!(:job) do
create(:ci_build, :success, pipeline: pipeline,
create(:ci_build, :success, :tags, pipeline: pipeline,
artifacts_expire_at: 1.day.since)
end
@ -50,6 +50,7 @@ RSpec.describe API::Jobs do
expect(json_response).not_to be_empty
expect(json_response.first['commit']['id']).to eq project.commit.id
expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at)
expect(json_response.first['tag_list'].sort).to eq job.tag_list.sort
end
context 'without artifacts and trace' do

View File

@ -288,16 +288,6 @@ RSpec.describe Git::WikiPushService, services: true do
expect { subject }.not_to raise_error
end
context 'when feature flag :wiki_housekeeping is disabled' do
it 'does not perform housekeeping' do
stub_feature_flags(wiki_housekeeping: false)
expect(housekeeping).not_to receive(:execute)
subject
end
end
end
it 'increments the push counter' do

View File

@ -3,6 +3,32 @@
module CycleAnalyticsHelpers
include GitHelpers
def wait_for_stages_to_load
expect(page).to have_selector '.js-stage-table'
wait_for_requests
end
def select_group(target_group)
visit group_analytics_cycle_analytics_path(target_group)
wait_for_stages_to_load
end
def toggle_dropdown(field)
page.within("[data-testid='#{field}']") do
find('.dropdown-toggle').click
wait_for_requests
expect(find('.dropdown-menu')).to have_selector('.dropdown-item')
end
end
def select_dropdown_option_by_value(name, value, elem = '.dropdown-item')
toggle_dropdown name
page.find("[data-testid='#{name}'] .dropdown-menu").find("#{elem}[value='#{value}']").click
end
def create_commit_referencing_issue(issue, branch_name: generate(:branch))
project.repository.add_branch(user, branch_name, 'master')
create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name)

View File

@ -4604,7 +4604,7 @@ eslint-import-resolver-node@^0.3.4:
debug "^2.6.9"
resolve "^1.13.1"
eslint-import-resolver-webpack@^0.12.1:
eslint-import-resolver-webpack@0.12.1:
version "0.12.1"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.12.1.tgz#771ae561e887ca4e53ee87605fbb36c5e290b0f5"
integrity sha512-O/sUAXk6GWrICiN8JUkkjdt9uZpqZHP+FVnTxtEILL6EZMaPSrnP4lGPSFwcKsv7O211maqq4Nz60+dh236hVg==
@ -4664,7 +4664,7 @@ eslint-plugin-import@^2.22.1:
resolve "^1.17.0"
tsconfig-paths "^3.9.0"
eslint-plugin-jasmine@^4.1.0:
eslint-plugin-jasmine@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-4.1.0.tgz#4f6d41b1a8622348c97559cbcd29badffa74dbfa"
integrity sha512-Vfuk2Sm1ULR7MqGjVIOOEdQWyoFBfSwvwUeo9MrajVGJB3C24c9Mmj1Cgf8Qwmf3aS2bezPt1sckpKXWpd74Dw==
@ -4676,7 +4676,7 @@ eslint-plugin-jest@^23.8.2:
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
eslint-plugin-no-jquery@^2.3.0:
eslint-plugin-no-jquery@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.3.1.tgz#1c364cb863a38cc1570c8020155b6004cca62178"
integrity sha512-/fiQUBSOMUETnfBuiK5ewvtRbek1IRTy5ov/6RZ6nlybvZ337vyGaNPWM1KgaIoIeN7dairNrPfq0h7A0tpT3A==