Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
35272ed523
commit
145fb28542
|
@ -63,7 +63,6 @@ export default {
|
|||
data-testid="preview-item"
|
||||
@click="onClickDraft(draft)"
|
||||
>
|
||||
{{ isOnLatestDiff(draft) }}
|
||||
<preview-item :draft="draft" :is-last="isLast(index)" />
|
||||
</gl-dropdown-item>
|
||||
</gl-dropdown>
|
||||
|
|
|
@ -136,6 +136,7 @@ export default {
|
|||
v-for="group in groups"
|
||||
:key="group.id"
|
||||
:name="group.name"
|
||||
data-qa-selector="group_select_dropdown_item"
|
||||
@click="selectGroup(group)"
|
||||
>
|
||||
<gl-avatar-labeled
|
||||
|
|
|
@ -371,51 +371,3 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
|
|||
/* stylelint-disable property-no-vendor-prefix */
|
||||
-webkit-backdrop-filter: blur(2px); // still required by Safari
|
||||
}
|
||||
|
||||
/*
|
||||
* The styles from here to END-#1825 will be moved to @gitlab/ui by
|
||||
* https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1825
|
||||
*/
|
||||
.gl-lg-mx-12 {
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: $gl-spacing-scale-12;
|
||||
margin-right: $gl-spacing-scale-12;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-ml-12 {
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: $gl-spacing-scale-12;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-mr-12 {
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-right: $gl-spacing-scale-12;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-ml-10 {
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: $gl-spacing-scale-10;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-mr-10 {
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-right: $gl-spacing-scale-10;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-w-30p {
|
||||
@include gl-media-breakpoint-up(lg) {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-lg-w-40p {
|
||||
@include gl-media-breakpoint-up(lg) {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
/* END-#1825 */
|
||||
|
|
|
@ -4,8 +4,8 @@ module Clusters
|
|||
class AgentsFinder
|
||||
include FinderMethods
|
||||
|
||||
def initialize(project, current_user, params: {})
|
||||
@project = project
|
||||
def initialize(object, current_user, params: {})
|
||||
@object = object
|
||||
@current_user = current_user
|
||||
@params = params
|
||||
end
|
||||
|
@ -13,7 +13,7 @@ module Clusters
|
|||
def execute
|
||||
return ::Clusters::Agent.none unless can_read_cluster_agents?
|
||||
|
||||
agents = project.cluster_agents
|
||||
agents = object.cluster_agents
|
||||
agents = agents.with_name(params[:name]) if params[:name].present?
|
||||
|
||||
agents.ordered_by_name
|
||||
|
@ -21,10 +21,10 @@ module Clusters
|
|||
|
||||
private
|
||||
|
||||
attr_reader :project, :current_user, :params
|
||||
attr_reader :object, :current_user, :params
|
||||
|
||||
def can_read_cluster_agents?
|
||||
current_user.can?(:read_cluster, project)
|
||||
current_user&.can?(:read_cluster, object)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,12 +15,10 @@ module Resolvers
|
|||
description: 'Name of the cluster agent.'
|
||||
end
|
||||
|
||||
alias_method :project, :object
|
||||
|
||||
def resolve_with_lookahead(**args)
|
||||
apply_lookahead(
|
||||
::Clusters::AgentsFinder
|
||||
.new(project, current_user, params: args)
|
||||
.new(object, current_user, params: args)
|
||||
.execute
|
||||
)
|
||||
end
|
||||
|
|
|
@ -53,3 +53,5 @@ module Clusters
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Clusters::Agent.prepend_mod_with('Clusters::Agent')
|
||||
|
|
|
@ -474,6 +474,7 @@ class Project < ApplicationRecord
|
|||
delegate :forward_deployment_enabled, :forward_deployment_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :job_token_scope_enabled, :job_token_scope_enabled=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :keep_latest_artifact, :keep_latest_artifact=, to: :ci_cd_settings, allow_nil: true
|
||||
delegate :opt_in_jwt, :opt_in_jwt=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :restrict_user_defined_variables, :restrict_user_defined_variables=, to: :ci_cd_settings, allow_nil: true
|
||||
delegate :separated_caches, :separated_caches=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
|
||||
delegate :runner_token_expiration_interval, :runner_token_expiration_interval=, :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval_human_readable=, to: :ci_cd_settings, allow_nil: true
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: operational_vulnerabilities_filters
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90845
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365986
|
||||
milestone: '15.2'
|
||||
type: development
|
||||
group: group::container security
|
||||
default_enabled: false
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddToggleOptInJwt < Gitlab::Database::Migration[2.0]
|
||||
def change
|
||||
add_column :project_ci_cd_settings, :opt_in_jwt, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
a18f38b1f25ab3344c3ce8dcefc4579370c79e70354dc1665dbb8026892e1e37
|
|
@ -19202,7 +19202,8 @@ CREATE TABLE project_ci_cd_settings (
|
|||
restrict_user_defined_variables boolean DEFAULT false NOT NULL,
|
||||
job_token_scope_enabled boolean DEFAULT false NOT NULL,
|
||||
runner_token_expiration_interval integer,
|
||||
separated_caches boolean DEFAULT true NOT NULL
|
||||
separated_caches boolean DEFAULT true NOT NULL,
|
||||
opt_in_jwt boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE project_ci_cd_settings_id_seq
|
||||
|
|
|
@ -611,6 +611,13 @@ user.skip_reconfirmation!
|
|||
|
||||
### Disable 2fa for single user
|
||||
|
||||
**In GitLab 13.5 and later:**
|
||||
|
||||
Use the code under [Disable 2FA | For a single user](../../security/two_factor_authentication.md#for-a-single-user) so that the target user
|
||||
is notified that 2FA has been disabled.
|
||||
|
||||
**In GitLab 13.4 and earlier:**
|
||||
|
||||
```ruby
|
||||
user = User.find_by_username('<username>')
|
||||
user.disable_two_factor!
|
||||
|
|
|
@ -11694,6 +11694,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| <a id="groupallowstalerunnerpruning"></a>`allowStaleRunnerPruning` | [`Boolean!`](#boolean) | Indicates whether to regularly prune stale group runners. Defaults to false. |
|
||||
| <a id="groupautodevopsenabled"></a>`autoDevopsEnabled` | [`Boolean`](#boolean) | Indicates whether Auto DevOps is enabled for all projects within this group. |
|
||||
| <a id="groupavatarurl"></a>`avatarUrl` | [`String`](#string) | Avatar URL of the group. |
|
||||
| <a id="groupclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with projects in the group and its subgroups. (see [Connections](#connections)) |
|
||||
| <a id="groupcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the group. |
|
||||
| <a id="groupcontainslockedprojects"></a>`containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
|
||||
| <a id="groupcrossprojectpipelineavailable"></a>`crossProjectPipelineAvailable` | [`Boolean!`](#boolean) | Indicates if the cross_project_pipeline feature is available for the namespace. |
|
||||
|
@ -12573,6 +12574,7 @@ A block of time for which a participant is on-call.
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="instancesecuritydashboardclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with projects selected in the Instance Security Dashboard. (see [Connections](#connections)) |
|
||||
| <a id="instancesecuritydashboardvulnerabilitygrades"></a>`vulnerabilityGrades` | [`[VulnerableProjectsByGrade!]!`](#vulnerableprojectsbygrade) | Represents vulnerable project counts for each grade. |
|
||||
| <a id="instancesecuritydashboardvulnerabilityscanners"></a>`vulnerabilityScanners` | [`VulnerabilityScannerConnection`](#vulnerabilityscannerconnection) | Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard. (see [Connections](#connections)) |
|
||||
|
||||
|
|
|
@ -1,32 +1,11 @@
|
|||
---
|
||||
stage: Secure, Protect
|
||||
group: all
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
type: index, dev, reference
|
||||
redirect_to: '../index.md'
|
||||
remove_date: '2022-09-23'
|
||||
---
|
||||
|
||||
# Application Security development documentation
|
||||
This document was moved to [another location](../index.md).
|
||||
|
||||
Development guides that are specific to the stages that work on Application Security features are listed here.
|
||||
|
||||
Please go to [Application Security](../../user/application_security/index.md) if you are looking for documentation on how to use those features.
|
||||
|
||||
## Namespaces
|
||||
|
||||
Application Security code in the Rails monolith is organized into the following namespaces, which generally follows
|
||||
the feature categories in the [Secure](https://about.gitlab.com/stages-devops-lifecycle/secure/) and [Protect](https://about.gitlab.com/stages-devops-lifecycle/protect/) stages.
|
||||
|
||||
- `AppSec`: shared code.
|
||||
- `AppSec::ContainerScanning`: Container Scanning code.
|
||||
- `AppSec::Dast`: DAST code.
|
||||
- `AppSec::DependencyScanning`: Dependency Scanning code.
|
||||
- `AppSec::Fuzzing::API`: API Fuzzing code.
|
||||
- `AppSec::Fuzzing::Coverage`: Coverage Fuzzing code.
|
||||
- `AppSec::Fuzzing`: Shared fuzzing code.
|
||||
- `AppSec::LicenseCompliance`: License Compliance code.
|
||||
- `AppSec::Sast`: SAST code.
|
||||
- `AppSec::SecretDetection`: Secret Detection code.
|
||||
- `AppSec::VulnMgmt`: Vulnerability Management code.
|
||||
|
||||
Most AppSec code does not conform to these namespace guidelines. When developing, make an effort
|
||||
to move existing code into the appropriate namespace whenever possible.
|
||||
<!-- This redirect file can be deleted after <2022-09-23>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
|
@ -174,7 +174,6 @@ See [database guidelines](database/index.md).
|
|||
## Domain-specific guides
|
||||
|
||||
- [CI/CD development documentation](cicd/index.md)
|
||||
- [AppSec development documentation](appsec/index.md)
|
||||
|
||||
## Technical Reference by Group
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ Please consider using a virtual machine to run GitLab.
|
|||
|
||||
### Redis versions
|
||||
|
||||
GitLab 13.0 and later requires Redis version 4.0 or higher.
|
||||
GitLab 13.0 and later requires Redis version 5.0 or higher.
|
||||
|
||||
Redis version 6.0 or higher is recommended, as this is what ships with
|
||||
[Omnibus GitLab](https://docs.gitlab.com/omnibus/) packages starting with GitLab 13.9.
|
||||
|
|
|
@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Scan execution policies **(ULTIMATE)**
|
||||
|
||||
> - Group-level security policies were [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4425) in GitLab 15.2 [with a flag](../../../administration/feature_flags.md) named `group_level_security_policies`. Disabled by default.
|
||||
> - Group-level security policies were [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4425) in GitLab 15.2 [with a flag](../../../administration/feature_flags.md) named `group_level_security_policies`. Enabled by default.
|
||||
|
||||
Group, sub-group, or project owners can use scan execution policies to require that security scans run on a specified
|
||||
schedule or with the project (or multiple projects if the policy is defined at a group or sub-group level) pipeline. Required scans are injected into the CI pipeline as new jobs
|
||||
|
|
|
@ -104,6 +104,7 @@ module API
|
|||
expose :ci_forward_deployment_enabled
|
||||
expose :ci_job_token_scope_enabled
|
||||
expose :ci_separated_caches
|
||||
expose :ci_opt_in_jwt
|
||||
expose :public_builds, as: :public_jobs
|
||||
expose :build_git_strategy, if: lambda { |project, options| options[:user_can_admin_project] } do |project, options|
|
||||
project.build_allow_git_fetch ? 'fetch' : 'clone'
|
||||
|
|
|
@ -4,12 +4,12 @@ return if Rails.env.production?
|
|||
|
||||
require 'pact/tasks/verification_task'
|
||||
|
||||
contracts = File.expand_path('../../spec/contracts', __dir__)
|
||||
contracts = File.expand_path('../../../spec/contracts', __dir__)
|
||||
provider = File.expand_path('provider', contracts)
|
||||
|
||||
# rubocop:disable Rails/RakeEnvironment
|
||||
namespace :contracts do
|
||||
namespace :mr do
|
||||
namespace :merge_requests do
|
||||
Pact::VerificationTask.new(:diffs_batch) do |pact|
|
||||
pact.uri(
|
||||
"#{contracts}/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_batch_endpoint.json",
|
||||
|
@ -33,14 +33,11 @@ namespace :contracts do
|
|||
end
|
||||
|
||||
desc 'Run all merge request contract tests'
|
||||
task 'test:merge_request', :contract_mr do |_t, arg|
|
||||
raise(ArgumentError, 'Merge request contract tests require contract_mr to be set') unless arg[:contract_mr]
|
||||
|
||||
ENV['CONTRACT_MR'] = arg[:contract_mr]
|
||||
errors = %w[metadata discussions diffs].each_with_object([]) do |task, err|
|
||||
task 'test:merge_requests', :contract_mr do |_t, arg|
|
||||
errors = %w[diffs_batch diffs_metadata discussions].each_with_object([]) do |task, err|
|
||||
Rake::Task["contracts:mr:pact:verify:#{task}"].execute
|
||||
rescue StandardError, SystemExit
|
||||
err << "contracts:mr:pact:verify:#{task}"
|
||||
err << "contracts:merge_requests:pact:verify:#{task}"
|
||||
end
|
||||
|
||||
raise StandardError, "Errors in tasks #{errors.join(', ')}" unless errors.empty?
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
return if Rails.env.production?
|
||||
|
||||
require 'pact/tasks/verification_task'
|
||||
|
||||
contracts = File.expand_path('../../../spec/contracts', __dir__)
|
||||
provider = File.expand_path('provider', contracts)
|
||||
|
||||
# rubocop:disable Rails/RakeEnvironment
|
||||
namespace :contracts do
|
||||
namespace :pipelines do
|
||||
Pact::VerificationTask.new(:get_list_project_pipelines) do |pact|
|
||||
pact.uri(
|
||||
"#{contracts}/contracts/project/pipeline/index/pipelines#index-get_list_project_pipelines.json",
|
||||
pact_helper: "#{provider}/pact_helpers/project/pipeline/get_list_project_pipelines_helper.rb"
|
||||
)
|
||||
end
|
||||
|
||||
desc 'Run all pipeline contract tests'
|
||||
task 'test:pipelines', :contract_mr do |_t, arg|
|
||||
errors = %w[get_list_project_pipelines].each_with_object([]) do |task, err|
|
||||
Rake::Task["contracts:pipelines:pact:verify:#{task}"].execute
|
||||
rescue StandardError, SystemExit
|
||||
err << "contracts:pipelines:pact:verify:#{task}"
|
||||
end
|
||||
|
||||
raise StandardError, "Errors in tasks #{errors.join(', ')}" unless errors.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Rails/RakeEnvironment
|
|
@ -17,6 +17,7 @@ module QA
|
|||
|
||||
base.view 'app/assets/javascripts/invite_members/components/group_select.vue' do
|
||||
element :group_select_dropdown_search_field
|
||||
element :group_select_dropdown_item
|
||||
end
|
||||
|
||||
base.view 'app/assets/javascripts/invite_members/components/members_token_select.vue' do
|
||||
|
@ -59,6 +60,8 @@ module QA
|
|||
within_element(:invite_members_modal_content) do
|
||||
click_button 'Select a group'
|
||||
|
||||
Support::Waiter.wait_until { has_element?(:group_select_dropdown_item) }
|
||||
|
||||
# Helps stabilize race condition with concurrent group API calls while searching
|
||||
# TODO: Replace with `fill_element :group_select_dropdown_search_field, group_name` when this bug is resolved: https://gitlab.com/gitlab-org/gitlab/-/issues/349379
|
||||
send_keys_to_element(:group_select_dropdown_search_field, group_name)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import { request } from 'axios';
|
||||
|
||||
export function getProjectPipelines(endpoint) {
|
||||
const { url } = endpoint;
|
||||
|
||||
return request({
|
||||
method: 'GET',
|
||||
baseURL: url,
|
||||
url: '/gitlab-org/gitlab-qa/-/pipelines.json',
|
||||
headers: { Accept: '*/*' },
|
||||
params: {
|
||||
scope: 'all',
|
||||
page: 1,
|
||||
},
|
||||
}).then((response) => response.data);
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
|
||||
import { Matchers } from '@pact-foundation/pact';
|
||||
import {
|
||||
URL,
|
||||
URL_PATH,
|
||||
PIPELINE_GROUPS,
|
||||
PIPELINE_LABELS,
|
||||
PIPELINE_SOURCES,
|
||||
PIPELINE_STATUSES,
|
||||
PIPELINE_TEXTS,
|
||||
USER_STATES,
|
||||
} from '../../../helpers/common_regex_patterns';
|
||||
|
||||
const body = {
|
||||
pipelines: Matchers.eachLike({
|
||||
id: Matchers.integer(564173401),
|
||||
iid: Matchers.integer(8197225),
|
||||
user: {
|
||||
id: Matchers.integer(1781152),
|
||||
username: Matchers.string('gitlab-bot'),
|
||||
name: Matchers.string('🤖 GitLab Bot 🤖'),
|
||||
state: Matchers.term({
|
||||
matcher: USER_STATES,
|
||||
generate: 'active',
|
||||
}),
|
||||
avatar_url: Matchers.term({
|
||||
matcher: URL,
|
||||
generate: 'https://gitlab.com/uploads/-/system/user/avatar/1516152/avatar.png',
|
||||
}),
|
||||
web_url: Matchers.term({
|
||||
matcher: URL,
|
||||
generate: 'https://gitlab.com/gitlab-bot',
|
||||
}),
|
||||
show_status: Matchers.boolean(false),
|
||||
path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-bot',
|
||||
}),
|
||||
},
|
||||
active: Matchers.boolean(true),
|
||||
source: Matchers.term({
|
||||
matcher: PIPELINE_SOURCES,
|
||||
generate: 'schedule',
|
||||
}),
|
||||
created_at: Matchers.iso8601DateTimeWithMillis('2022-06-11T00:05:21.558Z'),
|
||||
updated_at: Matchers.iso8601DateTimeWithMillis('2022-06-11T00:05:34.258Z'),
|
||||
path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/pipelines/561224401',
|
||||
}),
|
||||
flags: {
|
||||
stuck: Matchers.boolean(false),
|
||||
auto_devops: Matchers.boolean(false),
|
||||
merge_request: Matchers.boolean(false),
|
||||
yaml_errors: Matchers.boolean(false),
|
||||
retryable: Matchers.boolean(false),
|
||||
cancelable: Matchers.boolean(false),
|
||||
failure_reason: Matchers.boolean(false),
|
||||
detached_merge_request_pipeline: Matchers.boolean(false),
|
||||
merge_request_pipeline: Matchers.boolean(false),
|
||||
merge_train_pipeline: Matchers.boolean(false),
|
||||
latest: Matchers.boolean(true),
|
||||
},
|
||||
details: {
|
||||
status: {
|
||||
icon: Matchers.term({
|
||||
matcher: PIPELINE_STATUSES,
|
||||
generate: 'status_running',
|
||||
}),
|
||||
text: Matchers.term({
|
||||
matcher: PIPELINE_TEXTS,
|
||||
generate: 'running',
|
||||
}),
|
||||
label: Matchers.term({
|
||||
matcher: PIPELINE_LABELS,
|
||||
generate: 'running',
|
||||
}),
|
||||
group: Matchers.term({
|
||||
matcher: PIPELINE_GROUPS,
|
||||
generate: 'running',
|
||||
}),
|
||||
tooltip: Matchers.term({
|
||||
matcher: PIPELINE_LABELS,
|
||||
generate: 'passed',
|
||||
}),
|
||||
has_details: Matchers.boolean(true),
|
||||
details_path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/pipelines/566374401',
|
||||
}),
|
||||
illustration: null,
|
||||
favicon: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/assets/ci_favicons/favicon_status_running.png',
|
||||
}),
|
||||
},
|
||||
stages: Matchers.eachLike({
|
||||
name: Matchers.string('sync'),
|
||||
title: Matchers.string('sync: passed'),
|
||||
status: {
|
||||
icon: Matchers.term({
|
||||
matcher: PIPELINE_STATUSES,
|
||||
generate: 'status_success',
|
||||
}),
|
||||
text: Matchers.term({
|
||||
matcher: PIPELINE_TEXTS,
|
||||
generate: 'passed',
|
||||
}),
|
||||
label: Matchers.term({
|
||||
matcher: PIPELINE_LABELS,
|
||||
generate: 'passed',
|
||||
}),
|
||||
group: Matchers.term({
|
||||
matcher: PIPELINE_GROUPS,
|
||||
generate: 'success',
|
||||
}),
|
||||
tooltip: Matchers.term({
|
||||
matcher: PIPELINE_LABELS,
|
||||
generate: 'passed',
|
||||
}),
|
||||
has_details: Matchers.boolean(true),
|
||||
details_path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/pipelines/561174401#sync',
|
||||
}),
|
||||
illustration: null,
|
||||
favicon: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/assets/ci_favicons/favicon_status_success.png',
|
||||
}),
|
||||
},
|
||||
path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/pipelines/561124401#sync',
|
||||
}),
|
||||
dropdown_path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/pipelines/561174401/stage.json?stage=sync',
|
||||
}),
|
||||
}),
|
||||
duration: Matchers.integer(25),
|
||||
finished_at: Matchers.iso8601DateTimeWithMillis('2022-06-11T00:55:21.558Z'),
|
||||
name: Matchers.string('Pipeline'),
|
||||
manual_actions: Matchers.eachLike({
|
||||
name: Matchers.string('review-docs-deploy'),
|
||||
playable: Matchers.boolean(true),
|
||||
scheduled: Matchers.boolean(false),
|
||||
}),
|
||||
scheduled_actions: Matchers.eachLike({
|
||||
name: Matchers.string('review-docs-schedule'),
|
||||
playable: Matchers.boolean(true),
|
||||
scheduled: Matchers.boolean(false),
|
||||
}),
|
||||
},
|
||||
ref: {
|
||||
name: Matchers.string('master'),
|
||||
path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/commits/master',
|
||||
}),
|
||||
tag: Matchers.boolean(false),
|
||||
branch: Matchers.boolean(true),
|
||||
merge_request: Matchers.boolean(false),
|
||||
},
|
||||
commit: {
|
||||
id: Matchers.string('e6d797385144b955c6d4ecfa00e9656dc33efd2b'),
|
||||
short_id: Matchers.string('e6d79738'),
|
||||
created_at: Matchers.iso8601DateTimeWithMillis('2022-06-10T22:02:10.000+00:00'),
|
||||
parent_ids: Matchers.eachLike(Matchers.string('3b0e053a24958174eaa7e3b183c7263432890d1c')),
|
||||
title: Matchers.string("Merge branch 'ee-test' into 'master'"),
|
||||
message: Matchers.string("Merge branch 'ee-test' into 'master'\nThis is a test."),
|
||||
author_name: Matchers.string('John Doe'),
|
||||
author_email: Matchers.email('jdoe@gitlab.com'),
|
||||
authored_date: Matchers.iso8601DateTimeWithMillis('2022-06-10T22:02:10.000+00:00'),
|
||||
committer_name: Matchers.string('John Doe'),
|
||||
committer_email: Matchers.email('jdoe@gitlab.com'),
|
||||
committed_date: Matchers.iso8601DateTimeWithMillis('2022-06-10T22:02:10.000+00:00'),
|
||||
trailers: {},
|
||||
web_url: Matchers.term({
|
||||
matcher: URL,
|
||||
generate: 'https://gitlab.com/gitlab-org/gitlab/-/commit/f559253c514d9ab707c66e',
|
||||
}),
|
||||
author: null,
|
||||
author_gravatar_url: Matchers.term({
|
||||
matcher: URL,
|
||||
generate:
|
||||
'https://secure.gravatar.com/avatar/d85e45af29611ac2c1395e3c3d6ec5d6?s=80\u0026d=identicon',
|
||||
}),
|
||||
commit_url: Matchers.term({
|
||||
matcher: URL,
|
||||
generate:
|
||||
'https://gitlab.com/gitlab-org/gitlab/-/commit/dc7522f559253c514d9ab707c66e7a1026abca5a',
|
||||
}),
|
||||
commit_path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab/-/commit/dc7522f559253c514d9ab707c66e7a1026abca5a',
|
||||
}),
|
||||
},
|
||||
project: {
|
||||
id: Matchers.integer(253964),
|
||||
name: Matchers.string('GitLab'),
|
||||
full_path: Matchers.term({
|
||||
matcher: URL_PATH,
|
||||
generate: '/gitlab-org/gitlab',
|
||||
}),
|
||||
full_name: Matchers.string('GitLab.org / GitLab'),
|
||||
},
|
||||
triggered_by: null,
|
||||
triggered: [],
|
||||
}),
|
||||
count: {
|
||||
all: Matchers.string('1,000+'),
|
||||
},
|
||||
};
|
||||
|
||||
const ProjectPipelines = {
|
||||
body: Matchers.extractPayload(body),
|
||||
|
||||
success: {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body,
|
||||
},
|
||||
|
||||
request: {
|
||||
uponReceiving: 'a request for a list of project pipelines',
|
||||
withRequest: {
|
||||
method: 'GET',
|
||||
path: '/gitlab-org/gitlab-qa/-/pipelines.json',
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
},
|
||||
query: 'scope=all&page=1',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export { ProjectPipelines };
|
||||
|
||||
/* eslint-enable @gitlab/require-i18n-strings */
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Important note: These regex patterns need to use Ruby format because the underlying Pact mock service is written in Ruby.
|
||||
*/
|
||||
export const URL = '^(http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$';
|
||||
export const URL_PATH = '^/[a-zA-Z0-9#-=?_]+$';
|
||||
|
||||
// Pipelines
|
||||
export const PIPELINE_GROUPS =
|
||||
'^(canceled|created|failed|manual|pending|preparing|running|scheduled|skipped|success|success_warning|waiting-for-resource)$';
|
||||
export const PIPELINE_LABELS =
|
||||
'^(canceled|created|delayed|failed|manual action|passed|pending|preparing|running|skipped|passed with warnings|waiting for resource)$';
|
||||
export const PIPELINE_SOURCES =
|
||||
'^(push|web|trigger|schedule|api|external|pipeline|chat|webide|merge_request_event|external_pull_request_event|parent_pipeline|ondemand_dast_scan|ondemand_dast_validation)$';
|
||||
export const PIPELINE_STATUSES =
|
||||
'^status_(canceled|created|failed|manual|pending|preparing|running|scheduled|skipped|success|warning)$';
|
||||
export const PIPELINE_TEXTS =
|
||||
'^(canceled|created|delayed|failed|manual|passed|pending|preparing|running|skipped|waiting)$';
|
||||
|
||||
// Users
|
||||
export const USER_STATES = '^(active|blocked)$';
|
|
@ -0,0 +1,44 @@
|
|||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
|
||||
import { pactWith } from 'jest-pact';
|
||||
|
||||
import { ProjectPipelines } from '../../../fixtures/project/pipeline/get_list_project_pipelines.fixture';
|
||||
import { getProjectPipelines } from '../../../endpoints/project/pipelines';
|
||||
|
||||
const CONSUMER_NAME = 'Pipelines#index';
|
||||
const CONSUMER_LOG = '../logs/consumer.log';
|
||||
const CONTRACT_DIR = '../contracts/project/pipeline/index';
|
||||
const PROVIDER_NAME = 'GET List project pipelines';
|
||||
|
||||
// API endpoint: /pipelines.json
|
||||
pactWith(
|
||||
{
|
||||
consumer: CONSUMER_NAME,
|
||||
provider: PROVIDER_NAME,
|
||||
log: CONSUMER_LOG,
|
||||
dir: CONTRACT_DIR,
|
||||
},
|
||||
|
||||
(provider) => {
|
||||
describe(PROVIDER_NAME, () => {
|
||||
beforeEach(() => {
|
||||
const interaction = {
|
||||
state: 'a few pipelines for a project exists',
|
||||
...ProjectPipelines.request,
|
||||
willRespondWith: ProjectPipelines.success,
|
||||
};
|
||||
provider.addInteraction(interaction);
|
||||
});
|
||||
|
||||
it('returns a successful body', () => {
|
||||
return getProjectPipelines({
|
||||
url: provider.mockService.baseUrl,
|
||||
}).then((pipelines) => {
|
||||
expect(pipelines).toEqual(ProjectPipelines.body);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/* eslint-enable @gitlab/require-i18n-strings */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,472 @@
|
|||
{
|
||||
"consumer": {
|
||||
"name": "Pipelines#index"
|
||||
},
|
||||
"provider": {
|
||||
"name": "GET List project pipelines"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"description": "a request for a list of project pipelines",
|
||||
"providerState": "a few pipelines for a project exists",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"path": "/gitlab-org/gitlab-qa/-/pipelines.json",
|
||||
"query": "scope=all&page=1",
|
||||
"headers": {
|
||||
"Accept": "*/*"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": {
|
||||
"pipelines": [
|
||||
{
|
||||
"id": 564173401,
|
||||
"iid": 8197225,
|
||||
"user": {
|
||||
"id": 1781152,
|
||||
"username": "gitlab-bot",
|
||||
"name": "🤖 GitLab Bot 🤖",
|
||||
"state": "active",
|
||||
"avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/1516152/avatar.png",
|
||||
"web_url": "https://gitlab.com/gitlab-bot",
|
||||
"show_status": false,
|
||||
"path": "/gitlab-bot"
|
||||
},
|
||||
"active": true,
|
||||
"source": "schedule",
|
||||
"created_at": "2022-06-11T00:05:21.558Z",
|
||||
"updated_at": "2022-06-11T00:05:34.258Z",
|
||||
"path": "/gitlab-org/gitlab/-/pipelines/561224401",
|
||||
"flags": {
|
||||
"stuck": false,
|
||||
"auto_devops": false,
|
||||
"merge_request": false,
|
||||
"yaml_errors": false,
|
||||
"retryable": false,
|
||||
"cancelable": false,
|
||||
"failure_reason": false,
|
||||
"detached_merge_request_pipeline": false,
|
||||
"merge_request_pipeline": false,
|
||||
"merge_train_pipeline": false,
|
||||
"latest": true
|
||||
},
|
||||
"details": {
|
||||
"status": {
|
||||
"icon": "status_running",
|
||||
"text": "running",
|
||||
"label": "running",
|
||||
"group": "running",
|
||||
"tooltip": "passed",
|
||||
"has_details": true,
|
||||
"details_path": "/gitlab-org/gitlab/-/pipelines/566374401",
|
||||
"illustration": null,
|
||||
"favicon": "/assets/ci_favicons/favicon_status_running.png"
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "sync",
|
||||
"title": "sync: passed",
|
||||
"status": {
|
||||
"icon": "status_success",
|
||||
"text": "passed",
|
||||
"label": "passed",
|
||||
"group": "success",
|
||||
"tooltip": "passed",
|
||||
"has_details": true,
|
||||
"details_path": "/gitlab-org/gitlab/-/pipelines/561174401#sync",
|
||||
"illustration": null,
|
||||
"favicon": "/assets/ci_favicons/favicon_status_success.png"
|
||||
},
|
||||
"path": "/gitlab-org/gitlab/-/pipelines/561124401#sync",
|
||||
"dropdown_path": "/gitlab-org/gitlab/-/pipelines/561174401/stage.json?stage=sync"
|
||||
}
|
||||
],
|
||||
"duration": 25,
|
||||
"finished_at": "2022-06-11T00:55:21.558Z",
|
||||
"name": "Pipeline",
|
||||
"manual_actions": [
|
||||
{
|
||||
"name": "review-docs-deploy",
|
||||
"playable": true,
|
||||
"scheduled": false
|
||||
}
|
||||
],
|
||||
"scheduled_actions": [
|
||||
{
|
||||
"name": "review-docs-schedule",
|
||||
"playable": true,
|
||||
"scheduled": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"ref": {
|
||||
"name": "master",
|
||||
"path": "/gitlab-org/gitlab/-/commits/master",
|
||||
"tag": false,
|
||||
"branch": true,
|
||||
"merge_request": false
|
||||
},
|
||||
"commit": {
|
||||
"id": "e6d797385144b955c6d4ecfa00e9656dc33efd2b",
|
||||
"short_id": "e6d79738",
|
||||
"created_at": "2022-06-10T22:02:10.000+00:00",
|
||||
"parent_ids": [
|
||||
"3b0e053a24958174eaa7e3b183c7263432890d1c"
|
||||
],
|
||||
"title": "Merge branch 'ee-test' into 'master'",
|
||||
"message": "Merge branch 'ee-test' into 'master'\nThis is a test.",
|
||||
"author_name": "John Doe",
|
||||
"author_email": "jdoe@gitlab.com",
|
||||
"authored_date": "2022-06-10T22:02:10.000+00:00",
|
||||
"committer_name": "John Doe",
|
||||
"committer_email": "jdoe@gitlab.com",
|
||||
"committed_date": "2022-06-10T22:02:10.000+00:00",
|
||||
"trailers": {
|
||||
},
|
||||
"web_url": "https://gitlab.com/gitlab-org/gitlab/-/commit/f559253c514d9ab707c66e",
|
||||
"author": null,
|
||||
"author_gravatar_url": "https://secure.gravatar.com/avatar/d85e45af29611ac2c1395e3c3d6ec5d6?s=80&d=identicon",
|
||||
"commit_url": "https://gitlab.com/gitlab-org/gitlab/-/commit/dc7522f559253c514d9ab707c66e7a1026abca5a",
|
||||
"commit_path": "/gitlab-org/gitlab/-/commit/dc7522f559253c514d9ab707c66e7a1026abca5a"
|
||||
},
|
||||
"project": {
|
||||
"id": 253964,
|
||||
"name": "GitLab",
|
||||
"full_path": "/gitlab-org/gitlab",
|
||||
"full_name": "GitLab.org / GitLab"
|
||||
},
|
||||
"triggered_by": null,
|
||||
"triggered": [
|
||||
|
||||
]
|
||||
}
|
||||
],
|
||||
"count": {
|
||||
"all": "1,000+"
|
||||
}
|
||||
},
|
||||
"matchingRules": {
|
||||
"$.body.pipelines": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.pipelines[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].iid": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].user.id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].user.username": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].user.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].user.state": {
|
||||
"match": "regex",
|
||||
"regex": "^(active|blocked)$"
|
||||
},
|
||||
"$.body.pipelines[*].user.avatar_url": {
|
||||
"match": "regex",
|
||||
"regex": "^(http|https):\\/\\/[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"
|
||||
},
|
||||
"$.body.pipelines[*].user.web_url": {
|
||||
"match": "regex",
|
||||
"regex": "^(http|https):\\/\\/[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"
|
||||
},
|
||||
"$.body.pipelines[*].user.show_status": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].user.path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].active": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].source": {
|
||||
"match": "regex",
|
||||
"regex": "^(push|web|trigger|schedule|api|external|pipeline|chat|webide|merge_request_event|external_pull_request_event|parent_pipeline|ondemand_dast_scan|ondemand_dast_validation)$"
|
||||
},
|
||||
"$.body.pipelines[*].created_at": {
|
||||
"match": "regex",
|
||||
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
|
||||
},
|
||||
"$.body.pipelines[*].updated_at": {
|
||||
"match": "regex",
|
||||
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
|
||||
},
|
||||
"$.body.pipelines[*].path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].flags.stuck": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.auto_devops": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.merge_request": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.yaml_errors": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.retryable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.cancelable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.failure_reason": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.detached_merge_request_pipeline": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.merge_request_pipeline": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.merge_train_pipeline": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].flags.latest": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.icon": {
|
||||
"match": "regex",
|
||||
"regex": "^status_(canceled|created|failed|manual|pending|preparing|running|scheduled|skipped|success|warning)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.text": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|delayed|failed|manual|passed|pending|preparing|running|skipped|waiting)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.label": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|delayed|failed|manual action|passed|pending|preparing|running|skipped|passed with warnings|waiting for resource)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.group": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|failed|manual|pending|preparing|running|scheduled|skipped|success|success_warning|waiting-for-resource)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.tooltip": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|delayed|failed|manual action|passed|pending|preparing|running|skipped|passed with warnings|waiting for resource)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.has_details": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.details_path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].details.status.favicon": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].title": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.icon": {
|
||||
"match": "regex",
|
||||
"regex": "^status_(canceled|created|failed|manual|pending|preparing|running|scheduled|skipped|success|warning)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.text": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|delayed|failed|manual|passed|pending|preparing|running|skipped|waiting)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.label": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|delayed|failed|manual action|passed|pending|preparing|running|skipped|passed with warnings|waiting for resource)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.group": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|failed|manual|pending|preparing|running|scheduled|skipped|success|success_warning|waiting-for-resource)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.tooltip": {
|
||||
"match": "regex",
|
||||
"regex": "^(canceled|created|delayed|failed|manual action|passed|pending|preparing|running|skipped|passed with warnings|waiting for resource)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.has_details": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.details_path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].status.favicon": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].details.stages[*].dropdown_path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].details.duration": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.finished_at": {
|
||||
"match": "regex",
|
||||
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
|
||||
},
|
||||
"$.body.pipelines[*].details.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.manual_actions": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.pipelines[*].details.manual_actions[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.manual_actions[*].name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.manual_actions[*].playable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.manual_actions[*].scheduled": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.scheduled_actions": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.pipelines[*].details.scheduled_actions[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.scheduled_actions[*].name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.scheduled_actions[*].playable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].details.scheduled_actions[*].scheduled": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].ref.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].ref.path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].ref.tag": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].ref.branch": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].ref.merge_request": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.short_id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.created_at": {
|
||||
"match": "regex",
|
||||
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.parent_ids": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.pipelines[*].commit.parent_ids[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.parent_ids[*]": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.title": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.message": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.author_name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.author_email": {
|
||||
"match": "regex",
|
||||
"regex": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.authored_date": {
|
||||
"match": "regex",
|
||||
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.committer_name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].commit.committer_email": {
|
||||
"match": "regex",
|
||||
"regex": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.committed_date": {
|
||||
"match": "regex",
|
||||
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.web_url": {
|
||||
"match": "regex",
|
||||
"regex": "^(http|https):\\/\\/[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.author_gravatar_url": {
|
||||
"match": "regex",
|
||||
"regex": "^(http|https):\\/\\/[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.commit_url": {
|
||||
"match": "regex",
|
||||
"regex": "^(http|https):\\/\\/[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"
|
||||
},
|
||||
"$.body.pipelines[*].commit.commit_path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].project.id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].project.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pipelines[*].project.full_path": {
|
||||
"match": "regex",
|
||||
"regex": "^\\/[a-zA-Z0-9#-=?_]+$"
|
||||
},
|
||||
"$.body.pipelines[*].project.full_name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.count.all": {
|
||||
"match": "type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../../spec_helper'
|
||||
require_relative '../../../states/project/pipeline/pipelines_state'
|
||||
|
||||
module Provider
|
||||
module GetListProjectPipelinesHelper
|
||||
Pact.service_provider "GET List project pipelines" do
|
||||
app { Environments::Test.app }
|
||||
|
||||
honours_pact_with 'Pipelines#index' do
|
||||
pact_uri '../contracts/project/project/pipeline/index/pipelines#index-get_list_project_pipelines.json'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Pact.provider_states_for "Pipelines#index" do
|
||||
provider_state "a few pipelines for a project exists" do
|
||||
set_up do
|
||||
user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
|
||||
namespace = create(:namespace, name: 'gitlab-org')
|
||||
project = create(:project, :repository, name: 'gitlab-qa', namespace: namespace, creator: user)
|
||||
scheduled_job = create(:ci_build, :scheduled)
|
||||
manual_job = create(:ci_build, :manual)
|
||||
|
||||
project.add_maintainer(user)
|
||||
|
||||
create(
|
||||
:ci_pipeline,
|
||||
:with_job,
|
||||
:success,
|
||||
project: project,
|
||||
user: user,
|
||||
duration: 10,
|
||||
finished_at: '2022-06-01T02:47:31.432Z',
|
||||
builds: [scheduled_job, manual_job]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -100,6 +100,7 @@ ci_cd_settings:
|
|||
forward_deployment_enabled: ci_forward_deployment_enabled
|
||||
job_token_scope_enabled: ci_job_token_scope_enabled
|
||||
separated_caches: ci_separated_caches
|
||||
opt_in_jwt: ci_opt_in_jwt
|
||||
|
||||
build_import_state: # import_state
|
||||
unexposed_attributes:
|
||||
|
|
Loading…
Reference in New Issue