Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-06-23 15:07:50 +00:00
parent 71355c5f36
commit 676430584d
82 changed files with 731 additions and 296 deletions

View File

@ -35,7 +35,7 @@ gem 'rexml', '~> 3.2.5'
gem 'ruby-saml', '~> 1.12.1'
gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-activedirectory-v2', '~> 0.1'
gem 'omniauth-azure-activedirectory-v2', '~> 1.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' # Deprecated v1 version
gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0'

View File

@ -617,7 +617,7 @@ GEM
hana (1.3.6)
hangouts-chat (0.0.5)
hashdiff (1.0.1)
hashie (3.6.0)
hashie (4.1.0)
hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0)
health_check (3.0.0)
@ -809,7 +809,7 @@ GEM
shellany (~> 0.0)
numerizer (0.2.0)
oauth (0.5.4)
oauth2 (1.4.4)
oauth2 (1.4.7)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
@ -832,8 +832,8 @@ GEM
train-core
wmi-lite (~> 1.0)
oj (3.10.6)
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-atlassian-oauth2 (0.2.0)
omniauth (>= 1.1.1)
@ -843,8 +843,8 @@ GEM
omniauth-authentiq (0.3.3)
jwt (>= 1.5)
omniauth-oauth2 (>= 1.5)
omniauth-azure-activedirectory-v2 (0.1.1)
omniauth-oauth2
omniauth-azure-activedirectory-v2 (1.0.0)
omniauth-oauth2 (~> 1.7)
omniauth-azure-oauth2 (0.0.10)
jwt (>= 1.0, < 3.0)
omniauth (~> 1.0)
@ -873,9 +873,9 @@ GEM
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
omniauth (~> 1.9)
omniauth-oauth2 (1.7.1)
oauth2 (~> 1.4)
omniauth (>= 1.9, < 3)
omniauth-oauth2-generic (0.2.2)
omniauth-oauth2 (~> 1.0)
omniauth-salesforce (1.0.5)
@ -1566,7 +1566,7 @@ DEPENDENCIES
omniauth-atlassian-oauth2 (~> 0.2.0)
omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.3)
omniauth-azure-activedirectory-v2 (~> 0.1)
omniauth-azure-activedirectory-v2 (~> 1.0)
omniauth-azure-oauth2 (~> 0.0.9)
omniauth-cas3 (~> 1.1.4)
omniauth-facebook (~> 4.0.0)

View File

@ -86,6 +86,10 @@ export const PACKAGE_TYPES = [
title: s__('PackageRegistry|RubyGems'),
type: PackageType.RUBYGEMS,
},
{
title: s__('PackageRegistry|Debian'),
type: PackageType.DEBIAN,
},
];
export const LIST_TITLE_TEXT = s__('PackageRegistry|Package Registry');

View File

@ -9,6 +9,7 @@ export const PackageType = {
COMPOSER: 'composer',
RUBYGEMS: 'rubygems',
GENERIC: 'generic',
DEBIAN: 'debian',
};
// we want this separated from the main dictionary to avoid it being pulled in the search of package

View File

@ -25,6 +25,8 @@ export const getPackageTypeLabel = (packageType) => {
return s__('PackageRegistry|Composer');
case PackageType.GENERIC:
return s__('PackageRegistry|Generic');
case PackageType.DEBIAN:
return s__('PackageRegistry|Debian');
default:
return null;
}

View File

