Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-10-30 06:08:54 +00:00
parent 3b1798cdfa
commit d91998617f
30 changed files with 652 additions and 31 deletions

1
.gitignore vendored
View File

@ -56,6 +56,7 @@ eslint-report.html
/doc/code/*
/dump.rdb
/jsconfig.json
/lefthook-local.yml
/log/*.log*
/node_modules
/nohup.out

View File

@ -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
>

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -0,0 +1,5 @@
---
title: Add jobs field with secureReportTypes argument to Ci::PipelineType
merge_request: 45837
author:
type: added

View File

@ -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)

View File

@ -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. Weve 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

View File

@ -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
"""

View File

@ -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",

View File

@ -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.

View File

@ -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

View File

@ -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

26
lefthook.yml Normal file
View File

@ -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}

View File

@ -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,

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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 }

View File

@ -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) }

View File

@ -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