Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6b922f9bb0
commit
1b16af5ff9
34 changed files with 573 additions and 71 deletions
|
@ -1 +1 @@
|
|||
1.18.0
|
||||
1.19.0
|
||||
|
|
|
@ -105,6 +105,7 @@ export const handleLocationHash = () => {
|
|||
const topPadding = 8;
|
||||
const diffFileHeader = document.querySelector('.js-file-title');
|
||||
const versionMenusContainer = document.querySelector('.mr-version-menus-container');
|
||||
const fixedIssuableTitle = document.querySelector('.issue-sticky-header');
|
||||
|
||||
let adjustment = 0;
|
||||
if (fixedNav) adjustment -= fixedNav.offsetHeight;
|
||||
|
@ -133,6 +134,10 @@ export const handleLocationHash = () => {
|
|||
adjustment -= versionMenusContainer.offsetHeight;
|
||||
}
|
||||
|
||||
if (isInIssuePage()) {
|
||||
adjustment -= fixedIssuableTitle.offsetHeight;
|
||||
}
|
||||
|
||||
if (isInMRPage()) {
|
||||
adjustment -= topPadding;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ module Mutations
|
|||
description: 'File name of the snippet'
|
||||
|
||||
argument :content, GraphQL::STRING_TYPE,
|
||||
required: true,
|
||||
required: false,
|
||||
description: 'Content of the snippet'
|
||||
|
||||
argument :description, GraphQL::STRING_TYPE,
|
||||
|
@ -40,6 +40,10 @@ module Mutations
|
|||
required: false,
|
||||
description: 'The paths to files uploaded in the snippet description'
|
||||
|
||||
argument :files, [Types::Snippets::FileInputType],
|
||||
description: "The snippet files to create",
|
||||
required: false
|
||||
|
||||
def resolve(args)
|
||||
project_path = args.delete(:project_path)
|
||||
|
||||
|
@ -49,13 +53,9 @@ module Mutations
|
|||
raise_resource_not_available_error!
|
||||
end
|
||||
|
||||
# We need to rename `uploaded_files` into `files` because
|
||||
# it's the expected key param
|
||||
args[:files] = args.delete(:uploaded_files)
|
||||
|
||||
service_response = ::Snippets::CreateService.new(project,
|
||||
context[:current_user],
|
||||
args).execute
|
||||
context[:current_user],
|
||||
create_params(args)).execute
|
||||
|
||||
snippet = service_response.payload[:snippet]
|
||||
|
||||
|
@ -82,6 +82,18 @@ module Mutations
|
|||
def can_create_personal_snippet?
|
||||
Ability.allowed?(context[:current_user], :create_snippet)
|
||||
end
|
||||
|
||||
def create_params(args)
|
||||
args.tap do |create_args|
|
||||
# We need to rename `files` into `snippet_files` because
|
||||
# it's the expected key param
|
||||
create_args[:snippet_files] = create_args.delete(:files)&.map(&:to_h)
|
||||
|
||||
# We need to rename `uploaded_files` into `files` because
|
||||
# it's the expected key param
|
||||
create_args[:files] = create_args.delete(:uploaded_files)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -675,10 +675,11 @@ class Project < ApplicationRecord
|
|||
# '>' or its escaped form ('>') are checked for because '>' is sometimes escaped
|
||||
# when the reference comes from an external source.
|
||||
def markdown_reference_pattern
|
||||
%r{
|
||||
#{reference_pattern}
|
||||
(#{reference_postfix}|#{reference_postfix_escaped})
|
||||
}x
|
||||
@markdown_reference_pattern ||=
|
||||
%r{
|
||||
#{reference_pattern}
|
||||
(#{reference_postfix}|#{reference_postfix_escaped})
|
||||
}x
|
||||
end
|
||||
|
||||
def trending
|
||||
|
|
|
@ -619,11 +619,12 @@ class User < ApplicationRecord
|
|||
|
||||
# Pattern used to extract `@user` user references from text
|
||||
def reference_pattern
|
||||
%r{
|
||||
(?<!\w)
|
||||
#{Regexp.escape(reference_prefix)}
|
||||
(?<user>#{Gitlab::PathRegex::FULL_NAMESPACE_FORMAT_REGEX})
|
||||
}x
|
||||
@reference_pattern ||=
|
||||
%r{
|
||||
(?<!\w)
|
||||
#{Regexp.escape(reference_prefix)}
|
||||
(?<user>#{Gitlab::PathRegex::FULL_NAMESPACE_FORMAT_REGEX})
|
||||
}x
|
||||
end
|
||||
|
||||
# Return (create if necessary) the ghost user. The ghost user
|
||||
|
|
|
@ -95,7 +95,9 @@ class MergeRequestWidgetEntity < Grape::Entity
|
|||
end
|
||||
|
||||
def can_add_ci_config_path?(merge_request)
|
||||
merge_request.source_project&.uses_default_ci_config? &&
|
||||
merge_request.open? &&
|
||||
merge_request.source_branch_exists? &&
|
||||
merge_request.source_project&.uses_default_ci_config? &&
|
||||
!merge_request.source_project.has_ci? &&
|
||||
merge_request.commits_count.positive? &&
|
||||
can?(current_user, :read_build, merge_request.source_project) &&
|
||||
|
|
|
@ -12,7 +12,9 @@ module Snippets
|
|||
super
|
||||
|
||||
@uploaded_assets = Array(@params.delete(:files).presence)
|
||||
@snippet_files = SnippetInputActionCollection.new(Array(@params.delete(:snippet_files).presence))
|
||||
|
||||
input_actions = Array(@params.delete(:snippet_files).presence)
|
||||
@snippet_files = SnippetInputActionCollection.new(input_actions, allowed_actions: restricted_files_actions)
|
||||
|
||||
filter_spam_check_params
|
||||
end
|
||||
|
@ -79,5 +81,9 @@ module Snippets
|
|||
def build_actions_from_params(snippet)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def restricted_files_actions
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -100,5 +100,9 @@ module Snippets
|
|||
def build_actions_from_params(_snippet)
|
||||
[{ file_path: params[:file_name], content: params[:content] }]
|
||||
end
|
||||
|
||||
def restricted_files_actions
|
||||
:create
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
.form-group
|
||||
.form-text
|
||||
%p.text-secondary
|
||||
= _('Select a weight for the storage new repositories will be placed on.')
|
||||
= _('Enter weights for storages for new repositories.')
|
||||
= link_to icon('question-circle'), help_page_path('administration/repository_storage_paths')
|
||||
.form-check
|
||||
- storage_weights.each do |attribute|
|
||||
|
|
5
changelogs/unreleased/213816.yml
Normal file
5
changelogs/unreleased/213816.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Drop deprecated **_ANALYZER_IMAGE_PREFIX
|
||||
merge_request: 34325
|
||||
author:
|
||||
type: removed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add :section to approval_merge_request_rule unique index
|
||||
merge_request: 34680
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix Issue sticky title URL hash offset
|
||||
merge_request: 34764
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/add-node-ci-template.yml
Normal file
5
changelogs/unreleased/add-node-ci-template.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add node ci template
|
||||
merge_request: 25668
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add files argument to snippet create mutation
|
||||
merge_request: 34449
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Adjust verbiage on repository storages settings page
|
||||
merge_request: 34675
|
||||
author:
|
||||
type: changed
|
5
changelogs/unreleased/upgrade-pages-to-1-19.yml
Normal file
5
changelogs/unreleased/upgrade-pages-to-1-19.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Upgrade GitLab Pages to 1.19.0
|
||||
merge_request: 34730
|
||||
author:
|
||||
type: added
|
|
@ -10,7 +10,9 @@ def get_vue_files_with_ce_and_ee_versions(files)
|
|||
"ee/#{file}"
|
||||
end
|
||||
|
||||
response = gitlab.api.get_file(gitlab.mr_json['project_id'], counterpart_path, 'master')
|
||||
escaped_path = CGI.escape(counterpart_path)
|
||||
api_endpoint = "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ee/repository/files/#{escaped_path}?ref=master"
|
||||
response = HTTParty.get(api_endpoint) # rubocop:disable Gitlab/HTTParty
|
||||
response.code != 404
|
||||
else
|
||||
false
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UpdateIndexApprovalRuleNameForCodeOwnersRuleType < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
LEGACY_INDEX_NAME_RULE_TYPE = "index_approval_rule_name_for_code_owners_rule_type"
|
||||
LEGACY_INDEX_NAME_CODE_OWNERS = "approval_rule_name_index_for_code_owners"
|
||||
|
||||
SECTIONAL_INDEX_NAME = "index_approval_rule_name_for_sectional_code_owners_rule_type"
|
||||
|
||||
CODE_OWNER_RULE_TYPE = 2
|
||||
|
||||
def up
|
||||
unless index_exists_by_name?(:approval_merge_request_rules, SECTIONAL_INDEX_NAME)
|
||||
# Ensure only 1 code_owner rule with the same name and section per merge_request
|
||||
#
|
||||
add_concurrent_index(
|
||||
:approval_merge_request_rules,
|
||||
[:merge_request_id, :name, :section],
|
||||
unique: true,
|
||||
where: "rule_type = #{CODE_OWNER_RULE_TYPE}",
|
||||
name: SECTIONAL_INDEX_NAME
|
||||
)
|
||||
end
|
||||
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_RULE_TYPE
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
|
||||
add_concurrent_index(
|
||||
:approval_merge_request_rules,
|
||||
[:merge_request_id, :name],
|
||||
unique: true,
|
||||
where: "rule_type = #{CODE_OWNER_RULE_TYPE} AND section IS NULL",
|
||||
name: LEGACY_INDEX_NAME_RULE_TYPE
|
||||
)
|
||||
|
||||
add_concurrent_index(
|
||||
:approval_merge_request_rules,
|
||||
[:merge_request_id, :code_owner, :name],
|
||||
unique: true,
|
||||
where: "code_owner = true AND section IS NULL",
|
||||
name: LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# In a rollback situation, we can't guarantee that there will not be
|
||||
# records that were allowed under the more specific SECTIONAL_INDEX_NAME
|
||||
# index but would cause uniqueness violations under both the
|
||||
# LEGACY_INDEX_NAME_RULE_TYPE and LEGACY_INDEX_NAME_CODE_OWNERS indices.
|
||||
# Therefore, we need to first find all the MergeRequests with
|
||||
# ApprovalMergeRequestRules that would violate these "new" indices and
|
||||
# delete those approval rules, then create the new index, then finally
|
||||
# recreate the approval rules for those merge requests.
|
||||
#
|
||||
|
||||
# First, find all MergeRequests with ApprovalMergeRequestRules that will
|
||||
# violate the new index.
|
||||
#
|
||||
if Gitlab.ee?
|
||||
merge_request_ids = ApprovalMergeRequestRule
|
||||
.select(:merge_request_id)
|
||||
.where(rule_type: CODE_OWNER_RULE_TYPE)
|
||||
.group(:merge_request_id, :rule_type, :name)
|
||||
.includes(:merge_request)
|
||||
.having("count(*) > 1")
|
||||
.collect(&:merge_request_id)
|
||||
|
||||
# Delete ALL their code_owner approval rules
|
||||
#
|
||||
merge_request_ids.each_slice(10) do |ids|
|
||||
ApprovalMergeRequestRule.where(merge_request_id: ids).code_owner.delete_all
|
||||
end
|
||||
end
|
||||
|
||||
# Remove legacy partial indices that only apply to `section IS NULL` records
|
||||
#
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_RULE_TYPE
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
|
||||
# Reconstruct original "legacy" indices
|
||||
#
|
||||
add_concurrent_index(
|
||||
:approval_merge_request_rules,
|
||||
[:merge_request_id, :name],
|
||||
unique: true,
|
||||
where: "rule_type = #{CODE_OWNER_RULE_TYPE}",
|
||||
name: LEGACY_INDEX_NAME_RULE_TYPE
|
||||
)
|
||||
|
||||
add_concurrent_index(
|
||||
:approval_merge_request_rules,
|
||||
[:merge_request_id, :code_owner, :name],
|
||||
unique: true,
|
||||
where: "code_owner = true",
|
||||
name: LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
)
|
||||
|
||||
# MergeRequest::SyncCodeOwnerApprovalRules recreates the code_owner rules
|
||||
# from scratch, adding them to the index. Duplicates will be rejected.
|
||||
#
|
||||
if Gitlab.ee?
|
||||
merge_request_ids.each_slice(10) do |ids|
|
||||
MergeRequest.where(id: ids).each do |merge_request|
|
||||
MergeRequests::SyncCodeOwnerApprovalRules.new(merge_request).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, SECTIONAL_INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -9163,7 +9163,7 @@ CREATE UNIQUE INDEX any_approver_merge_request_rule_type_unique_index ON public.
|
|||
|
||||
CREATE UNIQUE INDEX any_approver_project_rule_type_unique_index ON public.approval_project_rules USING btree (project_id) WHERE (rule_type = 3);
|
||||
|
||||
CREATE UNIQUE INDEX approval_rule_name_index_for_code_owners ON public.approval_merge_request_rules USING btree (merge_request_id, code_owner, name) WHERE (code_owner = true);
|
||||
CREATE UNIQUE INDEX approval_rule_name_index_for_code_owners ON public.approval_merge_request_rules USING btree (merge_request_id, code_owner, name) WHERE ((code_owner = true) AND (section IS NULL));
|
||||
|
||||
CREATE INDEX ci_builds_gitlab_monitor_metrics ON public.ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
|
||||
|
||||
|
@ -9341,7 +9341,9 @@ CREATE UNIQUE INDEX index_approval_project_rules_users_1 ON public.approval_proj
|
|||
|
||||
CREATE INDEX index_approval_project_rules_users_2 ON public.approval_project_rules_users USING btree (user_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id, name) WHERE (rule_type = 2);
|
||||
CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id, name) WHERE ((rule_type = 2) AND (section IS NULL));
|
||||
|
||||
CREATE UNIQUE INDEX index_approval_rule_name_for_sectional_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id, name, section) WHERE (rule_type = 2);
|
||||
|
||||
CREATE INDEX index_approval_rules_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id) WHERE (rule_type = 2);
|
||||
|
||||
|
@ -13956,6 +13958,7 @@ COPY "schema_migrations" (version) FROM STDIN;
|
|||
20200526153844
|
||||
20200526164946
|
||||
20200526164947
|
||||
20200526231421
|
||||
20200527092027
|
||||
20200527094322
|
||||
20200527095401
|
||||
|
|
|
@ -1824,7 +1824,7 @@ input CreateSnippetInput {
|
|||
"""
|
||||
Content of the snippet
|
||||
"""
|
||||
content: String!
|
||||
content: String
|
||||
|
||||
"""
|
||||
Description of the snippet
|
||||
|
@ -1836,6 +1836,11 @@ input CreateSnippetInput {
|
|||
"""
|
||||
fileName: String
|
||||
|
||||
"""
|
||||
The snippet files to create
|
||||
"""
|
||||
files: [SnippetFileInputType!]
|
||||
|
||||
"""
|
||||
The project full path the snippet is associated with
|
||||
"""
|
||||
|
|
|
@ -4825,13 +4825,9 @@
|
|||
"name": "content",
|
||||
"description": "Content of the snippet",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
|
@ -4887,6 +4883,24 @@
|
|||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"description": "The snippet files to create",
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "SnippetFileInputType",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "clientMutationId",
|
||||
"description": "A unique identifier for the client performing the mutation.",
|
||||
|
|
|
@ -750,6 +750,15 @@ _Internal_ refers to documentation in the same project. When linking to document
|
|||
separate projects (for example, linking to Omnibus docs from GitLab docs), you must use absolute
|
||||
URLs.
|
||||
|
||||
Do not use absolute URLs like `https://docs.gitlab.com/ee/index.html` to crosslink
|
||||
to other docs within the same project. Use relative links to the file, like `../index.md`. (These are converted to HTML when the site is rendered.)
|
||||
|
||||
Relative linking enables crosslinks to work:
|
||||
|
||||
- in Review Apps, local previews, and `/help`.
|
||||
- when working on the docs locally, so you can verify that they work as early as possible in the process.
|
||||
- within the GitLab UI when browsing doc files in their respective repositories. For example, the links displayed at <https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md>.
|
||||
|
||||
To link to internal documentation:
|
||||
|
||||
- Use relative links to Markdown files in the same repository.
|
||||
|
|
|
@ -151,7 +151,6 @@ The following variables allow configuration of global dependency scanning settin
|
|||
| Environment variable | Description |
|
||||
| --------------------------------------- |------------ |
|
||||
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
|
||||
| `DS_ANALYZER_IMAGE_PREFIX` | **DEPRECATED:** Use `SECURE_ANALYZERS_PREFIX` instead. |
|
||||
| `DS_DEFAULT_ANALYZERS` | Override the names of the official default images. Read more about [customizing analyzers](analyzers.md). |
|
||||
| `DS_DISABLE_DIND` | Disable Docker-in-Docker and run analyzers [individually](#enabling-docker-in-docker). This variable is `true` by default. |
|
||||
| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. |
|
||||
|
@ -428,14 +427,14 @@ For details on saving and transporting Docker images as a file, see Docker's doc
|
|||
### Set Dependency Scanning CI job variables to use local Dependency Scanning analyzers
|
||||
|
||||
Add the following configuration to your `.gitlab-ci.yml` file. You must replace
|
||||
`DS_ANALYZER_IMAGE_PREFIX` to refer to your local Docker container registry:
|
||||
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- template: Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
DS_ANALYZER_IMAGE_PREFIX: "docker-registry.example.com/analyzers"
|
||||
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
|
||||
GEMNASIUM_DB_REMOTE_URL: "gitlab.example.com/gemnasium-db.git"
|
||||
GIT_SSL_NO_VERIFY: "true"
|
||||
```
|
||||
|
|
|
@ -278,7 +278,6 @@ The following are Docker image-related variables.
|
|||
| Environment variable | Description |
|
||||
|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the default images (proxy). Read more about [customizing analyzers](analyzers.md). |
|
||||
| `SAST_ANALYZER_IMAGE_PREFIX` | **DEPRECATED**: Use `SECURE_ANALYZERS_PREFIX` instead. |
|
||||
| `SAST_ANALYZER_IMAGE_TAG` | **DEPRECATED:** Override the Docker tag of the default images. Read more about [customizing analyzers](analyzers.md). |
|
||||
| `SAST_DEFAULT_ANALYZERS` | Override the names of default images. Read more about [customizing analyzers](analyzers.md). |
|
||||
| `SAST_DISABLE_DIND` | Disable Docker-in-Docker and run analyzers [individually](#enabling-docker-in-docker). This variable is `true` by default. |
|
||||
|
@ -509,7 +508,7 @@ For details on saving and transporting Docker images as a file, see Docker's doc
|
|||
### Set SAST CI job variables to use local SAST analyzers
|
||||
|
||||
Add the following configuration to your `.gitlab-ci.yml` file. You must replace
|
||||
`SAST_ANALYZER_IMAGE_PREFIX` to refer to your local Docker container registry:
|
||||
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
|
||||
|
||||
```yaml
|
||||
include:
|
||||
|
|
|
@ -9,9 +9,6 @@ variables:
|
|||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
|
||||
|
||||
# Deprecated, use SECURE_ANALYZERS_PREFIX instead
|
||||
DS_ANALYZER_IMAGE_PREFIX: "$SECURE_ANALYZERS_PREFIX"
|
||||
|
||||
DS_DEFAULT_ANALYZERS: "bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python"
|
||||
DS_EXCLUDED_PATHS: "spec, test, tests, tmp"
|
||||
DS_MAJOR_VERSION: 2
|
||||
|
@ -45,7 +42,7 @@ dependency_scanning:
|
|||
docker run \
|
||||
$(propagate_env_vars \
|
||||
DS_ANALYZER_IMAGES \
|
||||
DS_ANALYZER_IMAGE_PREFIX \
|
||||
SECURE_ANALYZERS_PREFIX \
|
||||
DS_ANALYZER_IMAGE_TAG \
|
||||
DS_DEFAULT_ANALYZERS \
|
||||
DS_EXCLUDED_PATHS \
|
||||
|
@ -98,7 +95,7 @@ dependency_scanning:
|
|||
gemnasium-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
image:
|
||||
name: "$DS_ANALYZER_IMAGE_PREFIX/gemnasium:$DS_MAJOR_VERSION"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/gemnasium:$DS_MAJOR_VERSION"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -117,7 +114,7 @@ gemnasium-dependency_scanning:
|
|||
gemnasium-maven-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
image:
|
||||
name: "$DS_ANALYZER_IMAGE_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -133,7 +130,7 @@ gemnasium-maven-dependency_scanning:
|
|||
gemnasium-python-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
image:
|
||||
name: "$DS_ANALYZER_IMAGE_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -156,7 +153,7 @@ gemnasium-python-dependency_scanning:
|
|||
bundler-audit-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
image:
|
||||
name: "$DS_ANALYZER_IMAGE_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -169,7 +166,7 @@ bundler-audit-dependency_scanning:
|
|||
retire-js-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
image:
|
||||
name: "$DS_ANALYZER_IMAGE_PREFIX/retire.js:$DS_MAJOR_VERSION"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/retire.js:$DS_MAJOR_VERSION"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
|
|
@ -9,9 +9,6 @@ variables:
|
|||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
|
||||
|
||||
# Deprecated, use SECURE_ANALYZERS_PREFIX instead
|
||||
SAST_ANALYZER_IMAGE_PREFIX: "$SECURE_ANALYZERS_PREFIX"
|
||||
|
||||
SAST_DEFAULT_ANALYZERS: "bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, tslint, secrets, sobelow, pmd-apex, kubesec"
|
||||
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
|
||||
SAST_ANALYZER_IMAGE_TAG: 2
|
||||
|
@ -63,7 +60,7 @@ sast:
|
|||
bandit-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -76,7 +73,7 @@ bandit-sast:
|
|||
brakeman-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -88,7 +85,7 @@ brakeman-sast:
|
|||
eslint-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -102,7 +99,7 @@ eslint-sast:
|
|||
flawfinder-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -116,7 +113,7 @@ flawfinder-sast:
|
|||
kubesec-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -128,7 +125,7 @@ kubesec-sast:
|
|||
gosec-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -141,7 +138,7 @@ gosec-sast:
|
|||
nodejs-scan-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -154,7 +151,7 @@ nodejs-scan-sast:
|
|||
phpcs-security-audit-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -167,7 +164,7 @@ phpcs-security-audit-sast:
|
|||
pmd-apex-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -180,7 +177,7 @@ pmd-apex-sast:
|
|||
secrets-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/secrets:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -191,7 +188,7 @@ secrets-sast:
|
|||
security-code-scan-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -205,7 +202,7 @@ security-code-scan-sast:
|
|||
sobelow-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -218,7 +215,7 @@ sobelow-sast:
|
|||
spotbugs-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
@ -233,7 +230,7 @@ spotbugs-sast:
|
|||
tslint-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE_PREFIX/tslint:$SAST_ANALYZER_IMAGE_TAG"
|
||||
name: "$SECURE_ANALYZERS_PREFIX/tslint:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
- if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
|
||||
when: never
|
||||
|
|
29
lib/gitlab/ci/templates/npm.gitlab-ci.yml
Normal file
29
lib/gitlab/ci/templates/npm.gitlab-ci.yml
Normal file
|
@ -0,0 +1,29 @@
|
|||
image: node:latest
|
||||
|
||||
create_npmrc:
|
||||
stage: build
|
||||
script:
|
||||
- |
|
||||
if [ ! -f .npmrc ]; then
|
||||
echo 'No .npmrc found! Creating one now. Please review the following link for more information: https://docs.gitlab.com/ee/user/packages/npm_registry/index.html#authenticating-with-a-ci-job-token'
|
||||
|
||||
echo "@${CI_PROJECT_NAMESPACE%%/*}:registry=\${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" >> .npmrc
|
||||
echo '//gitlab.com/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN}' >> .npmrc
|
||||
echo '//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}' >> .npmrc
|
||||
fi
|
||||
artifacts:
|
||||
paths:
|
||||
- .npmrc
|
||||
|
||||
publish_package:
|
||||
stage: deploy
|
||||
script:
|
||||
- export NPM_PACKAGE_NAME=$(node -p "require('./package.json').name")
|
||||
- export NPM_PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
- |
|
||||
{
|
||||
npm publish &&
|
||||
echo "Successfully published version $NPM_PACKAGE_VERSION of $NPM_PACKAGE_NAME to GitLab's NPM registry."
|
||||
} || {
|
||||
echo "No new version of $NPM_PACKAGE_NAME published. This is most likely because version $NPM_PACKAGE_VERSION already exists in GitLab's NPM registry."
|
||||
}
|
|
@ -8543,6 +8543,9 @@ msgstr ""
|
|||
msgid "Enter the name of your application, and we'll return a unique %{type}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter weights for storages for new repositories."
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter your password to approve"
|
||||
msgstr ""
|
||||
|
||||
|
@ -20040,9 +20043,6 @@ msgstr ""
|
|||
msgid "Select a timezone"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select a weight for the storage new repositories will be placed on."
|
||||
msgstr ""
|
||||
|
||||
msgid "Select all"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -576,7 +576,10 @@ describe('RepoEditor', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('adds an image entry to the same folder for a pasted image in a markdown file', () => {
|
||||
// The following test is flaky
|
||||
// see https://gitlab.com/gitlab-org/gitlab/-/issues/221039
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('adds an image entry to the same folder for a pasted image in a markdown file', () => {
|
||||
pasteImage();
|
||||
|
||||
return waitForPromises().then(() => {
|
||||
|
|
|
@ -134,7 +134,7 @@ describe Gitlab::Ci::Pipeline::Seed::Build::Cache do
|
|||
it_behaves_like 'foo/bar directory key'
|
||||
end
|
||||
|
||||
context 'with directories ending in slash star', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222356' do
|
||||
context 'with directories ending in slash star' do
|
||||
let(:files) { ['foo/bar/*'] }
|
||||
|
||||
it_behaves_like 'foo/bar directory key'
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require Rails.root.join('db', 'migrate', '20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb')
|
||||
|
||||
describe UpdateIndexApprovalRuleNameForCodeOwnersRuleType do
|
||||
let(:migration) { described_class.new }
|
||||
|
||||
let(:approval_rules) { table(:approval_merge_request_rules) }
|
||||
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab') }
|
||||
|
||||
let(:project) do
|
||||
table(:projects).create!(
|
||||
namespace_id: namespace.id,
|
||||
name: 'gitlab',
|
||||
path: 'gitlab'
|
||||
)
|
||||
end
|
||||
|
||||
let(:merge_request) do
|
||||
table(:merge_requests).create!(
|
||||
target_project_id: project.id,
|
||||
source_project_id: project.id,
|
||||
target_branch: 'feature',
|
||||
source_branch: 'master'
|
||||
)
|
||||
end
|
||||
|
||||
let(:index_names) do
|
||||
ActiveRecord::Base.connection
|
||||
.indexes(:approval_merge_request_rules)
|
||||
.collect(&:name)
|
||||
end
|
||||
|
||||
def create_sectional_approval_rules
|
||||
approval_rules.create!(
|
||||
merge_request_id: merge_request.id,
|
||||
name: "*.rb",
|
||||
code_owner: true,
|
||||
rule_type: 2,
|
||||
section: "First Section"
|
||||
)
|
||||
|
||||
approval_rules.create!(
|
||||
merge_request_id: merge_request.id,
|
||||
name: "*.rb",
|
||||
code_owner: true,
|
||||
rule_type: 2,
|
||||
section: "Second Section"
|
||||
)
|
||||
end
|
||||
|
||||
def create_two_matching_nil_section_approval_rules
|
||||
2.times do
|
||||
approval_rules.create!(
|
||||
merge_request_id: merge_request.id,
|
||||
name: "nil_section",
|
||||
code_owner: true,
|
||||
rule_type: 2
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
approval_rules.delete_all
|
||||
end
|
||||
|
||||
describe "#up" do
|
||||
it "creates the new index and removes the 'legacy' indices" do
|
||||
# Confirm that existing legacy indices prevent duplicate entries
|
||||
#
|
||||
expect { create_sectional_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
expect { create_two_matching_nil_section_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
|
||||
approval_rules.delete_all
|
||||
|
||||
disable_migrations_output { migrate! }
|
||||
|
||||
# After running the migration, expect `section == nil` rules to still
|
||||
# be blocked by the legacy indices, but sectional rules are allowed.
|
||||
#
|
||||
expect { create_sectional_approval_rules }
|
||||
.to change { approval_rules.count }.by(2)
|
||||
expect { create_two_matching_nil_section_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
|
||||
# Attempt to rerun the creation of sectional rules, and see that sectional
|
||||
# rules are unique by section
|
||||
#
|
||||
expect { create_sectional_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
|
||||
expect(index_names).to include(
|
||||
described_class::SECTIONAL_INDEX_NAME,
|
||||
described_class::LEGACY_INDEX_NAME_RULE_TYPE,
|
||||
described_class::LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#down" do
|
||||
context "run as FOSS" do
|
||||
before do
|
||||
expect(Gitlab).to receive(:ee?).twice.and_return(false)
|
||||
end
|
||||
|
||||
it "recreates legacy indices, but does not invoke EE-specific code" do
|
||||
disable_migrations_output { migrate! }
|
||||
|
||||
expect(index_names).to include(
|
||||
described_class::SECTIONAL_INDEX_NAME,
|
||||
described_class::LEGACY_INDEX_NAME_RULE_TYPE,
|
||||
described_class::LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
)
|
||||
|
||||
# Since ApprovalMergeRequestRules are EE-specific, we expect none to
|
||||
# be deleted during the migration.
|
||||
#
|
||||
expect { disable_migrations_output { migration.down } }
|
||||
.not_to change { approval_rules.count }
|
||||
|
||||
index_names = ActiveRecord::Base.connection
|
||||
.indexes(:approval_merge_request_rules)
|
||||
.collect(&:name)
|
||||
|
||||
expect(index_names).not_to include(described_class::SECTIONAL_INDEX_NAME)
|
||||
expect(index_names).to include(
|
||||
described_class::LEGACY_INDEX_NAME_RULE_TYPE,
|
||||
described_class::LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "EE" do
|
||||
it "recreates 'legacy' indices and removes duplicate code owner approval rules" do
|
||||
skip("This test is skipped under FOSS") unless Gitlab.ee?
|
||||
|
||||
disable_migrations_output { migrate! }
|
||||
|
||||
expect { create_sectional_approval_rules }
|
||||
.to change { approval_rules.count }.by(2)
|
||||
expect { create_two_matching_nil_section_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
|
||||
# Run the down migration. This will remove the 2 approval rules we create
|
||||
# above, and call MergeRequests::SyncCodeOwnerApprovalRules to recreate
|
||||
# new ones.
|
||||
#
|
||||
expect(MergeRequests::SyncCodeOwnerApprovalRules)
|
||||
.to receive(:new).with(MergeRequest.find(merge_request.id)).once.and_call_original
|
||||
|
||||
# We expect approval_rules.count to be changed by -2 as we're deleting the
|
||||
# 3 rules created above, and MergeRequests::SyncCodeOwnerApprovalRules
|
||||
# will not be able to create new one with an empty (or missing)
|
||||
# CODEOWNERS file.
|
||||
#
|
||||
expect { disable_migrations_output { migration.down } }
|
||||
.to change { approval_rules.count }.by(-3)
|
||||
|
||||
# Test that the index does not allow us to create the same rules as the
|
||||
# previous sectional index.
|
||||
#
|
||||
expect { create_sectional_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
expect { create_two_matching_nil_section_approval_rules }
|
||||
.to raise_exception(ActiveRecord::RecordNotUnique)
|
||||
|
||||
expect(index_names).not_to include(described_class::SECTIONAL_INDEX_NAME)
|
||||
expect(index_names).to include(
|
||||
described_class::LEGACY_INDEX_NAME_RULE_TYPE,
|
||||
described_class::LEGACY_INDEX_NAME_CODE_OWNERS
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,9 +14,8 @@ describe 'Creating a Snippet' do
|
|||
let(:visibility_level) { 'public' }
|
||||
let(:project_path) { nil }
|
||||
let(:uploaded_files) { nil }
|
||||
|
||||
let(:mutation) do
|
||||
variables = {
|
||||
let(:mutation_vars) do
|
||||
{
|
||||
content: content,
|
||||
description: description,
|
||||
visibility_level: visibility_level,
|
||||
|
@ -25,8 +24,10 @@ describe 'Creating a Snippet' do
|
|||
project_path: project_path,
|
||||
uploaded_files: uploaded_files
|
||||
}
|
||||
end
|
||||
|
||||
graphql_mutation(:create_snippet, variables)
|
||||
let(:mutation) do
|
||||
graphql_mutation(:create_snippet, mutation_vars)
|
||||
end
|
||||
|
||||
def mutation_response
|
||||
|
@ -137,6 +138,47 @@ describe 'Creating a Snippet' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when snippet is created using the files param' do
|
||||
let(:action) { :create }
|
||||
let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' }}
|
||||
let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' }}
|
||||
let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] }
|
||||
let(:mutation_vars) do
|
||||
{
|
||||
description: description,
|
||||
visibility_level: visibility_level,
|
||||
project_path: project_path,
|
||||
title: title,
|
||||
files: actions
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates the Snippet' do
|
||||
expect do
|
||||
subject
|
||||
end.to change { Snippet.count }.by(1)
|
||||
end
|
||||
|
||||
it 'returns the created Snippet' do
|
||||
subject
|
||||
|
||||
expect(mutation_response['snippet']['title']).to eq(title)
|
||||
expect(mutation_response['snippet']['description']).to eq(description)
|
||||
expect(mutation_response['snippet']['visibilityLevel']).to eq(visibility_level)
|
||||
expect(mutation_response['snippet']['blobs'][0]['plainData']).to match(file_1[:content])
|
||||
expect(mutation_response['snippet']['blobs'][0]['fileName']).to match(file_1[:file_path])
|
||||
expect(mutation_response['snippet']['blobs'][1]['plainData']).to match(file_2[:content])
|
||||
expect(mutation_response['snippet']['blobs'][1]['fileName']).to match(file_2[:file_path])
|
||||
end
|
||||
|
||||
context 'when action is invalid' do
|
||||
let(:file_1) { { filePath: 'example_file1' }}
|
||||
|
||||
it_behaves_like 'a mutation that returns errors in the response', errors: ['Snippet files have invalid data']
|
||||
it_behaves_like 'does not create snippet'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are ActiveRecord validation errors' do
|
||||
let(:title) { '' }
|
||||
|
||||
|
|
|
@ -155,6 +155,36 @@ describe MergeRequestWidgetEntity do
|
|||
expect(subject[:merge_request_add_ci_config_path]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when merge request is merged' do
|
||||
before do
|
||||
resource.mark_as_merged!
|
||||
end
|
||||
|
||||
it 'returns a blank ci config path' do
|
||||
expect(subject[:merge_request_add_ci_config_path]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when merge request is closed' do
|
||||
before do
|
||||
resource.close!
|
||||
end
|
||||
|
||||
it 'returns a blank ci config path' do
|
||||
expect(subject[:merge_request_add_ci_config_path]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source branch does not exist' do
|
||||
before do
|
||||
resource.source_project.repository.rm_branch(user, resource.source_branch)
|
||||
end
|
||||
|
||||
it 'returns a blank ci config path' do
|
||||
expect(subject[:merge_request_add_ci_config_path]).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user does not have permissions' do
|
||||
|
|
|
@ -283,6 +283,19 @@ describe Snippets::CreateService do
|
|||
expect(snippet.repository.exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'when snippet_files contain an action different from "create"' do
|
||||
let(:snippet_files) { [{ action: 'delete', file_path: 'snippet_file_path.rb' }] }
|
||||
|
||||
it 'a validation error is raised' do
|
||||
response = subject
|
||||
snippet = response.payload[:snippet]
|
||||
|
||||
expect(response).to be_error
|
||||
expect(snippet.errors.full_messages_for(:snippet_files)).to eq ['Snippet files have invalid data']
|
||||
expect(snippet.repository.exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when ProjectSnippet' do
|
||||
|
|
Loading…
Reference in a new issue