@ -0,0 +1,38 @@
<script>
import { GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
import Tracking from '~/tracking';
import { pipelineEditorTrackingOptions, TEMPLATE_REPOSITORY_URL } from '../../constants';
export default {
i18n: {
browseTemplates: __('Browse templates'),
},
TEMPLATE_REPOSITORY_URL,
components: {
GlButton,
},
mixins: [Tracking.mixin()],
methods: {
trackTemplateBrowsing() {
const { label, actions } = pipelineEditorTrackingOptions;
this.track(actions.browse_templates, { label });
},
},
};
</script>
<template>
<div class="gl-bg-gray-10 gl-p-3 gl-border-solid gl-border-gray-100 gl-border-1">
<gl-button
:href="$options.TEMPLATE_REPOSITORY_URL"
size="small"
icon="external-link"
target="_blank"
@click="trackTemplateBrowsing"
>
{{ $options.i18n.browseTemplates }}
</gl-button>
</div>
</template>

View File

@ -43,7 +43,7 @@ export default {
};
</script>
<template>
<div class="gl-border-solid gl-border-gray-100 gl-border-1">
<div class="gl-border-solid gl-border-gray-100 gl-border-1 gl-border-t-none!">
<source-editor
ref="editor"
:file-name="ciConfigPath"

View File

@ -16,6 +16,7 @@ import {
} from '../constants';
import getAppStatus from '../graphql/queries/client/app_status.graphql';
import CiConfigMergedPreview from './editor/ci_config_merged_preview.vue';
import CiEditorHeader from './editor/ci_editor_header.vue';
import TextEditor from './editor/text_editor.vue';
import CiLint from './lint/ci_lint.vue';
import EditorTab from './ui/editor_tab.vue';
@ -49,6 +50,7 @@ export default {
},
components: {
CiConfigMergedPreview,
CiEditorHeader,
CiLint,
EditorTab,
GlAlert,
@ -107,6 +109,7 @@ export default {
data-testid="editor-tab"
@click="setCurrentTab($options.tabConstants.CREATE_TAB)"
>
<ci-editor-header />
<text-editor :value="ciFileContent" v-on="$listeners" />
</editor-tab>
<editor-tab

View File

@ -33,3 +33,13 @@ export const BRANCH_PAGINATION_LIMIT = 20;
export const BRANCH_SEARCH_DEBOUNCE = '500';
export const STARTER_TEMPLATE_NAME = 'Getting-Started';
export const pipelineEditorTrackingOptions = {
label: 'pipeline_editor',
actions: {
browse_templates: 'browse_templates',
},
};
export const TEMPLATE_REPOSITORY_URL =
'https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates';

View File

@ -1,12 +1,12 @@
<script>
import { GlButton } from '@gitlab/ui';
import allReleasesQuery from 'shared_queries/releases/all_releases.query.graphql';
import createFlash from '~/flash';
import { historyPushState, getParameterByName } from '~/lib/utils/common_utils';
import { scrollUp } from '~/lib/utils/scroll_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import { PAGE_SIZE, DEFAULT_SORT } from '~/releases/constants';
import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql';
import { convertAllReleasesGraphQLResponse } from '~/releases/util';
import ReleaseBlock from './release_block.vue';
import ReleaseSkeletonLoader from './release_skeleton_loader.vue';

View File

@ -1,4 +1,5 @@
fragment Release on Release {
__typename
name
tagName
tagPath
@ -7,15 +8,20 @@ fragment Release on Release {
createdAt
upcomingRelease
assets {
__typename
count
sources {
__typename
nodes {
__typename
format
url
}
}
links {
__typename
nodes {
__typename
id
name
url
@ -26,13 +32,16 @@ fragment Release on Release {
}
}
evidences {
__typename
nodes {
__typename
filepath
collectedAt
sha
}
}
links {
__typename
editUrl
selfUrl
openedIssuesUrl
@ -42,22 +51,27 @@ fragment Release on Release {
closedMergeRequestsUrl
}
commit {
__typename
sha
webUrl
title
}
author {
__typename
webUrl
avatarUrl
username
}
milestones {
__typename
nodes {
__typename
id
title
description
webPath
stats {
__typename
totalIssuesCount
closedIssuesCount
}

View File

@ -1,5 +1,11 @@
#import "../fragments/release.fragment.graphql"
# This query is identical to
# `app/graphql/queries/releases/all_releases.query.graphql`.
# These two queries should be kept in sync.
# When the `releases_index_apollo_client` feature flag is
# removed, this query should be removed entirely.
query allReleases(
$fullPath: ID!
$first: Int
@ -9,11 +15,14 @@ query allReleases(
$sort: ReleaseSort
) {
project(fullPath: $fullPath) {
__typename
releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
__typename
nodes {
...Release
}
pageInfo {
__typename
startCursor
hasPreviousPage
hasNextPage

View File

@ -34,8 +34,8 @@ export const DAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/das
});
export const DAST_PROFILES_NAME = __('DAST Scans');
export const DAST_PROFILES_DESCRIPTION = __(
'Saved scan settings and target site settings which are reusable.',
export const DAST_PROFILES_DESCRIPTION = s__(
'SecurityConfiguration|Manage profiles for use by DAST scans.',
);
export const DAST_PROFILES_HELP_PATH = helpPagePath('user/application_security/dast/index');
export const DAST_PROFILES_CONFIG_TEXT = s__('SecurityConfiguration|Manage scans');

View File

@ -8,12 +8,15 @@ import UpgradeBanner from './upgrade_banner.vue';
export const i18n = {
compliance: s__('SecurityConfiguration|Compliance'),
configurationHistory: s__('SecurityConfiguration|Configuration history'),
securityTesting: s__('SecurityConfiguration|Security testing'),
securityTestingDescription: s__(
latestPipelineDescription: s__(
`SecurityConfiguration|The status of the tools only applies to the
default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.
Once you've enabled a scan for the default branch, any subsequent feature
branch you create will include the scan.`,
default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.`,
),
description: s__(
`SecurityConfiguration|Once you've enabled a scan for the default branch,
any subsequent feature branch you create will include the scan.`,
),
securityConfiguration: __('Security Configuration'),
};
@ -84,16 +87,19 @@ export default {
<gl-tab data-testid="security-testing-tab" :title="$options.i18n.securityTesting">
<section-layout :heading="$options.i18n.securityTesting">
<template #description>
<p
v-if="latestPipelinePath"
data-testid="latest-pipeline-info-security"
class="gl-line-height-20"
>
<gl-sprintf :message="$options.i18n.securityTestingDescription">
<template #link="{ content }">
<gl-link :href="latestPipelinePath">{{ content }}</gl-link>
</template>
</gl-sprintf>
<p>
<span data-testid="latest-pipeline-info-security">
<gl-sprintf
v-if="latestPipelinePath"
:message="$options.i18n.latestPipelineDescription"
>
<template #link="{ content }">
<gl-link :href="latestPipelinePath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
{{ $options.i18n.description }}
</p>
<p v-if="canViewCiHistory">
<gl-link data-testid="security-view-history-link" :href="gitlabCiHistoryPath">{{
@ -115,16 +121,19 @@ export default {
<gl-tab data-testid="compliance-testing-tab" :title="$options.i18n.compliance">
<section-layout :heading="$options.i18n.compliance">
<template #description>
<p
v-if="latestPipelinePath"
class="gl-line-height-20"
data-testid="latest-pipeline-info-compliance"
>
<gl-sprintf :message="$options.i18n.securityTestingDescription">
<template #link="{ content }">
<gl-link :href="latestPipelinePath">{{ content }}</gl-link>
</template>
</gl-sprintf>
<p>
<span data-testid="latest-pipeline-info-compliance">
<gl-sprintf
v-if="latestPipelinePath"
:message="$options.i18n.latestPipelineDescription"
>
<template #link="{ content }">
<gl-link :href="latestPipelinePath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
{{ $options.i18n.description }}
</p>
<p v-if="canViewCiHistory">
<gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{

View File

@ -11,12 +11,12 @@ export default {
</script>
<template>
<div class="row">
<div class="col-lg-5">
<div class="row gl-line-height-20">
<div class="col-lg-4">
<h2 class="gl-font-size-h2 gl-mt-0">{{ heading }}</h2>
<slot name="description"></slot>
</div>
<div class="col-lg-7">
<div class="col-lg-8">
<slot name="features"></slot>
</div>
</div>

View File

@ -0,0 +1,105 @@
# This query is identical to
# `app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql`.
# These two queries should be kept in sync.
query allReleases(
$fullPath: ID!
$first: Int
$last: Int
$before: String
$after: String
$sort: ReleaseSort
) {
project(fullPath: $fullPath) {
__typename
releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
__typename
nodes {
__typename
name
tagName
tagPath
descriptionHtml
releasedAt
createdAt
upcomingRelease
assets {
__typename
count
sources {
__typename
nodes {
__typename
format
url
}
}
links {
__typename
nodes {
__typename
id
name
url
directAssetUrl
linkType
external
}
}
}
evidences {
__typename
nodes {
__typename
filepath
collectedAt
sha
}
}
links {
__typename
editUrl
selfUrl
openedIssuesUrl
closedIssuesUrl
openedMergeRequestsUrl
mergedMergeRequestsUrl
closedMergeRequestsUrl
}
commit {
__typename
sha
webUrl
title
}
author {
__typename
webUrl
avatarUrl
username
}
milestones {
__typename
nodes {
__typename
id
title
description
webPath
stats {
__typename
totalIssuesCount
closedIssuesCount
}
}
}
}
pageInfo {
__typename
startCursor
hasPreviousPage
hasNextPage
endCursor
}
}
}
}

View File

@ -4,6 +4,10 @@ module ReleasesHelper
IMAGE_PATH = 'illustrations/releases.svg'
DOCUMENTATION_PATH = 'user/project/releases/index'
# This needs to be kept in sync with the constant in
# app/assets/javascripts/releases/constants.js
DEFAULT_SORT = 'RELEASED_AT_DESC'
def illustration
image_path(IMAGE_PATH)
end
@ -25,6 +29,19 @@ module ReleasesHelper
end
end
# For simplicity, only optimize non-paginated requests
def use_startup_query_for_index_page?
params[:before].nil? && params[:after].nil?
end
def index_page_startup_query_variables
{
fullPath: @project.full_path,
sort: DEFAULT_SORT,
first: 1
}
end
def data_for_show_page
{
project_id: @project.id,

View File

@ -929,8 +929,7 @@ module Ci
end
def supports_artifacts_exclude?
options&.dig(:artifacts, :exclude)&.any? &&
Gitlab::Ci::Features.artifacts_exclude_enabled?
options&.dig(:artifacts, :exclude)&.any?
end
def multi_build_steps?

View File

@ -82,7 +82,7 @@ module Ci
expire_in: artifacts[:expire_in]
}
if artifacts.dig(:exclude).present? && ::Gitlab::Ci::Features.artifacts_exclude_enabled?
if artifacts.dig(:exclude).present?
archive.merge(exclude: artifacts[:exclude])
else
archive

View File

@ -142,7 +142,10 @@ module MergeRequests
params[:add_assignee_ids] = params.delete(:assign).keys if params.has_key?(:assign)
params[:remove_assignee_ids] = params.delete(:unassign).keys if params.has_key?(:unassign)
params[:milestone] = project.milestones&.find_by_name(push_options[:milestone]) if push_options[:milestone]
if push_options[:milestone]
milestone = Milestone.for_projects_and_groups(@project, @project.ancestors_upto)&.find_by_name(push_options[:milestone])
params[:milestone] = milestone if milestone
end
params
end

View File

@ -1,3 +1,5 @@
- page_title _('Releases')
- if use_startup_query_for_index_page?
- add_page_startup_graphql_call('releases/all_releases', index_page_startup_query_variables)
#js-releases-page{ data: data_for_releases_page }

View File

@ -1,4 +1,6 @@
- breadcrumb_title _("Security Configuration")
- page_title _("Security Configuration")
- redesign_enabled = ::Feature.enabled?(:security_configuration_redesign, default_enabled: :yaml)
- @content_class = "limit-container-width" unless fluid_layout || !redesign_enabled
#js-security-configuration-static{ data: { project_path: @project.full_path, upgrade_path: security_upgrade_path } }

View File

@ -32,7 +32,9 @@ module WaitableWorker
failed = []
args_list.each do |args|
new.perform(*args)
worker = new
Gitlab::AppJsonLogger.info(worker.structured_payload(message: 'running inline'))
worker.perform(*args)
rescue StandardError
failed << args
end

View File

@ -1,8 +0,0 @@
---
name: ci_artifacts_exclude
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30708
rollout_issue_url:
milestone: '13.0'
type: development
group: group::pipeline execution
default_enabled: true

View File

@ -11,6 +11,7 @@ milestone: "9.1"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521
time_frame: none
data_source: database
data_category: Standard
instrumentation_class: UuidMetric
distribution:
- ee

View File

@ -9,6 +9,7 @@ value_type: string
status: data_available
time_frame: none
data_source: system
data_category: Standard
instrumentation_class: HostnameMetric
distribution:
- ce

View File

@ -515,13 +515,21 @@ For instructions about how to set up Patroni on the primary site, see the
In a Geo secondary site, the main PostgreSQL database is a read-only replica of the primary sites PostgreSQL database.
If you are currently using `repmgr` on your Geo primary site, see [these instructions](#migrating-from-repmgr-to-patroni) for migrating from `repmgr` to Patroni.
If you are currently using `repmgr` on your Geo primary site, see [these instructions](#migrating-from-repmgr-to-patroni)
for migrating from `repmgr` to Patroni.
A production-ready and secure setup requires at least three Consul nodes, three
Patroni nodes, one internal load-balancing node on the primary site, and a similar
configuration for the secondary site. The internal load balancer provides a single
endpoint for connecting to the Patroni cluster's leader whenever a new leader is
elected. Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni) and other database best practices.
A production-ready and secure setup requires at least:
- 3 Consul nodes _(primary and secondary sites)_
- 2 Patroni nodes _(primary and secondary sites)_
- 1 PgBouncer node _(primary and secondary sites)_
- 1 internal load-balancer _(primary site only)_
The internal load balancer provides a single endpoint for connecting to the Patroni cluster's leader whenever a new leader is
elected, and it is required for enabling cascading replication from the secondary sites.
Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni)
and other database best practices.
##### Step 1. Configure Patroni permanent replication slot on the primary site
@ -781,18 +789,18 @@ by following the same instructions above.
Secondary sites use a separate PostgreSQL installation as a tracking database to
keep track of replication status and automatically recover from potential replication issues.
Omnibus automatically configures a tracking database when `roles(['geo_secondary_role'])` is set.
If you want to run this database in a highly available configuration, follow the instructions below.
A production-ready and secure setup requires at least three Consul nodes, three
Patroni nodes on the secondary site secondary site. Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni) and other database best practices.
If you want to run this database in a highly available configuration, don't use the `geo_secondary_role` above.
Instead, follow the instructions below.
A production-ready and secure setup requires at least three Consul nodes, two
Patroni nodes and one PgBouncer node on the secondary site.
Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni)
and other database best practices.
#### Step 1. Configure a PgBouncer node on the secondary site
A production-ready and highly available configuration requires at least
three Consul nodes, three PgBouncer nodes, and one internal load-balancing node.
The internal load balancer provides a single endpoint for connecting to the
PgBouncer cluster. For more information, see [High Availability with Omnibus GitLab](../../postgresql/replication_and_failover.md).
Follow the minimal configuration for the PgBouncer node for the tracking database:
1. SSH into your PgBouncer node and login as root:

View File

@ -4,9 +4,7 @@ group: Project Management
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
---
# Award Emoji API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4575) in GitLab 8.9. Snippet support added in 8.12.
# Award emoji API **(FREE)**
An [awarded emoji](../user/award_emojis.md) tells a thousand words.

View File

@ -4,9 +4,9 @@ group: Project Management
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
---
# Project Issue Boards API
# Project issue boards API **(FREE)**
Every API call to boards must be authenticated.
Every API call to [issue boards](../user/project/issue_board.md) must be authenticated.
If a user is not a member of a private project,
a `GET` request on that project results in a `404` status code.

View File

@ -4,10 +4,10 @@ group: Project Management
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
---
# Identify issue boards with GraphQL
# Identify issue boards with GraphQL **(FREE)**
This page describes how you can use the GraphiQL explorer to identify
existing issue boards in the `gitlab-docs` documentation repository.
existing [issue boards](../../user/project/issue_board.md) in the `gitlab-docs` documentation repository.
## Set up the GraphiQL explorer

View File

@ -4,16 +4,16 @@ group: Project Management
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
---
# Group Issue Boards API
# Group issue boards API **(FREE)**
Every API call to group boards must be authenticated.
Every API call to [group issue boards](../user/project/issue_board.md#group-issue-boards) must be authenticated.
If a user is not a member of a group and the group is private, a `GET`
request results in `404` status code.
## List all group issue boards in a group
Lists Issue Boards in the given group.
Lists issue boards in the given group.
```plaintext
GET /groups/:id/boards

View File

@ -4,11 +4,13 @@ group: Project Management
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
---
# Group Labels API
# Group labels API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21368) in GitLab 11.8.
This API supports managing of [group labels](../user/project/labels.md#project-labels-and-group-labels). It allows to list, create, update, and delete group labels. Furthermore, users can subscribe and unsubscribe to and from group labels.
This API supports managing [group labels](../user/project/labels.md#project-labels-and-group-labels).
It allows users to list, create, update, and delete group labels. Furthermore, users can subscribe to and
unsubscribe from group labels.
NOTE:
The `description_html` - was added to response JSON in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413).

View File

@ -4,11 +4,9 @@ group: Project Management
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
---
# Group milestones API
# Group milestones API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12819) in GitLab 9.5.
This page describes the group milestones API.
Use the group [milestones](../user/project/milestones/index.md) using the REST API.
There's a separate [project milestones API](milestones.md) page.
## List group milestones

View File

@ -4,7 +4,9 @@ group: Project Management
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
---
# Issues API
# Issues API **(FREE)**
Interact with [GitLab Issues](../user/project/issues/index.md) using the REST API.
If a user is not a member of a private project, a `GET`
request on that project results in a `404` status code.

View File

@ -4,9 +4,9 @@ group: Project Management
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
---
# Issues Statistics API
# Issues statistics API **(FREE)**
Every API call to issues_statistics must be authenticated.
Every API call to the [issues](../user/project/issues/index.md) statistics API must be authenticated.
If a user is not a member of a project and the project is private, a `GET`
request on that project results in a `404` status code.

View File

@ -4,7 +4,9 @@ group: Project Management
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
---
# Labels API
# Labels API **(FREE)**
Interact with [labels](../user/project/labels.md) using the REST API.
NOTE:
The `description_html` - was added to response JSON in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413).

View File

@ -4,9 +4,9 @@ group: Project Management
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
---
# Project milestones API
# Project milestones API **(FREE)**
This page describes the project milestones API.
Use project [milestones](../user/project/milestones/index.md) with the REST API.
There's a separate [group milestones API](group_milestones.md) page.
## List project milestones

View File

@ -4,22 +4,20 @@ group: Project Management
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
---
# Notification settings API
# Notification settings API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5632) in GitLab 8.12.
Change [notification settings](../user/profile/notifications.md) using the REST API.
## Valid notification levels
The notification levels are defined in the `NotificationSetting.level` model enumeration. Currently, these levels are recognized:
```plaintext
disabled
participating
watch
global
mention
custom
```
- `disabled`
- `participating`
- `watch`
- `global`
- `mention`
- `custom`
If the `custom` level is used, specific email events can be controlled. Available events are returned by `NotificationSetting.email_events`. Currently, these events are recognized:

View File

@ -4,7 +4,9 @@ group: Project Management
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
---
# Projects API
# Projects API **(FREE)**
Interact with [projects](../user/project/index.md) using the REST API.
## Project visibility level

View File

@ -4,12 +4,12 @@ group: Project Management
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
---
# Resource milestone events API
# Resource milestone events API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31720) in GitLab 13.1.
Resource milestone events keep track of what happens to GitLab [issues](../user/project/issues/) and
[merge requests](../user/project/merge_requests/).
Resource [milestone](../user/project/milestones/index.md) events keep track of what happens to
GitLab [issues](../user/project/issues/) and [merge requests](../user/project/merge_requests/).
Use them to track which milestone was added or removed, who did it, and when it happened.

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Resource state events API
# Resource state events API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35210/) in GitLab 13.2.

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Resource weight events API
# Resource weight events API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32542) in GitLab 13.2.

View File

@ -4,13 +4,13 @@ group: Project Management
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
---
# To dos API
# GitLab To-Do List API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3188) in GitLab 8.10.
Interact with [to-do items](../user/todos.md) using the REST API.
## Get a list of to dos
## Get a list of to-do items
Returns a list of [to-do items](../user/todos.md). When no filter is applied, it
Returns a list of to-do items. When no filter is applied, it
returns all pending to-do items for the current user. Different filters allow the
user to refine the request.
@ -26,7 +26,7 @@ Parameters:
| `author_id` | integer | no | The ID of an author |
| `project_id` | integer | no | The ID of a project |
| `group_id` | integer | no | The ID of a group |
| `state` | string | no | The state of the to do. Can be either `pending` or `done` |
| `state` | string | no | The state of the to-do item. Can be either `pending` or `done` |
| `type` | string | no | The type of to-do item. Can be either `Issue`, `MergeRequest`, `DesignManagement::Design` or `AlertManagement::Alert` |
```shell
@ -190,8 +190,8 @@ Example Response:
## Mark a to-do item as done
Marks a single pending to do given by its ID for the current user as done. The
to do marked as done is returned in the response.
Marks a single pending to-do item given by its ID for the current user as done. The
to-do item marked as done is returned in the response.
```plaintext
POST /todos/:id/mark_as_done
@ -287,9 +287,9 @@ Example Response:
}
```
## Mark all to dos as done
## Mark all to-do items as done
Marks all pending to dos for the current user as done. It returns the HTTP status code `204` with an empty response.
Marks all pending to-do items for the current user as done. It returns the HTTP status code `204` with an empty response.
```plaintext
POST /todos/mark_as_done

View File

@ -653,7 +653,7 @@ Example response:
## CI minute provisioning
The CI Minute endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
The CI Minute endpoints are used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
to apply additional packs of CI minutes, for personal namespaces or top-level groups within GitLab.com.
### Creating an additional pack
@ -694,6 +694,39 @@ Example response:
}
```
### Moving additional packs
Use a PATCH to move additional packs from one namespace to another.
```plaintext
PATCH /namespaces/:id/minutes/move/:target_id
```
| Attribute | Type | Required | Description |
|:------------|:--------|:---------|:------------|
| `id` | string | yes | The ID of the namespace to transfer packs from |
| `target_id` | string | yes | The ID of the target namespace to transfer the packs to |
Example request:
```shell
curl --request PATCH \
--url http://localhost:3000/api/v4/namespaces/123/minutes/move/321 \
--header 'PRIVATE-TOKEN: <admin access token>'
```
Example response:
```json
{
"message": "202 Accepted"
}
```
### Known consumers
- CustomersDot
## Upcoming reconciliations
The `upcoming_reconciliations` endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)

View File

@ -4,7 +4,7 @@ group: Product Intelligence
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
---
# Usage Ping Guide
# Usage Ping Guide **(FREE SELF)**
> Introduced in GitLab Ultimate 11.2, more statistics.
@ -37,7 +37,7 @@ and sales teams understand how GitLab is used. For example, the data helps to:
Usage Ping information is not anonymous. It's linked to the instance's hostname. However, it does
not contain project names, usernames, or any other specific data.
Sending a Usage Ping payload is optional and can be [disabled](#disable-usage-ping) on any instance.
Sending a Usage Ping payload is optional and can be [disabled](#disable-usage-ping) on any self-managed instance.
When Usage Ping is enabled, GitLab gathers data from the other instances
and can show your instance's usage statistics to your users.
@ -66,7 +66,7 @@ We use the following terminology to describe the Usage Ping components:
- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events.
- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed.
## Usage Ping payload
## View the Usage Ping payload **(FREE SELF)**
You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload:
@ -78,7 +78,7 @@ You can view the exact JSON payload sent to GitLab Inc. in the administration pa
For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload).
## Disable Usage Ping
## Disable Usage Ping **(FREE SELF)**
NOTE:
The method to disable Usage Ping in the GitLab configuration file does not work in

View File

@ -25,6 +25,27 @@ For each security control the page displays:
- **Security Control:** Name, description, and a documentation link.
- **Manage:** A management option or a documentation link.
## UI redesign
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326926) in 14.0 for GitLab Free and Premium, behind a feature flag, disabled by default.
> - Enabled on GitLab.com.
> - Recommended for production use.
> - It can be enabled or disabled for a single project.
> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-ui-redesign). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
The Security Configuration page has been redesigned in GitLab Free and Premium.
The same functionality exists as before, but presented in a more extensible
way.
For each security control the page displays:
- Its name, description and a documentation link.
- Whether or not it is available.
- A configuration button or a link to its configuration guide.
## Status **(ULTIMATE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
@ -52,3 +73,28 @@ You can configure the following security controls:
- Secret Detection
- Select **Configure via Merge Request** to create a merge request with the changes required to
enable Secret Detection. For more details, see [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request).
## Enable or disable UI redesign **(FREE SELF)**
The Security Configuration redesign is under development, but is ready for
production use. It is deployed behind a feature flag that is **disabled by
default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can enable it.
To enable it:
```ruby
# For the instance
Feature.enable(:security_configuration_redesign)
# For a single project
Feature.enable(:security_configuration_redesign, Project.find(<project id>))
```
To disable it:
```ruby
# For the instance
Feature.disable(:security_configuration_redesign)
# For a single project
Feature.disable(:security_configuration_redesign, Project.find(<project id>))
```

View File

@ -5,8 +5,6 @@ group: Product Planning
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
---
<!-- When adding a new h2 section here, remember to mention it in index.md#manage-epics -->
# Manage epics **(PREMIUM)**
This page collects instructions for all the things you can do with [epics](index.md) or in relation

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Description templates
# Description templates **(FREE)**
We all know that a properly submitted issue is more likely to be addressed in
a timely manner by the developers of a project.

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Import your Jira project issues to GitLab
# Import your Jira project issues to GitLab **(PREMIUM)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2766) in GitLab 12.10.

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Associate a Zoom meeting with an issue
# Associate a Zoom meeting with an issue **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609) in GitLab 12.4.

View File

@ -4,11 +4,9 @@ group: Project Management
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
---
# Confidential issues
# Confidential issues **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3282) in GitLab 8.6.
Confidential issues are issues visible only to members of a project with
Confidential issues are [issues](index.md) visible only to members of a project with
[sufficient permissions](#permissions-and-access-to-confidential-issues).
Confidential issues can be used by open source projects and companies alike to
keep security vulnerabilities private or prevent surprises from leaking out.

View File

@ -4,9 +4,9 @@ group: Project Management
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
---
# Crosslinking issues
# Crosslinking issues **(FREE)**
There are several ways to mention an issue or make issues appear in each other's
There are several ways to mention an issue or make [issues](index.md) appear in each other's
[Linked issues](related_issues.md) section.
For more information on GitLab Issues, read the [issues documentation](index.md).

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Issue Data and Actions
# Issue Data and Actions **(FREE)**
Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.

View File

@ -4,7 +4,7 @@ group: Project Management
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
---
# Managing issues
# Managing issues **(FREE)**
[GitLab Issues](index.md) are the fundamental medium for collaborating on ideas and
planning work in GitLab.

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -113,6 +113,32 @@ To complete the deletion of the status check you must select the
**Remove status check** button. This **permanently** deletes
the status check and it **will not** be recoverable.
## Status checks widget
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327634) in GitLab 14.1.
> - The [external status checks](#external-status-checks) feature must be [enabled](#enable-or-disable-status-checks) to see the status checks widget.
The status checks widget displays in merge requests and shows the status of external
status checks:
![Status checks widget](img/status_checks_widget_passed_v14_0.png)
An organization might have a policy that does not allow merging merge requests if
external status checks do not pass. However, the details in the widget are for informational
purposes only. GitLab does not prevent merging of merge requests that fail status checks.
While GitLab waits for a response from the external status check, the widget shows
the status checks as `pending`:
![Status checks widget pending](img/status_checks_widget_pending_v14_0.png)
After GitLab [receives a response](../../../api/status_checks.md#set-approval-status-of-an-external-status-check)
from the external status check, the widget updates accordingly.
NOTE:
GitLab cannot guarantee that the external status checks are properly processed by
the related external service.
## Troubleshooting
### Duplicate value errors
@ -149,6 +175,19 @@ An unexpected response was received from the branches retrieval API.
As suggested, you should close the form and reopen again or refresh the page. This error should be temporary, although
if it persists please check the [GitLab status page](https://status.gitlab.com/) to see if there is a wider outage.
### Failed to load status checks
```plaintext
Failed to load status checks
```
An unexpected response was received from the external status checks API.
You should:
- Refresh the page in case this error is temporary.
- Check the [GitLab status page](https://status.gitlab.com/) if the problem persists,
to see if there is a wider outage.
## Enable or disable status checks **(ULTIMATE SELF)**
Status checks are under development and not ready for production use. It is

View File

@ -62,3 +62,9 @@ merge request widget takes you directly to the pages changed, making it easier a
faster to preview proposed modifications.
[Read more about Review Apps](../../../ci/review_apps/index.md).
## External status checks **(ULTIMATE)**
If you have configured [external status checks](status_checks.md) you can
see the status of these checks in merge requests
[in a specific widget](status_checks.md#status-checks-widget).

View File

@ -6,9 +6,7 @@ group: Project Management
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
---
# Time Tracking
> Introduced in GitLab 8.14.
# Time Tracking **(FREE)**
Time Tracking allows you to track estimates and time spent on issues and merge
requests within GitLab.

View File

@ -56,7 +56,7 @@ A to-do item appears on your To-Do List when:
and you're the user that added it.
When several trigger actions occur for the same user on the same object (for
example, an issue), GitLab displays only the first action as a single to do
example, an issue), GitLab displays only the first action as a single to-do
item.
To-do item triggers aren't affected by [GitLab notification email settings](profile/notifications.md).
@ -99,7 +99,7 @@ You can also add the following to your To-Do List by clicking the **Add a to do*
- [Epics](group/epics/index.md)
- [Designs](project/issues/design_management.md)
![Adding a to-do item from the issuable sidebar](img/todos_add_todo_sidebar.png)
![Adding a to-do item from the issuable sidebar](img/todos_add_todo_sidebar_v14_1.png)
## Marking a to-do item as done
@ -129,12 +129,12 @@ If no action is needed, you can manually mark the to-do item as done by
clicking its corresponding **Done** button to have GitLab remove the item from
your To-Do List.
![A to do in the To-Do List](img/todos_todo_list_item.png)
![A to-do in the To-Do List](img/todos_todo_list_item.png)
You can also mark a to-do item as done by clicking the **Mark as done** button
in the sidebar of an issue, merge request, or epic.
![Mark as done from the issuable sidebar](img/todos_mark_done_sidebar.png)
![Mark as done from the issuable sidebar](img/todos_mark_done_sidebar_v14_1.png)
You can mark all your to-do items as done at once by clicking the
**Mark all as done** button.
@ -147,9 +147,9 @@ You can use the following types of filters with your To-Do List:
| ------- | ---------------------------------------------------------------- |
| Project | Filter by project. |
| Group | Filter by group. |
| Author | Filter by the author that triggered the to do. |
| Author | Filter by the author that triggered the to-do item. |
| Type | Filter by issue, merge request, design, or epic. |
| Action | Filter by the action that triggered the to do. |
| Action | Filter by the action that triggered the to-do item. |
You can also filter by more than one of these at the same time. The previously
described [triggering actions](#what-triggers-a-to-do-item) include:

View File

@ -36,8 +36,7 @@ module Gitlab
}, if: :expose_as_present?
validates :expose_as, type: String, length: { maximum: 100 }, if: :expose_as_present?
validates :expose_as, format: { with: EXPOSE_AS_REGEX, message: EXPOSE_AS_ERROR_MESSAGE }, if: :expose_as_present?
validates :exclude, array_of_strings: true, if: :exclude_enabled?
validates :exclude, absence: { message: 'feature is disabled' }, unless: :exclude_enabled?
validates :exclude, array_of_strings: true
validates :reports, type: Hash
validates :when,
inclusion: { in: %w[on_success on_failure always],
@ -60,10 +59,6 @@ module Gitlab
!@config[:expose_as].nil?
end
def exclude_enabled?
::Gitlab::Ci::Features.artifacts_exclude_enabled?
end
end
end
end

View File

@ -6,10 +6,6 @@ module Gitlab
# Ci::Features is a class that aggregates all CI/CD feature flags in one place.
#
module Features
def self.artifacts_exclude_enabled?
::Feature.enabled?(:ci_artifacts_exclude, default_enabled: true)
end
# NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`
# is a safe switch to disable the feature for a particular project when something went wrong,
# therefore it's not supposed to be enabled by default.

View File

@ -25,7 +25,6 @@ module Gitlab
::Gitlab::InstrumentationHelper.add_instrumentation_data(payload)
payload[:queue_duration_s] = event.payload[:queue_duration_s] if event.payload[:queue_duration_s]
payload[:response] = event.payload[:response] if event.payload[:response]
payload[:etag_route] = event.payload[:etag_route] if event.payload[:etag_route]
payload[Labkit::Correlation::CorrelationId::LOG_KEY] = event.payload[Labkit::Correlation::CorrelationId::LOG_KEY] || Labkit::Correlation::CorrelationId.current_id

View File

@ -5579,6 +5579,9 @@ msgstr ""
msgid "Browse files"
msgstr ""
msgid "Browse templates"
msgstr ""
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr ""
@ -23204,6 +23207,9 @@ msgstr ""
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
msgid "PackageRegistry|Delete Package File"
msgstr ""
@ -28303,9 +28309,6 @@ msgstr ""
msgid "Save space and find images in the container Registry. remove unneeded tags and keep only the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
msgstr ""
msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
msgid "Saving"
msgstr ""
@ -28697,6 +28700,9 @@ msgstr ""
msgid "SecurityConfiguration|Configuration guide"
msgstr ""
msgid "SecurityConfiguration|Configuration history"
msgstr ""
msgid "SecurityConfiguration|Configure"
msgstr ""
@ -28745,6 +28751,9 @@ msgstr ""
msgid "SecurityConfiguration|Manage"
msgstr ""
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr ""
msgid "SecurityConfiguration|Manage scans"
msgstr ""
@ -28754,6 +28763,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
msgstr ""
msgid "SecurityConfiguration|Runtime security metrics for application environments."
msgstr ""
@ -28778,7 +28790,7 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
msgid "SecurityConfiguration|Upgrade or start a free trial"

View File

@ -14,9 +14,14 @@ RSpec.describe 'User views releases', :js do
let_it_be(:maintainer) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:internal_link) { create(:release_link, release: release_v1, name: 'An internal link', url: "#{project.web_url}/-/jobs/1/artifacts/download", filepath: nil) }
let_it_be(:internal_link_with_redirect) { create(:release_link, release: release_v1, name: 'An internal link with a redirect', url: "#{project.web_url}/-/jobs/2/artifacts/download", filepath: '/binaries/linux-amd64' ) }
let_it_be(:external_link) { create(:release_link, release: release_v1, name: 'An external link', url: "https://example.com/an/external/link", filepath: nil) }
before do
project.add_maintainer(maintainer)
project.add_guest(guest)
stub_default_url_options(host: 'localhost')
end
shared_examples 'releases index page' do
@ -25,6 +30,8 @@ RSpec.describe 'User views releases', :js do
sign_in(maintainer)
visit project_releases_path(project)
wait_for_requests
end
it 'sees the release' do
@ -35,38 +42,18 @@ RSpec.describe 'User views releases', :js do
end
end
context 'when there is a link as an asset' do
let!(:release_link) { create(:release_link, release: release_v1, url: url ) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{release_link.filepath}" }
it 'renders the correct links', :aggregate_failures do
page.within("##{release_v1.tag} .js-assets-list") do
external_link_indicator_selector = '[data-testid="external-link-indicator"]'
it 'sees the link' do
page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end
end
expect(page).to have_link internal_link.name, href: internal_link.url
expect(find_link(internal_link.name)).not_to have_css(external_link_indicator_selector)
context 'when there is a link redirect' do
let!(:release_link) { create(:release_link, release: release_v1, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
expect(page).to have_link internal_link_with_redirect.name, href: Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{internal_link_with_redirect.filepath}"
expect(find_link(internal_link_with_redirect.name)).not_to have_css(external_link_indicator_selector)
it 'sees the link', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/329301' do
page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_link release_link.name, href: direct_asset_link
expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end
end
end
context 'when url points to external resource' do
let(:url) { 'http://google.com/download' }
it 'sees that the link is external resource', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/329302' do
page.within("##{release_v1.tag} .js-assets-list") do
expect(page).to have_css('[data-testid="external-link-indicator"]')
end
end
expect(page).to have_link external_link.name, href: external_link.url
expect(find_link(external_link.name)).to have_css(external_link_indicator_selector)
end
end

View File

@ -40,6 +40,7 @@ describe('Packages shared utils', () => {
${'pypi'} | ${'PyPI'}
${'rubygems'} | ${'RubyGems'}
${'composer'} | ${'Composer'}
${'debian'} | ${'Debian'}
${'foo'} | ${null}
`(`package type`, ({ packageType, expectedResult }) => {
it(`${packageType} should show as ${expectedResult}`, () => {

View File

@ -0,0 +1,53 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import CiEditorHeader from '~/pipeline_editor/components/editor/ci_editor_header.vue';
import {
pipelineEditorTrackingOptions,
TEMPLATE_REPOSITORY_URL,
} from '~/pipeline_editor/constants';
describe('CI Editor Header', () => {
let wrapper;
let trackingSpy = null;
const createComponent = () => {
wrapper = shallowMount(CiEditorHeader, {});
};
const findLinkBtn = () => wrapper.findComponent(GlButton);
afterEach(() => {
wrapper.destroy();
unmockTracking();
});
describe('link button', () => {
beforeEach(() => {
createComponent();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
it('finds the browse template button', () => {
expect(findLinkBtn().exists()).toBe(true);
});
it('contains the link to the template repo', () => {
expect(findLinkBtn().attributes('href')).toBe(TEMPLATE_REPOSITORY_URL);
});
it('has the external-link icon', () => {
expect(findLinkBtn().props('icon')).toBe('external-link');
});
it('tracks the click on the browse button', async () => {
const { label, actions } = pipelineEditorTrackingOptions;
await findLinkBtn().vm.$emit('click');
expect(trackingSpy).toHaveBeenCalledWith(undefined, actions.browse_templates, {
label,
});
});
});
});

View File

@ -5,6 +5,7 @@ Object {
"data": Array [
Object {
"_links": Object {
"__typename": "ReleaseLinks",
"closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.2&scope=all&state=closed",
"closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.2&scope=all&state=closed",
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.2/edit",
@ -19,24 +20,29 @@ Object {
"links": Array [],
"sources": Array [
Object {
"__typename": "ReleaseSource",
"format": "zip",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.zip",
},
Object {
"__typename": "ReleaseSource",
"format": "tar.gz",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.tar.gz",
},
Object {
"__typename": "ReleaseSource",
"format": "tar.bz2",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.tar.bz2",
},
Object {
"__typename": "ReleaseSource",
"format": "tar",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.2/releases-project-v1.2.tar",
},
],
},
"author": Object {
"__typename": "UserCore",
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
"username": "administrator",
"webUrl": "http://localhost/administrator",
@ -57,6 +63,7 @@ Object {
},
Object {
"_links": Object {
"__typename": "ReleaseLinks",
"closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=closed",
"closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=closed",
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/edit",
@ -70,6 +77,7 @@ Object {
"count": 8,
"links": Array [
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-3",
"external": true,
"id": "gid://gitlab/Releases::Link/13",
@ -78,6 +86,7 @@ Object {
"url": "https://example.com/image",
},
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-2",
"external": true,
"id": "gid://gitlab/Releases::Link/12",
@ -86,6 +95,7 @@ Object {
"url": "https://example.com/package",
},
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-1",
"external": false,
"id": "gid://gitlab/Releases::Link/11",
@ -94,6 +104,7 @@ Object {
"url": "http://localhost/releases-namespace/releases-project/runbook",
},
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/linux-amd64",
"external": true,
"id": "gid://gitlab/Releases::Link/10",
@ -104,24 +115,29 @@ Object {
],
"sources": Array [
Object {
"__typename": "ReleaseSource",
"format": "zip",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.zip",
},
Object {
"__typename": "ReleaseSource",
"format": "tar.gz",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar.gz",
},
Object {
"__typename": "ReleaseSource",
"format": "tar.bz2",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar.bz2",
},
Object {
"__typename": "ReleaseSource",
"format": "tar",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar",
},
],
},
"author": Object {
"__typename": "UserCore",
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
"username": "administrator",
"webUrl": "http://localhost/administrator",
@ -134,6 +150,7 @@ Object {
"descriptionHtml": "<p data-sourcepos=\\"1:1-1:33\\" dir=\\"auto\\">Best. Release. <strong>Ever.</strong> <gl-emoji title=\\"rocket\\" data-name=\\"rocket\\" data-unicode-version=\\"6.0\\">🚀</gl-emoji></p>",
"evidences": Array [
Object {
"__typename": "ReleaseEvidence",
"collectedAt": "2018-12-03T00:00:00Z",
"filepath": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/evidences/1.json",
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
@ -141,6 +158,7 @@ Object {
],
"milestones": Array [
Object {
"__typename": "Milestone",
"description": "The 12.3 milestone",
"id": "gid://gitlab/Milestone/123",
"issueStats": Object {
@ -153,6 +171,7 @@ Object {
"webUrl": "/releases-namespace/releases-project/-/milestones/1",
},
Object {
"__typename": "Milestone",
"description": "The 12.4 milestone",
"id": "gid://gitlab/Milestone/124",
"issueStats": Object {
@ -173,6 +192,7 @@ Object {
},
],
"paginationInfo": Object {
"__typename": "PageInfo",
"endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9",
"hasNextPage": false,
"hasPreviousPage": false,
@ -247,6 +267,7 @@ exports[`releases/util.js convertOneReleaseGraphQLResponse matches snapshot 1`]
Object {
"data": Object {
"_links": Object {
"__typename": "ReleaseLinks",
"closedIssuesUrl": "http://localhost/releases-namespace/releases-project/-/issues?release_tag=v1.1&scope=all&state=closed",
"closedMergeRequestsUrl": "http://localhost/releases-namespace/releases-project/-/merge_requests?release_tag=v1.1&scope=all&state=closed",
"editUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/edit",
@ -260,6 +281,7 @@ Object {
"count": 8,
"links": Array [
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-3",
"external": true,
"id": "gid://gitlab/Releases::Link/13",
@ -268,6 +290,7 @@ Object {
"url": "https://example.com/image",
},
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-2",
"external": true,
"id": "gid://gitlab/Releases::Link/12",
@ -276,6 +299,7 @@ Object {
"url": "https://example.com/package",
},
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-1",
"external": false,
"id": "gid://gitlab/Releases::Link/11",
@ -284,6 +308,7 @@ Object {
"url": "http://localhost/releases-namespace/releases-project/runbook",
},
Object {
"__typename": "ReleaseAssetLink",
"directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/linux-amd64",
"external": true,
"id": "gid://gitlab/Releases::Link/10",
@ -294,24 +319,29 @@ Object {
],
"sources": Array [
Object {
"__typename": "ReleaseSource",
"format": "zip",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.zip",
},
Object {
"__typename": "ReleaseSource",
"format": "tar.gz",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar.gz",
},
Object {
"__typename": "ReleaseSource",
"format": "tar.bz2",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar.bz2",
},
Object {
"__typename": "ReleaseSource",
"format": "tar",
"url": "http://localhost/releases-namespace/releases-project/-/archive/v1.1/releases-project-v1.1.tar",
},
],
},
"author": Object {
"__typename": "UserCore",
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
"username": "administrator",
"webUrl": "http://localhost/administrator",
@ -324,6 +354,7 @@ Object {
"descriptionHtml": "<p data-sourcepos=\\"1:1-1:33\\" dir=\\"auto\\">Best. Release. <strong>Ever.</strong> <gl-emoji title=\\"rocket\\" data-name=\\"rocket\\" data-unicode-version=\\"6.0\\">🚀</gl-emoji></p>",
"evidences": Array [
Object {
"__typename": "ReleaseEvidence",
"collectedAt": "2018-12-03T00:00:00Z",
"filepath": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/evidences/1.json",
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
@ -331,6 +362,7 @@ Object {
],
"milestones": Array [
Object {
"__typename": "Milestone",
"description": "The 12.3 milestone",
"id": "gid://gitlab/Milestone/123",
"issueStats": Object {
@ -343,6 +375,7 @@ Object {
"webUrl": "/releases-namespace/releases-project/-/milestones/1",
},
Object {
"__typename": "Milestone",
"description": "The 12.4 milestone",
"id": "gid://gitlab/Milestone/124",
"issueStats": Object {

View File

@ -3,6 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import allReleasesQuery from 'shared_queries/releases/all_releases.query.graphql';
import createFlash from '~/flash';
import { historyPushState } from '~/lib/utils/common_utils';
import ReleasesIndexApolloClientApp from '~/releases/components/app_index_apollo_client.vue';
@ -12,7 +13,6 @@ import ReleasesEmptyState from '~/releases/components/releases_empty_state.vue';
import ReleasesPaginationApolloClient from '~/releases/components/releases_pagination_apollo_client.vue';
import ReleasesSortApolloClient from '~/releases/components/releases_sort_apollo_client.vue';
import { PAGE_SIZE, CREATED_ASC, DEFAULT_SORT } from '~/releases/constants';
import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql';
Vue.use(VueApollo);

View File

@ -23,6 +23,7 @@ import {
} from '~/vue_shared/security_reports/constants';
const upgradePath = '/upgrade';
const gitlabCiHistoryPath = 'test/historyPath';
describe('redesigned App component', () => {
let wrapper;
@ -52,8 +53,28 @@ describe('redesigned App component', () => {
const findTabs = () => wrapper.findAllComponents(GlTab);
const findByTestId = (id) => wrapper.findByTestId(id);
const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
const findComplianceViewHistoryLink = () => findByTestId('compliance-view-history-link');
const findSecurityViewHistoryLink = () => findByTestId('security-view-history-link');
const findLink = ({ href, text, container = wrapper }) => {
const selector = `a[href="${href}"]`;
const link = container.find(selector);
if (link.exists() && link.text() === text) {
return link;
}
return wrapper.find(`${selector} does not exist`);
};
const findSecurityViewHistoryLink = () =>
findLink({
href: gitlabCiHistoryPath,
text: i18n.configurationHistory,
container: findByTestId('security-testing-tab'),
});
const findComplianceViewHistoryLink = () =>
findLink({
href: gitlabCiHistoryPath,
text: i18n.configurationHistory,
container: findByTestId('compliance-testing-tab'),
});
const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner);
const securityFeaturesMock = [
@ -119,6 +140,10 @@ describe('redesigned App component', () => {
expect(cards.at(1).props()).toEqual({ feature: complianceFeaturesMock[0] });
});
it('renders a basic description', () => {
expect(wrapper.text()).toContain(i18n.description);
});
it('should not show latest pipeline link when latestPipelinePath is not defined', () => {
expect(findByTestId('latest-pipeline-info').exists()).toBe(false);
});
@ -193,9 +218,8 @@ describe('redesigned App component', () => {
it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
const latestPipelineInfoSecurity = findByTestId('latest-pipeline-info-security');
expect(latestPipelineInfoSecurity.exists()).toBe(true);
expect(latestPipelineInfoSecurity.text()).toMatchInterpolatedText(
i18n.securityTestingDescription,
i18n.latestPipelineDescription,
);
expect(latestPipelineInfoSecurity.find('a').attributes('href')).toBe('test/path');
});
@ -203,9 +227,8 @@ describe('redesigned App component', () => {
it('should show latest pipeline info on the compliance tab with correct link when latestPipelinePath is defined', () => {
const latestPipelineInfoCompliance = findByTestId('latest-pipeline-info-compliance');
expect(latestPipelineInfoCompliance.exists()).toBe(true);
expect(latestPipelineInfoCompliance.text()).toMatchInterpolatedText(
i18n.securityTestingDescription,
i18n.latestPipelineDescription,
);
expect(latestPipelineInfoCompliance.find('a').attributes('href')).toBe('test/path');
});
@ -217,7 +240,7 @@ describe('redesigned App component', () => {
augmentedSecurityFeatures: securityFeaturesMock,
augmentedComplianceFeatures: complianceFeaturesMock,
gitlabCiPresent: true,
gitlabCiHistoryPath: 'test/historyPath',
gitlabCiHistoryPath,
});
});

View File

@ -97,4 +97,42 @@ RSpec.describe ReleasesHelper do
end
end
end
describe 'startup queries' do
describe 'use_startup_query_for_index_page?' do
it 'allows startup queries for non-paginated requests' do
allow(helper).to receive(:params).and_return({ unrelated_query_param: 'value' })
expect(helper.use_startup_query_for_index_page?).to be(true)
end
it 'disallows startup queries for requests paginated with a "before" cursor' do
allow(helper).to receive(:params).and_return({ unrelated_query_param: 'value', before: 'cursor' })
expect(helper.use_startup_query_for_index_page?).to be(false)
end
it 'disallows startup queries for requests paginated with an "after" cursor' do
allow(helper).to receive(:params).and_return({ unrelated_query_param: 'value', after: 'cursor' })
expect(helper.use_startup_query_for_index_page?).to be(false)
end
end
describe '#index_page_startup_query_variables' do
let_it_be(:project) { build(:project, namespace: create(:group)) }
before do
helper.instance_variable_set(:@project, project)
end
it 'returns the correct GraphQL variables for the startup query' do
expect(helper.index_page_startup_query_variables).to eq({
fullPath: project.full_path,
sort: 'RELEASED_AT_DESC',
first: 1
})
end
end
end
end

View File

@ -143,51 +143,22 @@ RSpec.describe Gitlab::Ci::Config::Entry::Artifacts do
end
describe 'excluded artifacts' do
context 'when configuration is valid and the feature is enabled' do
before do
stub_feature_flags(ci_artifacts_exclude: true)
end
context 'when configuration is valid' do
let(:config) { { untracked: true, exclude: ['some/directory/'] } }
context 'when configuration is valid' do
let(:config) { { untracked: true, exclude: ['some/directory/'] } }
it 'correctly parses the configuration' do
expect(entry).to be_valid
expect(entry.value).to eq config
end
end
context 'when configuration is not valid' do
let(:config) { { untracked: true, exclude: 1234 } }
it 'returns an error' do
expect(entry).not_to be_valid
expect(entry.errors)
.to include 'artifacts exclude should be an array of strings'
end
it 'correctly parses the configuration' do
expect(entry).to be_valid
expect(entry.value).to eq config
end
end
context 'when artifacts/exclude feature is disabled' do
before do
stub_feature_flags(ci_artifacts_exclude: false)
end
context 'when configuration is not valid' do
let(:config) { { untracked: true, exclude: 1234 } }
context 'when configuration has been provided' do
let(:config) { { untracked: true, exclude: ['some/directory/'] } }
it 'returns an error' do
expect(entry).not_to be_valid
expect(entry.errors).to include 'artifacts exclude feature is disabled'
end
end
context 'when configuration is not present' do
let(:config) { { untracked: true } }
it 'is a valid configuration' do
expect(entry).to be_valid
end
it 'returns an error' do
expect(entry).not_to be_valid
expect(entry.errors)
.to include 'artifacts exclude should be an array of strings'
end
end
end

View File

@ -1648,8 +1648,6 @@ module Gitlab
end
it 'populates a build options with complete artifacts configuration' do
stub_feature_flags(ci_artifacts_exclude: true)
config = <<~YAML
test:
script: echo "Hello World"

View File

@ -4493,26 +4493,12 @@ RSpec.describe Ci::Build do
it { is_expected.to include(:upload_multiple_artifacts) }
end
context 'when artifacts exclude is defined and the is feature enabled' do
context 'when artifacts exclude is defined' do
let(:options) do
{ artifacts: { exclude: %w[something] } }
end
context 'when a feature flag is enabled' do
before do
stub_feature_flags(ci_artifacts_exclude: true)
end
it { is_expected.to include(:artifacts_exclude) }
end
context 'when a feature flag is disabled' do
before do
stub_feature_flags(ci_artifacts_exclude: false)
end
it { is_expected.not_to include(:artifacts_exclude) }
end
it { is_expected.to include(:artifacts_exclude) }
end
end

View File

@ -44,29 +44,13 @@ RSpec.describe Ci::BuildRunnerPresenter do
create(:ci_build, options: { artifacts: { paths: %w[abc], exclude: %w[cde] } })
end
context 'when the feature is enabled' do
before do
stub_feature_flags(ci_artifacts_exclude: true)
end
it 'includes the list of excluded paths' do
expect(presenter.artifacts.first).to include(
artifact_type: :archive,
artifact_format: :zip,
paths: %w[abc],
exclude: %w[cde]
)
end
end
context 'when the feature is disabled' do
before do
stub_feature_flags(ci_artifacts_exclude: false)
end
it 'does not include the list of excluded paths' do
expect(presenter.artifacts.first).not_to have_key(:exclude)
end
it 'includes the list of excluded paths' do
expect(presenter.artifacts.first).to include(
artifact_type: :archive,
artifact_format: :zip,
paths: %w[abc],
exclude: %w[cde]
)
end
end

View File

@ -803,29 +803,16 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when a runner supports this feature' do
it 'exposes excluded paths when the feature is enabled' do
stub_feature_flags(ci_artifacts_exclude: true)
it 'exposes excluded paths' do
request_job info: { features: { artifacts_exclude: true } }
expect(response).to have_gitlab_http_status(:created)
expect(json_response.dig('artifacts').first).to include('exclude' => ['cde'])
end
it 'does not expose excluded paths when the feature is disabled' do
stub_feature_flags(ci_artifacts_exclude: false)
request_job info: { features: { artifacts_exclude: true } }
expect(response).to have_gitlab_http_status(:created)
expect(json_response.dig('artifacts').first).not_to have_key('exclude')
end
end
context 'when a runner does not support this feature' do
it 'does not expose the build at all' do
stub_feature_flags(ci_artifacts_exclude: true)
request_job
expect(response).to have_gitlab_http_status(:no_content)

View File

@ -5,12 +5,16 @@ require 'spec_helper'
RSpec.describe MergeRequests::PushOptionsHandlerService do
include ProjectForksHelper
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:parent_group) { create(:group, :public) }
let_it_be(:child_group) { create(:group, :public, parent: parent_group) }
let_it_be(:project) { create(:project, :public, :repository, group: child_group) }
let_it_be(:user1) { create(:user, developer_projects: [project]) }
let_it_be(:user2) { create(:user, developer_projects: [project]) }
let_it_be(:user3) { create(:user, developer_projects: [project]) }
let_it_be(:forked_project) { fork_project(project, user1, repository: true) }
let_it_be(:milestone) { create(:milestone, project: project, title: '1.0') }
let_it_be(:parent_group_milestone) { create(:milestone, group: parent_group, title: 'ParentGroupMilestone1.0') }
let_it_be(:child_group_milestone) { create(:milestone, group: child_group, title: 'ChildGroupMilestone1.0') }
let_it_be(:project_milestone) { create(:milestone, project: project, title: 'ProjectMilestone1.0') }
let(:service) { described_class.new(project: project, current_user: user1, changes: changes, push_options: push_options) }
let(:source_branch) { 'fix' }
@ -527,8 +531,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
describe '`milestone` push option' do
context 'with a valid milestone' do
let(:expected_milestone) { milestone.title }
let(:push_options) { { milestone: milestone.title } }
let(:expected_milestone) { project_milestone.title }
let(:push_options) { { milestone: project_milestone.title } }
context 'with a new branch' do
let(:changes) { new_branch_changes }
@ -542,7 +546,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
end
context 'when coupled with the `create` push option' do
let(:push_options) { { create: true, milestone: milestone.title } }
let(:push_options) { { create: true, milestone: project_milestone.title } }
it_behaves_like 'a service that can create a merge request'
it_behaves_like 'a service that can set the milestone of a merge request'
@ -561,7 +565,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
end
context 'when coupled with the `create` push option' do
let(:push_options) { { create: true, milestone: milestone.title } }
let(:push_options) { { create: true, milestone: project_milestone.title } }
it_behaves_like 'a service that can create a merge request'
it_behaves_like 'a service that can set the milestone of a merge request'
@ -587,6 +591,26 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can set the milestone of a merge request'
end
context 'with an ancestor milestone' do
let(:changes) { existing_branch_changes }
context 'with immediate parent milestone' do
let(:push_options) { { create: true, milestone: child_group_milestone.title } }
let(:expected_milestone) { child_group_milestone.title }
it_behaves_like 'a service that can create a merge request'
it_behaves_like 'a service that can set the milestone of a merge request'
end
context 'with multi-level ancestor milestone' do
let(:push_options) { { create: true, milestone: parent_group_milestone.title } }
let(:expected_milestone) { parent_group_milestone.title }
it_behaves_like 'a service that can create a merge request'
it_behaves_like 'a service that can set the milestone of a merge request'
end
end
end
shared_examples 'with an existing branch that has a merge request open in foss' do

View File

@ -38,6 +38,12 @@ RSpec.describe WaitableWorker do
it 'inlines workloads <= 3 jobs' do
args_list = [[1], [2], [3]]
expect(worker).to receive(:bulk_perform_inline).with(args_list).and_call_original
expect(Gitlab::AppJsonLogger).to(
receive(:info).with(a_hash_including('message' => 'running inline',
'class' => 'Gitlab::Foo::Bar::DummyWorker',
'job_status' => 'running',
'queue' => 'foo_bar_dummy'))
.exactly(3).times)
worker.bulk_perform_and_wait(args_list)