Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3b1798cdfa
commit
d91998617f
|
@ -56,6 +56,7 @@ eslint-report.html
|
|||
/doc/code/*
|
||||
/dump.rdb
|
||||
/jsconfig.json
|
||||
/lefthook-local.yml
|
||||
/log/*.log*
|
||||
/node_modules
|
||||
/nohup.out
|
||||
|
|
|
@ -50,6 +50,7 @@ export default {
|
|||
variant="danger"
|
||||
category="secondary"
|
||||
:disabled="!canDelete"
|
||||
data-qa-selector="delete_file_button"
|
||||
@click="$emit('delete')"
|
||||
>{{ s__('Snippets|Delete file') }}</gl-button
|
||||
>
|
||||
|
|
|
@ -2,12 +2,21 @@
|
|||
|
||||
module Resolvers
|
||||
class ProjectPipelinesResolver < BaseResolver
|
||||
include LooksAhead
|
||||
include ResolvesPipelines
|
||||
|
||||
alias_method :project, :object
|
||||
|
||||
def resolve(**args)
|
||||
resolve_pipelines(project, args)
|
||||
def resolve_with_lookahead(**args)
|
||||
apply_lookahead(resolve_pipelines(project, args))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def preloads
|
||||
{
|
||||
jobs: [:statuses]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,6 +56,12 @@ module Types
|
|||
description: 'Specifies if a pipeline can be canceled',
|
||||
method: :cancelable?,
|
||||
null: false
|
||||
|
||||
field :jobs,
|
||||
::Types::Ci::JobType.connection_type,
|
||||
null: true,
|
||||
description: 'Jobs belonging to the pipeline',
|
||||
method: :statuses
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -191,6 +191,7 @@ module Types
|
|||
Types::Ci::PipelineType.connection_type,
|
||||
null: true,
|
||||
description: 'Build pipelines of the project',
|
||||
extras: [:lookahead],
|
||||
resolver: Resolvers::ProjectPipelinesResolver
|
||||
|
||||
field :pipeline,
|
||||
|
|
|
@ -37,12 +37,13 @@ class Packages::Package < ApplicationRecord
|
|||
validate :package_already_taken, if: :npm?
|
||||
validates :name, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
|
||||
validates :name, format: { with: Gitlab::Regex.generic_package_name_regex }, if: :generic?
|
||||
validates :version, format: { with: Gitlab::Regex.semver_regex }, if: :npm?
|
||||
validates :version, format: { with: Gitlab::Regex.nuget_version_regex }, if: :nuget?
|
||||
validates :version, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
|
||||
validates :version, format: { with: Gitlab::Regex.maven_version_regex }, if: -> { version? && maven? }
|
||||
validates :version, format: { with: Gitlab::Regex.pypi_version_regex }, if: :pypi?
|
||||
validates :version, format: { with: Gitlab::Regex.prefixed_semver_regex }, if: :golang?
|
||||
validates :version, format: { with: Gitlab::Regex.semver_regex }, if: -> { composer_tag_version? || npm? }
|
||||
|
||||
validates :version,
|
||||
presence: true,
|
||||
format: { with: Gitlab::Regex.generic_package_version_regex },
|
||||
|
@ -174,6 +175,10 @@ class Packages::Package < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def composer_tag_version?
|
||||
composer? && !Gitlab::Regex.composer_dev_version_regex.match(version.to_s)
|
||||
end
|
||||
|
||||
def valid_conan_package_recipe
|
||||
recipe_exists = project.packages
|
||||
.conan
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
= clipboard_button(target: '#serverless_domain_verification', class: 'btn-default d-none d-sm-block')
|
||||
%p.form-text.text-muted
|
||||
- link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help }
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
|
||||
|
||||
- else
|
||||
.form-group
|
||||
|
|
|
@ -30,4 +30,4 @@
|
|||
= clipboard_button(target: '#domain_verification', class: 'btn-default d-none d-sm-block')
|
||||
%p.form-text.text-muted
|
||||
- link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help }
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add jobs field with secureReportTypes argument to Ci::PipelineType
|
||||
merge_request: 45837
|
||||
author:
|
||||
type: added
|
|
@ -37,7 +37,8 @@ def build_message(commit, message, more_info: true)
|
|||
end
|
||||
|
||||
def squash_mr?
|
||||
gitlab_danger.ci? ? gitlab.mr_json['squash'] : false
|
||||
# Locally, we assume the MR is set to be squashed so that the user only sees warnings instead of errors.
|
||||
gitlab_danger.ci? ? gitlab.mr_json['squash'] : true
|
||||
end
|
||||
|
||||
def wip_mr?
|
||||
|
@ -112,7 +113,7 @@ def lint_commits(commits)
|
|||
|
||||
if multi_line_commit_linter && multi_line_commit_linter.failed?
|
||||
warn_or_fail_commits(multi_line_commit_linter)
|
||||
else
|
||||
elsif gitlab_danger.ci? # We don't have access to the MR title locally
|
||||
title_linter = lint_mr_title(gitlab.mr_json['title'])
|
||||
if title_linter.failed?
|
||||
warn_or_fail_commits(title_linter)
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
- title: Group wikis
|
||||
body: For many teams, using GitLab wikis for planning and documentation is a critical part of their workflow. Wikis are so popular that they get over a million views each month on GitLab.com. Despite this popularity, teams have struggled with the limitation that wikis were only available at the project level. Teams working on multiple projects needed to create separate wikis for each repository, leading to a fragmented experience. In Gitlab 13.5, we are so excited to bring you group wikis! This was the most upvoted feature in the entire GitLab backlog. While highly requested, making a large project-only feature like wikis available at the group level has been a non-trivial operation. We’ve worked tirelessly over the past year to make it happen and now we can't wait to get it in your hands and hear your feedback.
|
||||
stage: Create
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
packages: [Premium, Ultimate]
|
||||
url: https://docs.gitlab.com/ee/user/group/index.html#group-wikis
|
||||
image_url: https://about.gitlab.com/images/13_5/cdybenko-group-wiki.png
|
||||
published_at: 2020-10-22
|
||||
release: 13.5
|
||||
- title: Install the GitLab Kubernetes Agent with Omnibus GitLab
|
||||
body: "Last month we introduced the GitLab Kubernetes Agent for self-managed GitLab instances installed with Helm. This release adds support for the official Linux package. In this new Kubernetes integration, the Agent orchestrates deployments by pulling new changes from GitLab, rather than GitLab pushing updates to your cluster."
|
||||
stage: Configure
|
||||
self-managed: true
|
||||
gitlab-com: false
|
||||
packages: [Premium, Ultimate]
|
||||
url: https://docs.gitlab.com/ee/user/clusters/agent/
|
||||
image_url: https://about.gitlab.com/images/13_5/gitops-header.png
|
||||
published_at: 2020-10-22
|
||||
release: 13.5
|
||||
- title: Snippets with multiple files
|
||||
body: Engineers often use Snippets to share examples of code, reusable components, logs, and other items. These valuable pieces of information often require additional context and may require more than one file. Sharing a link to multiple files or multiple Snippets makes it challenging for users to piece this context together and understand the scope of what is being presented. GitLab now supports multiple files inside of a single Snippet, so you can create Snippets composed of multiple parts. It broadens its use to endless possibilities!
|
||||
stage: Create
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
packages: [Core, Starter, Premium, Ultimate]
|
||||
url: https://docs.gitlab.com/ee/user/snippets.html#multiple-files-by-snippet
|
||||
image_url: https://about.gitlab.com/images/13_5/phikai-snippets-multiple-files.png
|
||||
published_at: 2020-10-22
|
||||
release: 13.5
|
||||
- title: Enable instance-level shared runners when viewing groups
|
||||
body: GitLab SaaS includes Linux and Windows runners, which are easy to use agents that run your GitLab CI/CD pipeline jobs. These runners, visible in the GitLab.com UI as "shared runners," are enabled by default and can be disabled for each project. However, some organizations require their CI/CD jobs to run only on self-managed runners, and so disabling the use of instance-level shared runners on each project resulted in unnecessary administrative overhead. Now administrators can enable or disable shared runners at the group level. Administrators can also allow groups to override the global setting and use shared runners on a project-by-project basis.
|
||||
stage: Verify
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
packages: [Core, Starter, Premium, Ultimate]
|
||||
url: https://docs.gitlab.com/ee/ci/runners/README.html#disable-shared-runners
|
||||
image_url: https://about.gitlab.com/images/13_5/enable_shared_runners_v2.png
|
||||
published_at: 2020-10-22
|
||||
release: 13.5
|
||||
- title: Feature Flags flexible rollout strategy
|
||||
body: When you use the percent rollout strategy today, the stickiness, or the experience consistency, is determined only by the user ID. This can be limiting; as an example, anonymous users cannot be affected by this strategy. We have improved this rollout strategy by enabling you to define the stickiness based on session ID, user ID, or at random (no stickiness). This gives you more control over the rollout and allows you to support stickiness for anonymous users.
|
||||
stage: Release
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
packages: [core, starter, premium, ultimate]
|
||||
url: https://docs.gitlab.com/ee/operations/feature_flags.html#percent-rollout
|
||||
image_url: https://about.gitlab.com/images/13_5/percent-rollout.png
|
||||
published_at: 2020-10-22
|
||||
release: 13.5
|
||||
- title: SAST support for iOS and Android mobile apps
|
||||
body: GitLab SAST now supports mobile applications including iOS apps written in Objective-C and Swift as well as Android apps written in Java and Kotlin powered by the Mobile Security Framework (MobSF). Initially this analyzer supports source code analysis but we intend to expand support for binary scanning of .ipa and .apk files in the near future. This feature was a generous contribution by the H-E-B Digital team.
|
||||
stage: Secure
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
packages: [core, starter, premium, ultimate]
|
||||
url: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
|
||||
image_url: https://about.gitlab.com/images/13_5/sast-gitlab-mobile.png
|
||||
published_at: 2020-10-22
|
||||
release: 13.5
|
|
@ -13675,6 +13675,36 @@ type Pipeline {
|
|||
"""
|
||||
iid: String!
|
||||
|
||||
"""
|
||||
Jobs belonging to the pipeline
|
||||
"""
|
||||
jobs(
|
||||
"""
|
||||
Returns the elements in the list that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements in the list that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns the first _n_ elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns the last _n_ elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
|
||||
"""
|
||||
Filter jobs by the type of security report they produce
|
||||
"""
|
||||
securityReportTypes: [SecurityReportTypeEnum!]
|
||||
): CiJobConnection
|
||||
|
||||
"""
|
||||
Specifies if a pipeline can be retried
|
||||
"""
|
||||
|
@ -18181,6 +18211,43 @@ type SecurityReportSummarySection {
|
|||
vulnerabilitiesCount: Int
|
||||
}
|
||||
|
||||
enum SecurityReportTypeEnum {
|
||||
"""
|
||||
API FUZZING scan report
|
||||
"""
|
||||
API_FUZZING
|
||||
|
||||
"""
|
||||
CONTAINER SCANNING scan report
|
||||
"""
|
||||
CONTAINER_SCANNING
|
||||
|
||||
"""
|
||||
COVERAGE FUZZING scan report
|
||||
"""
|
||||
COVERAGE_FUZZING
|
||||
|
||||
"""
|
||||
DAST scan report
|
||||
"""
|
||||
DAST
|
||||
|
||||
"""
|
||||
DEPENDENCY SCANNING scan report
|
||||
"""
|
||||
DEPENDENCY_SCANNING
|
||||
|
||||
"""
|
||||
SAST scan report
|
||||
"""
|
||||
SAST
|
||||
|
||||
"""
|
||||
SECRET DETECTION scan report
|
||||
"""
|
||||
SECRET_DETECTION
|
||||
}
|
||||
|
||||
"""
|
||||
The type of the security scanner
|
||||
"""
|
||||
|
|
|
@ -40202,6 +40202,77 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "jobs",
|
||||
"description": "Jobs belonging to the pipeline",
|
||||
"args": [
|
||||
{
|
||||
"name": "securityReportTypes",
|
||||
"description": "Filter jobs by the type of security report they produce",
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "SecurityReportTypeEnum",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "after",
|
||||
"description": "Returns the elements in the list that come after the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "before",
|
||||
"description": "Returns the elements in the list that come before the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "first",
|
||||
"description": "Returns the first _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "last",
|
||||
"description": "Returns the last _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "CiJobConnection",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "retryable",
|
||||
"description": "Specifies if a pipeline can be retried",
|
||||
|
@ -52355,6 +52426,59 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "SecurityReportTypeEnum",
|
||||
"description": null,
|
||||
"fields": null,
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": [
|
||||
{
|
||||
"name": "SAST",
|
||||
"description": "SAST scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "DAST",
|
||||
"description": "DAST scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "DEPENDENCY_SCANNING",
|
||||
"description": "DEPENDENCY SCANNING scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "CONTAINER_SCANNING",
|
||||
"description": "CONTAINER SCANNING scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "SECRET_DETECTION",
|
||||
"description": "SECRET DETECTION scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "COVERAGE_FUZZING",
|
||||
"description": "COVERAGE FUZZING scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "API_FUZZING",
|
||||
"description": "API FUZZING scan report",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "SecurityScannerType",
|
||||
|
|
|
@ -3806,6 +3806,18 @@ Size of UI component in SAST configuration page.
|
|||
| `MEDIUM` | |
|
||||
| `SMALL` | |
|
||||
|
||||
### SecurityReportTypeEnum
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| `API_FUZZING` | API FUZZING scan report |
|
||||
| `CONTAINER_SCANNING` | CONTAINER SCANNING scan report |
|
||||
| `COVERAGE_FUZZING` | COVERAGE FUZZING scan report |
|
||||
| `DAST` | DAST scan report |
|
||||
| `DEPENDENCY_SCANNING` | DEPENDENCY SCANNING scan report |
|
||||
| `SAST` | SAST scan report |
|
||||
| `SECRET_DETECTION` | SECRET DETECTION scan report |
|
||||
|
||||
### SecurityScannerType
|
||||
|
||||
The type of the security scanner.
|
||||
|
|
|
@ -15,25 +15,35 @@ settings automatically by default. If your editor/IDE does not automatically sup
|
|||
we suggest investigating to see if a plugin exists. For instance here is the
|
||||
[plugin for vim](https://github.com/editorconfig/editorconfig-vim).
|
||||
|
||||
## Pre-commit static analysis
|
||||
## Pre-push static analysis
|
||||
|
||||
You should install [`overcommit`](https://github.com/sds/overcommit) to automatically check for
|
||||
static analysis offenses before committing locally.
|
||||
We strongly recommend installing
|
||||
[Lefthook](https://github.com/Arkweid/lefthook) to automatically check for
|
||||
static analysis offenses before pushing your changes.
|
||||
|
||||
After installing `overcommit`, run the following in your GitLab source directory:
|
||||
|
||||
```shell
|
||||
make -C tooling/overcommit
|
||||
# Make sure to uninstall Overcommit first
|
||||
overcommit --uninstall
|
||||
|
||||
# Install lefthook
|
||||
gem install lefthook && lefthook install -f
|
||||
```
|
||||
|
||||
Then before a commit is created, `overcommit` automatically checks for RuboCop (and other checks)
|
||||
offenses on every modified file.
|
||||
Before you push your changes, Lefthook will then automatically run Danger checks, as well
|
||||
as RuboCop, ES Lint, HAML Lint, and SCSS Lint for the changed files.
|
||||
|
||||
This saves you time as you don't have to wait for the same errors to be detected by CI/CD.
|
||||
|
||||
`overcommit` relies on a pre-commit hook to prevent commits that violate its ruleset. To override
|
||||
this behavior, pass the `OVERCOMMIT_DISABLE` environment variable. For example,
|
||||
`OVERCOMMIT_DISABLE=1 git rebase master` to rebase while disabling the Git hook.
|
||||
Lefthook relies on a pre-push hook to prevent commits that violate its ruleset.
|
||||
If you wish to override this behavior, pass the environment variable `LEFTHOOK=0`.
|
||||
That is, `LEFTHOOK=0 git push`.
|
||||
|
||||
You can also:
|
||||
|
||||
- Define [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
|
||||
- Skip [checks per tag on the fly](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#skip-some-tags-on-the-fly).
|
||||
|
||||
## Ruby, Rails, RSpec
|
||||
|
||||
|
|
|
@ -716,7 +716,7 @@ Sample configuration for `overcommit` is available in the
|
|||
file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project.
|
||||
|
||||
To set up `overcommit` for documentation linting, see
|
||||
[Pre-commit static analysis](../contributing/style_guides.md#pre-commit-static-analysis).
|
||||
[Pre-commit static analysis](../contributing/style_guides.md#pre-push-static-analysis).
|
||||
|
||||
#### Disable Vale tests
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
pre-push:
|
||||
parallel: true
|
||||
commands:
|
||||
danger:
|
||||
run: bundle exec danger dry_run
|
||||
eslint:
|
||||
tags: frontend style
|
||||
files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: "*.{js,vue}"
|
||||
run: yarn eslint --cache --max-warnings 0 --report-unused-disable-directives {files}
|
||||
haml-lint:
|
||||
tags: view haml style
|
||||
files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: "*.html.haml"
|
||||
run: bundle exec haml-lint --config .haml-lint.yml {files}
|
||||
scss-lint:
|
||||
tags: stylesheet css style
|
||||
files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: "*.scss.css"
|
||||
exclude: "app/assets/stylesheets/pages/emojis.scss"
|
||||
run: bundle exec scss-lint --config .scss-lint.yml {files}
|
||||
rubocop:
|
||||
tags: backend style
|
||||
files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: "*.rb"
|
||||
run: bundle exec rubocop --parallel --force-exclusion {files}
|
|
@ -168,7 +168,7 @@ module Gitlab
|
|||
|
||||
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
|
||||
%r{\A\.codeclimate\.yml\z} => :engineering_productivity,
|
||||
%r{\A\.overcommit\.yml\.example\z} => :engineering_productivity,
|
||||
%r{\Alefthook.yml\z} => :engineering_productivity,
|
||||
%r{\A\.editorconfig\z} => :engineering_productivity,
|
||||
%r{Dangerfile\z} => :engineering_productivity,
|
||||
%r{\A(ee/)?(danger/|lib/gitlab/danger/)} => :engineering_productivity,
|
||||
|
|
|
@ -22,6 +22,10 @@ module Gitlab
|
|||
@composer_package_version_regex ||= %r{^v?(\d+(\.(\d+|x))*(-.+)?)}.freeze
|
||||
end
|
||||
|
||||
def composer_dev_version_regex
|
||||
@composer_dev_version_regex ||= %r{(^dev-)|(-dev$)}.freeze
|
||||
end
|
||||
|
||||
def package_name_regex
|
||||
@package_name_regex ||= %r{\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z}.freeze
|
||||
end
|
||||
|
|
|
@ -27810,7 +27810,7 @@ msgstr ""
|
|||
msgid "To"
|
||||
msgstr ""
|
||||
|
||||
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
|
||||
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
|
||||
msgstr ""
|
||||
|
||||
msgid "To Do"
|
||||
|
|
|
@ -110,6 +110,18 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
def has_no_file_name?(file_name, file_number = nil)
|
||||
if file_number
|
||||
within_element_by_index(:file_title_content, file_number - 1) do
|
||||
has_no_text?(file_name)
|
||||
end
|
||||
else
|
||||
within_element(:file_title_content) do
|
||||
has_no_text?(file_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def has_file_content?(file_content, file_number = nil)
|
||||
if file_number
|
||||
within_element_by_index(:file_content, file_number - 1) do
|
||||
|
|
|
@ -14,6 +14,10 @@ module QA
|
|||
element :file_holder_container
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/blob/components/blob_edit_header.vue' do
|
||||
element :delete_file_button
|
||||
end
|
||||
|
||||
def add_to_file_content(content)
|
||||
text_area.set content
|
||||
text_area.has_text?(content) # wait for changes to take effect
|
||||
|
@ -47,6 +51,12 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
def click_delete_file(file_number)
|
||||
within_element_by_index(:file_holder_container, file_number - 1) do
|
||||
click_element(:delete_file_button)
|
||||
end
|
||||
end
|
||||
|
||||
def save_changes
|
||||
wait_until(reload: false) { !find_element(:submit_button).disabled? }
|
||||
click_element(:submit_button, Page::Dashboard::Snippet::Show)
|
||||
|
|
|
@ -56,14 +56,16 @@ module QA
|
|||
title: title,
|
||||
description: description,
|
||||
visibility: visibility.downcase,
|
||||
files: [
|
||||
{
|
||||
content: file_content,
|
||||
file_path: file_name
|
||||
}
|
||||
]
|
||||
files: all_file_contents
|
||||
}
|
||||
end
|
||||
|
||||
def all_file_contents
|
||||
@files.insert(0, { name: @file_name, content: @file_content })
|
||||
@files.each do |file|
|
||||
file[:file_path] = file.delete(:name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Create' do
|
||||
describe 'Multiple file snippet' do
|
||||
let(:personal_snippet) do
|
||||
Resource::Snippet.fabricate_via_api! do |snippet|
|
||||
snippet.title = 'Personal snippet to delete file from'
|
||||
snippet.file_name = 'Original file name'
|
||||
snippet.file_content = 'Original file content'
|
||||
|
||||
snippet.add_files do |files|
|
||||
files.append(name: 'Second file name', content: 'Second file content')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:project_snippet) do
|
||||
Resource::ProjectSnippet.fabricate_via_api! do |snippet|
|
||||
snippet.title = 'Project snippet to delete file from'
|
||||
snippet.file_name = 'Original file name'
|
||||
snippet.file_content = 'Original file content'
|
||||
|
||||
snippet.add_files do |files|
|
||||
files.append(name: 'Second file name', content: 'Second file content')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
shared_examples 'deleting file from snippet' do |snippet_type|
|
||||
it "deletes second file from an existing #{snippet_type} to make it single-file" do
|
||||
send(snippet_type).visit!
|
||||
|
||||
Page::Dashboard::Snippet::Show.perform(&:click_edit_button)
|
||||
|
||||
Page::Dashboard::Snippet::Edit.perform do |snippet|
|
||||
snippet.click_delete_file(2)
|
||||
snippet.save_changes
|
||||
end
|
||||
|
||||
Page::Dashboard::Snippet::Show.perform do |snippet|
|
||||
aggregate_failures 'file names and contents' do
|
||||
expect(snippet).to have_file_name('Original file name')
|
||||
expect(snippet).to have_file_content('Original file content')
|
||||
expect(snippet).to have_no_file_name('Second file name')
|
||||
expect(snippet).to have_no_file_content('Second file content')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'deleting file from snippet', :personal_snippet
|
||||
it_behaves_like 'deleting file from snippet', :project_snippet
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,127 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Package', :orchestrated, :packages do
|
||||
describe 'Maven Repository with Gradle' do
|
||||
include Runtime::Fixtures
|
||||
|
||||
let(:group_id) { 'com.gitlab.qa' }
|
||||
let(:artifact_id) { 'maven_gradle' }
|
||||
let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
|
||||
let(:auth_token) do
|
||||
unless Page::Main::Menu.perform(&:signed_in?)
|
||||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
Resource::PersonalAccessToken.fabricate!.access_token
|
||||
end
|
||||
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = 'maven-with-gradle-project'
|
||||
project.initialize_with_readme = true
|
||||
end
|
||||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
runner.project = project
|
||||
end
|
||||
end
|
||||
|
||||
let(:gitlab_address_with_port) do
|
||||
uri = URI.parse(Runtime::Scenario.gitlab_address)
|
||||
"#{uri.scheme}://#{uri.host}:#{uri.port}"
|
||||
end
|
||||
|
||||
after do
|
||||
runner.remove_via_api!
|
||||
end
|
||||
|
||||
it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
commit.commit_message = 'Add .gitlab-ci.yml'
|
||||
commit.add_files([{
|
||||
file_path: '.gitlab-ci.yml',
|
||||
content:
|
||||
<<~YAML
|
||||
deploy:
|
||||
image: gradle:6.5-jdk11
|
||||
script:
|
||||
- 'gradle publish'
|
||||
only:
|
||||
- master
|
||||
tags:
|
||||
- "runner-for-#{project.name}"
|
||||
YAML
|
||||
},
|
||||
{
|
||||
file_path: 'build.gradle',
|
||||
content:
|
||||
<<~EOF
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
library(MavenPublication) {
|
||||
groupId '#{group_id}'
|
||||
artifactId '#{artifact_id}'
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/maven"
|
||||
credentials(HttpHeaderCredentials) {
|
||||
name = "Private-Token"
|
||||
value = "#{auth_token}"
|
||||
}
|
||||
authentication {
|
||||
header(HttpHeaderAuthentication)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}])
|
||||
end
|
||||
|
||||
project.visit!
|
||||
Page::Project::Menu.perform(&:click_ci_cd_pipelines)
|
||||
Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
|
||||
|
||||
Page::Project::Pipeline::Show.perform do |pipeline|
|
||||
pipeline.click_job('deploy')
|
||||
end
|
||||
|
||||
Page::Project::Job::Show.perform do |job|
|
||||
expect(job).to be_successful(timeout: 800)
|
||||
end
|
||||
|
||||
Page::Project::Menu.perform(&:click_packages_link)
|
||||
|
||||
Page::Project::Packages::Index.perform do |index|
|
||||
expect(index).to have_package(package_name)
|
||||
|
||||
index.click_package(package_name)
|
||||
end
|
||||
|
||||
Page::Project::Packages::Show.perform do |show|
|
||||
show.click_delete
|
||||
end
|
||||
|
||||
Page::Project::Packages::Index.perform do |index|
|
||||
expect(index).to have_content("Package deleted successfully")
|
||||
expect(index).to have_no_package(package_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -278,9 +278,9 @@ RSpec.describe Gitlab::Danger::Helper do
|
|||
'scripts/foo' | [:engineering_productivity]
|
||||
'lib/gitlab/danger/foo' | [:engineering_productivity]
|
||||
'ee/lib/gitlab/danger/foo' | [:engineering_productivity]
|
||||
'.overcommit.yml.example' | [:engineering_productivity]
|
||||
'lefthook.yml' | [:engineering_productivity]
|
||||
'.editorconfig' | [:engineering_productivity]
|
||||
'tooling/overcommit/foo' | [:engineering_productivity]
|
||||
'tooling/bin/find_foss_tests' | [:engineering_productivity]
|
||||
'.codeclimate.yml' | [:engineering_productivity]
|
||||
'.gitlab/CODEOWNERS' | [:engineering_productivity]
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
# This is temporary while https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45733 gets rolled out.
|
||||
# TODO: clean this up once the MR has been merged.
|
||||
# As each associated, backwards-compatible experiment gets cleaned up and removed from the EXPERIMENTS list, its key will also get removed from this list. Once the list here is empty, we can remove the backwards compatibility code altogether.
|
||||
# Originally created as part of https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45733 for https://gitlab.com/gitlab-org/gitlab/-/issues/270858.
|
||||
RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
|
||||
it 'temporarily ensures we know what experiments exist for backwards compatibility' do
|
||||
known_experiments = [
|
||||
expected_experiment_keys = [
|
||||
:signup_flow,
|
||||
:onboarding_issues,
|
||||
:ci_notification_dot,
|
||||
|
@ -23,7 +23,10 @@ RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
|
|||
:default_to_issues_board
|
||||
]
|
||||
|
||||
expect(described_class.keys).to match(known_experiments)
|
||||
backwards_compatible_experiment_keys = described_class.filter { |_, v| v[:use_backwards_compatible_subject_index] }.keys
|
||||
|
||||
expect(backwards_compatible_experiment_keys).not_to be_empty, "Oh, hey! Let's clean up that :use_backwards_compatible_subject_index stuff now :D"
|
||||
expect(backwards_compatible_experiment_keys).to match(expected_experiment_keys)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -243,6 +243,15 @@ RSpec.describe Gitlab::Regex do
|
|||
it { is_expected.not_to match('!!()()') }
|
||||
end
|
||||
|
||||
describe '.composer_dev_version_regex' do
|
||||
subject { described_class.composer_dev_version_regex }
|
||||
|
||||
it { is_expected.to match('dev-master') }
|
||||
it { is_expected.to match('1.x-dev') }
|
||||
it { is_expected.not_to match('foobar') }
|
||||
it { is_expected.not_to match('1.2.3') }
|
||||
end
|
||||
|
||||
describe '.conan_recipe_component_regex' do
|
||||
subject { described_class.conan_recipe_component_regex }
|
||||
|
||||
|
|
|
@ -156,6 +156,13 @@ RSpec.describe Packages::Package, type: :model do
|
|||
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
|
||||
end
|
||||
|
||||
context 'composer package' do
|
||||
it_behaves_like 'validating version to be SemVer compliant for', :composer_package
|
||||
|
||||
it { is_expected.to allow_value('dev-master').for(:version) }
|
||||
it { is_expected.to allow_value('2.x-dev').for(:version) }
|
||||
end
|
||||
|
||||
context 'maven package' do
|
||||
subject { build_stubbed(:maven_package) }
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Query.project(fullPath).pipelines' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, :repository, :public) }
|
||||
let_it_be(:first_user) { create(:user) }
|
||||
let_it_be(:second_user) { create(:user) }
|
||||
|
||||
describe '.jobs' do
|
||||
let_it_be(:query) do
|
||||
%(
|
||||
query {
|
||||
project(fullPath: "#{project.full_path}") {
|
||||
pipelines {
|
||||
nodes {
|
||||
jobs {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it 'fetches the jobs without an N+1' do
|
||||
pipeline = create(:ci_pipeline, project: project)
|
||||
create(:ci_build, pipeline: pipeline, name: 'Job 1')
|
||||
|
||||
control_count = ActiveRecord::QueryRecorder.new do
|
||||
post_graphql(query, current_user: first_user)
|
||||
end
|
||||
|
||||
pipeline = create(:ci_pipeline, project: project)
|
||||
create(:ci_build, pipeline: pipeline, name: 'Job 2')
|
||||
|
||||
expect do
|
||||
post_graphql(query, current_user: second_user)
|
||||
end.not_to exceed_query_limit(control_count)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
|
||||
pipelines_data = graphql_data.dig('project', 'pipelines', 'nodes')
|
||||
|
||||
job_names = pipelines_data.map do |pipeline_data|
|
||||
jobs_data = pipeline_data.dig('jobs', 'nodes')
|
||||
jobs_data.map { |job_data| job_data['name'] }
|
||||
end.flatten
|
||||
|
||||
expect(job_names).to contain_exactly('Job 1', 'Job 2')
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue