Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
60028378dd
commit
6728ed6fe2
76 changed files with 1725 additions and 67 deletions
|
@ -9,3 +9,4 @@
|
|||
/sitespeed-result/
|
||||
/fixtures/**/*.graphql
|
||||
spec/fixtures/**/*.graphql
|
||||
**/contracts/consumer/
|
||||
|
|
|
@ -16,7 +16,6 @@ Database/MultipleDatabases:
|
|||
- lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
|
||||
- lib/gitlab/database.rb
|
||||
- lib/gitlab/health_checks/db_check.rb
|
||||
- lib/gitlab/import_export/group/relation_tree_restorer.rb
|
||||
- lib/gitlab/seeder.rb
|
||||
- spec/db/schema_spec.rb
|
||||
- spec/initializers/database_config_spec.rb
|
||||
|
|
|
@ -431,7 +431,7 @@ export default {
|
|||
class="js-ide-edit-blob"
|
||||
data-qa-selector="edit_in_ide_button"
|
||||
>
|
||||
{{ __('Edit in Web IDE') }}
|
||||
{{ __('Open in Web IDE') }}
|
||||
</gl-dropdown-item>
|
||||
</template>
|
||||
|
||||
|
|
14
app/events/repositories/keep_around_refs_created_event.rb
Normal file
14
app/events/repositories/keep_around_refs_created_event.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Repositories
|
||||
class KeepAroundRefsCreatedEvent < ::Gitlab::EventStore::Event
|
||||
def schema
|
||||
{
|
||||
'type' => 'object',
|
||||
'properties' => {
|
||||
'project_id' => { 'type' => 'integer' }
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -37,14 +37,14 @@ class WebHook < ApplicationRecord
|
|||
!temporarily_disabled? && !permanently_disabled?
|
||||
end
|
||||
|
||||
def temporarily_disabled?
|
||||
return false unless web_hooks_disable_failed?
|
||||
def temporarily_disabled?(ignore_flag: false)
|
||||
return false unless ignore_flag || web_hooks_disable_failed?
|
||||
|
||||
disabled_until.present? && disabled_until >= Time.current
|
||||
end
|
||||
|
||||
def permanently_disabled?
|
||||
return false unless web_hooks_disable_failed?
|
||||
def permanently_disabled?(ignore_flag: false)
|
||||
return false unless ignore_flag || web_hooks_disable_failed?
|
||||
|
||||
recent_failures > FAILURE_THRESHOLD
|
||||
end
|
||||
|
@ -106,6 +106,13 @@ class WebHook < ApplicationRecord
|
|||
save(validate: false)
|
||||
end
|
||||
|
||||
def active_state(ignore_flag: false)
|
||||
return :permanently_disabled if permanently_disabled?(ignore_flag: ignore_flag)
|
||||
return :temporarily_disabled if temporarily_disabled?(ignore_flag: ignore_flag)
|
||||
|
||||
:enabled
|
||||
end
|
||||
|
||||
# @return [Boolean] Whether or not the WebHook is currently throttled.
|
||||
def rate_limited?
|
||||
return false unless rate_limit
|
||||
|
|
|
@ -194,6 +194,10 @@ class ProjectPolicy < BasePolicy
|
|||
condition(:"#{f}_disabled", score: 32) { !access_allowed_to?(f.to_sym) }
|
||||
end
|
||||
|
||||
condition(:project_runner_registration_allowed) do
|
||||
Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?('project')
|
||||
end
|
||||
|
||||
# `:read_project` may be prevented in EE, but `:read_project_for_iids` should
|
||||
# not.
|
||||
rule { guest | admin }.enable :read_project_for_iids
|
||||
|
@ -230,6 +234,8 @@ class ProjectPolicy < BasePolicy
|
|||
enable :set_emails_disabled
|
||||
enable :set_show_default_award_emojis
|
||||
enable :set_warn_about_potentially_unwanted_characters
|
||||
|
||||
enable :register_project_runners
|
||||
end
|
||||
|
||||
rule { can?(:guest_access) }.policy do
|
||||
|
@ -453,6 +459,7 @@ class ProjectPolicy < BasePolicy
|
|||
enable :update_freeze_period
|
||||
enable :destroy_freeze_period
|
||||
enable :admin_feature_flags_client
|
||||
enable :register_project_runners
|
||||
enable :update_runners_registration_token
|
||||
enable :admin_project_google_cloud
|
||||
end
|
||||
|
@ -727,6 +734,10 @@ class ProjectPolicy < BasePolicy
|
|||
enable :access_security_and_compliance
|
||||
end
|
||||
|
||||
rule { ~admin & ~project_runner_registration_allowed }.policy do
|
||||
prevent :register_project_runners
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_is_user?
|
||||
|
|
|
@ -23,11 +23,11 @@ module Issues
|
|||
|
||||
def header_to_value_hash
|
||||
{
|
||||
'Title' => 'title',
|
||||
'Description' => 'description',
|
||||
'Issue ID' => 'iid',
|
||||
'URL' => -> (issue) { issue_url(issue) },
|
||||
'Title' => 'title',
|
||||
'State' => -> (issue) { issue.closed? ? 'Closed' : 'Open' },
|
||||
'Description' => 'description',
|
||||
'Author' => 'author_name',
|
||||
'Author Username' => -> (issue) { issue.author&.username },
|
||||
'Assignee' => -> (issue) { issue.assignees.map(&:name).join(', ') },
|
||||
|
|
|
@ -13,11 +13,11 @@ module MergeRequests
|
|||
|
||||
def header_to_value_hash
|
||||
{
|
||||
'Title' => 'title',
|
||||
'Description' => 'description',
|
||||
'MR IID' => 'iid',
|
||||
'URL' => -> (merge_request) { merge_request_url(merge_request) },
|
||||
'Title' => 'title',
|
||||
'State' => 'state',
|
||||
'Description' => 'description',
|
||||
'Source Branch' => 'source_branch',
|
||||
'Target Branch' => 'target_branch',
|
||||
'Source Project ID' => 'source_project_id',
|
||||
|
|
|
@ -12,8 +12,9 @@ module WebHooks
|
|||
|
||||
def initialize(hook:, log_data:, response_category:)
|
||||
@hook = hook
|
||||
@log_data = log_data
|
||||
@log_data = log_data.transform_keys(&:to_sym)
|
||||
@response_category = response_category
|
||||
@prev_state = hook.active_state(ignore_flag: true)
|
||||
end
|
||||
|
||||
def execute
|
||||
|
@ -24,7 +25,7 @@ module WebHooks
|
|||
private
|
||||
|
||||
def log_execution
|
||||
WebHookLog.create!(web_hook: hook, **log_data.transform_keys(&:to_sym))
|
||||
WebHookLog.create!(web_hook: hook, **log_data)
|
||||
end
|
||||
|
||||
# Perform this operation within an `Gitlab::ExclusiveLease` lock to make it
|
||||
|
@ -41,11 +42,36 @@ module WebHooks
|
|||
when :failed
|
||||
hook.failed!
|
||||
end
|
||||
|
||||
log_state_change
|
||||
end
|
||||
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
|
||||
raise if raise_lock_error?
|
||||
end
|
||||
|
||||
def log_state_change
|
||||
new_state = hook.active_state(ignore_flag: true)
|
||||
|
||||
return if @prev_state == new_state
|
||||
|
||||
Gitlab::AuthLogger.info(
|
||||
message: 'WebHook change active_state',
|
||||
# identification
|
||||
hook_id: hook.id,
|
||||
hook_type: hook.type,
|
||||
project_id: hook.project_id,
|
||||
group_id: hook.group_id,
|
||||
# relevant data
|
||||
prev_state: @prev_state,
|
||||
new_state: new_state,
|
||||
duration: log_data[:execution_duration],
|
||||
response_status: log_data[:response_status],
|
||||
recent_hook_failures: hook.recent_failures,
|
||||
# context
|
||||
**Gitlab::ApplicationContext.current
|
||||
)
|
||||
end
|
||||
|
||||
def lock_name
|
||||
"web_hooks:update_hook_failure_state:#{hook.id}"
|
||||
end
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
.content_list
|
||||
.loading
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'md')
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
.js-groups-list-holder
|
||||
#js-groups-tree{ data: { hide_projects: 'true', endpoint: dashboard_groups_path(format: :json), path: dashboard_groups_path, form_sel: 'form#group-filter-form', filter_sel: '.js-groups-list-filter', holder_sel: '.js-groups-list-holder', dropdown_sel: '.js-group-filter-dropdown-wrap' } }
|
||||
.loading-container.text-center.prepend-top-20
|
||||
.gl-spinner.gl-spinner-md
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
.content_list
|
||||
.loading
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'md')
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
|
||||
%ul.content-list{ data: { hide_projects: 'false', group_id: group.id, path: group_path(group) } }
|
||||
.js-groups-list-holder
|
||||
.loading-container.text-center.prepend-top-20
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'md', css_class: 'gl-mt-6')
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
- if Feature.enabled?(:runner_list_group_view_vue_ui, @group, default_enabled: :yaml)
|
||||
.gl-card.gl-px-8.gl-py-6.gl-line-height-20
|
||||
.gl-card-body.gl-display-flex{ :class => "gl-p-0!" }
|
||||
.gl-banner-illustration
|
||||
= image_tag('illustrations/rocket-launch-md.svg', alt: s_('Runners|Rocket launch illustration'))
|
||||
.gl-banner-content
|
||||
%h1.gl-banner-title
|
||||
= s_('Runners|New group runners view')
|
||||
%p
|
||||
= s_('Runners|The new view gives you more space and better visibility into your fleet of runners.')
|
||||
%a.btn.btn-confirm.btn-md.gl-button{ :href => group_runners_path(@group) }
|
||||
%span.gl-button-text
|
||||
= s_('Runners|Take me there!')
|
||||
|
||||
= render 'shared/runners/runner_description'
|
||||
|
||||
%hr
|
||||
|
|
|
@ -9,5 +9,5 @@
|
|||
|
||||
#ide.ide-loading{ data: ide_data }
|
||||
.text-center
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'md')
|
||||
%h2.clgray= _('Loading the GitLab IDE...')
|
||||
|
|
|
@ -11,4 +11,4 @@
|
|||
|
||||
.content_list.project-activity{ :"data-href" => activity_project_path(@project) }
|
||||
.loading
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'md')
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
|
||||
.mr-loading-status
|
||||
.loading.hide
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'lg')
|
||||
|
||||
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch
|
||||
|
||||
|
|
|
@ -16,5 +16,4 @@
|
|||
|
||||
- if @commit
|
||||
.network-graph.gl-bg-white.gl-overflow-scroll.gl-overflow-x-hidden{ data: { url: @url, commit_url: @commit_url, ref: @ref, commit_id: @commit.id } }
|
||||
.text-center.gl-mt-3
|
||||
.gl-spinner.gl-spinner-md
|
||||
= gl_loading_icon(size: 'md', css_class: 'gl-mt-3')
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
= _('Specific runners')
|
||||
|
||||
.bs-callout.help-callout
|
||||
- if valid_runner_registrars.include?('project')
|
||||
- if can?(current_user, :register_project_runners, @project)
|
||||
= _('These runners are specific to this project.')
|
||||
- if params[:ci_runner_templates]
|
||||
%hr
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
%strong.fly-out-top-item-name
|
||||
= sidebar_menu.title
|
||||
- if sidebar_menu.has_pill?
|
||||
%span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
|
||||
= gl_badge_tag({ variant: :info, size: :sm }, { class: "count fly-out-badge #{sidebar_menu.pill_html_options[:class]}" }) do
|
||||
= number_with_delimiter(sidebar_menu.pill_count)
|
||||
|
||||
- if sidebar_menu.has_renderable_items?
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: issues_full_text_search
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71913
|
||||
rollout_issue_url:
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354784
|
||||
milestone: '14.5'
|
||||
type: development
|
||||
group: group::project management
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: source_editor_toolbar
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82304
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354748
|
||||
milestone: '14.9'
|
||||
type: development
|
||||
group: group::editor
|
||||
default_enabled: false
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddCommentToDeploymentApprovals < Gitlab::Database::Migration[1.0]
|
||||
# rubocop:disable Migration/AddLimitToTextColumns
|
||||
# limit is added in 20220303191047_add_text_limit_to_deployment_approvals_comment
|
||||
def change
|
||||
add_column :deployment_approvals, :comment, :text
|
||||
end
|
||||
# rubocop:enable Migration/AddLimitToTextColumns
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddTextLimitToDeploymentApprovalsComment < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_text_limit :deployment_approvals, :comment, 255
|
||||
end
|
||||
|
||||
def down
|
||||
remove_text_limit :deployment_approvals, :comment
|
||||
end
|
||||
end
|
1
db/schema_migrations/20220303190555
Normal file
1
db/schema_migrations/20220303190555
Normal file
|
@ -0,0 +1 @@
|
|||
f8fa8b83da24bf98c97447a2940c8ca801532c80395b6a65c11f83515f811652
|
1
db/schema_migrations/20220303191047
Normal file
1
db/schema_migrations/20220303191047
Normal file
|
@ -0,0 +1 @@
|
|||
19566152e16a92263dd5dcfd66299e3b9d8b82acd4edb4bba21f6b9b06fc8070
|
|
@ -14264,7 +14264,9 @@ CREATE TABLE deployment_approvals (
|
|||
user_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
status smallint NOT NULL
|
||||
status smallint NOT NULL,
|
||||
comment text,
|
||||
CONSTRAINT check_e2eb6a17d8 CHECK ((char_length(comment) <= 255))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE deployment_approvals_id_seq
|
||||
|
|
|
@ -465,9 +465,10 @@ POST /projects/:id/deployments/:deployment_id/approval
|
|||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
|
||||
| `deployment_id` | integer | yes | The ID of the deployment. |
|
||||
| `status` | string | yes | The status of the approval (either `approved` or `rejected`). |
|
||||
| `comment` | string | no | A comment to go with the approval |
|
||||
|
||||
```shell
|
||||
curl --data "status=approved" \
|
||||
curl --data "status=approved&comment=Looks good to me" \
|
||||
--header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/1/approval"
|
||||
```
|
||||
|
||||
|
@ -484,6 +485,7 @@ Example response:
|
|||
"web_url": "http://localhost:3000/root"
|
||||
},
|
||||
"status": "approved",
|
||||
"created_at": "2022-02-24T20:22:30.097Z"
|
||||
"created_at": "2022-02-24T20:22:30.097Z",
|
||||
"comment":"Looks good to me"
|
||||
}
|
||||
```
|
||||
|
|
|
@ -89,7 +89,7 @@ Using the [Deployments API](../../api/deployments.md#approve-or-reject-a-blocked
|
|||
Example:
|
||||
|
||||
```shell
|
||||
curl --data "status=approved" \
|
||||
curl --data "status=approved&comment=Looks good to me" \
|
||||
--header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/1/approval"
|
||||
```
|
||||
|
||||
|
|
|
@ -47,10 +47,7 @@ To implement tracking for HAML or Vue templates, add a [`data-track` attribute](
|
|||
The following example shows `data-track-*` attributes assigned to a button:
|
||||
|
||||
```haml
|
||||
%button.btn{ data: { track: { action: "click_button", label: "template_preview", property: "my-template" } } }
|
||||
|
||||
// or
|
||||
// %button.btn{ data: { track_action: "click_button", track_label: "template_preview", track_property: "my-template" } }
|
||||
%button.btn{ data: { track_action: "click_button", track_label: "template_preview", track_property: "my-template" } }
|
||||
```
|
||||
|
||||
```html
|
||||
|
|
|
@ -12,16 +12,16 @@ each security partner:
|
|||
|
||||
<!-- vale gitlab.Spelling = NO -->
|
||||
|
||||
- [Accurics](https://readme.accurics.com/1409/)
|
||||
- [Anchore](https://docs.anchore.com/current/docs/using/integration/ci_cd/gitlab/)
|
||||
- [Bridgecrew](https://docs.bridgecrew.io/docs/integrate-with-gitlab-self-managed)
|
||||
- [Checkmarx](https://checkmarx.atlassian.net/wiki/spaces/SD/pages/1929937052/GitLab+Integration)
|
||||
- [Deepfactor](https://docs.deepfactor.io/hc/en-us/articles/1500008981941)
|
||||
- [GrammaTech](https://www.grammatech.com/codesonar-gitlab-integration)
|
||||
- [Indeni](https://cloudrail.app/doc/integrate-with-ci-cd/gitlab-instructions/)
|
||||
- [Indeni](https://docs.cloudrail.app/#/integrations/gitlab)
|
||||
- [JScrambler](https://docs.jscrambler.com/code-integrity/documentation/gitlab-ci-integration)
|
||||
- [Semgrep](https://semgrep.dev/for/gitlab)
|
||||
- [StackHawk](https://docs.stackhawk.com/continuous-integration/gitlab.html)
|
||||
- [Tenable](https://docs.tenable.com/tenableio/Content/ContainerSecurity/GetStarted.htm)
|
||||
- [Venafi](https://marketplace.venafi.com/details/gitlab-ci-cd/)
|
||||
- [Veracode](https://community.veracode.com/s/knowledgeitem/gitlab-ci-MCEKSYPRWL35BRTGOVI55SK5RI4A)
|
||||
- [WhiteSource](https://www.whitesourcesoftware.com/gitlab/)
|
||||
|
|
|
@ -9,9 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
To enable the Twitter OmniAuth provider you must register your application with
|
||||
Twitter. Twitter generates a client ID and secret key for you to use.
|
||||
|
||||
1. Sign in to [Twitter Application Management](https://developer.twitter.com/apps).
|
||||
1. Sign in to [Twitter Application Management](https://apps.twitter.com).
|
||||
|
||||
1. Select "Create new app"
|
||||
1. Select "Create new app".
|
||||
|
||||
1. Fill in the application details.
|
||||
- Name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or
|
||||
|
|
|
@ -408,7 +408,7 @@ If you are using [EGit](https://www.eclipse.org/egit/), you can [add your SSH ke
|
|||
## Use SSH on Microsoft Windows
|
||||
|
||||
If you're running Windows 10, you can either use the [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install)
|
||||
with [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install-win10#update-to-wsl-2) which
|
||||
with [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install#update-to-wsl-2) which
|
||||
has both `git` and `ssh` preinstalled, or install [Git for Windows](https://gitforwindows.org) to
|
||||
use SSH through Powershell.
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ used for the build.
|
|||
|
||||
Specify either:
|
||||
|
||||
- The CI/CD variable `BUILDPACK_URL` according to [`pack`'s specifications](https://buildpacks.io/docs/app-developer-guide/specific-buildpacks/).
|
||||
- The CI/CD variable `BUILDPACK_URL` according to [`pack`'s specifications](https://buildpacks.io/docs/app-developer-guide/specify-buildpacks/).
|
||||
- A [`project.toml` project descriptor](https://buildpacks.io/docs/app-developer-guide/using-project-descriptor/) with the buildpacks you would like to include.
|
||||
|
||||
### Custom buildpacks with Herokuish
|
||||
|
|
|
@ -112,7 +112,7 @@ Herokuish, with the following caveats:
|
|||
converted to a Cloud Native Buildpack using Heroku's
|
||||
[`cnb-shim`](https://github.com/heroku/cnb-shim).
|
||||
- `BUILDPACK_URL` must be in a format
|
||||
[supported by `pack`](https://buildpacks.io/docs/app-developer-guide/specific-buildpacks/).
|
||||
[supported by `pack`](https://buildpacks.io/docs/app-developer-guide/specify-buildpacks/).
|
||||
- The `/bin/herokuish` command is not present in the built image, and prefixing
|
||||
commands with `/bin/herokuish procfile exec` is no longer required (nor possible).
|
||||
Instead, custom commands should be prefixed with `/cnb/lifecycle/launcher`
|
||||
|
|
|
@ -190,7 +190,7 @@ By doing this, you minimize the length of time during which you have to apply bu
|
|||
After announcing a release branch, only add serious bug fixes to the branch.
|
||||
If possible, first merge these bug fixes into `main`, and then cherry-pick them into the release branch.
|
||||
If you start by merging into the release branch, you might forget to cherry-pick them into `main`, and then you'd encounter the same bug in subsequent releases.
|
||||
Merging into `main` and then cherry-picking into release is called an "upstream first" policy, which is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first) and [Red Hat](https://www.redhat.com/en/blog/a-community-for-using-openstack-with-red-hat-rdo).
|
||||
Merging into `main` and then cherry-picking into release is called an "upstream first" policy, which is also practiced by [Google](https://www.chromium.org/chromium-os/chromiumos-design-docs/upstream-first/) and [Red Hat](https://www.redhat.com/en/blog/a-community-for-using-openstack-with-red-hat-rdo).
|
||||
Every time you include a bug fix in a release branch, increase the patch version (to comply with [Semantic Versioning](https://semver.org/)) by setting a new tag.
|
||||
Some projects also have a stable branch that points to the same commit as the latest released branch.
|
||||
In this flow, it is not common to have a production branch (or Git flow `main` branch).
|
||||
|
|
|
@ -40,7 +40,7 @@ To view Code Review Analytics:
|
|||
|
||||
## Use cases
|
||||
|
||||
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#delaney-development-team-lead)
|
||||
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/product/personas/#delaney-development-team-lead)
|
||||
and others who want to understand broad code review dynamics, and identify patterns to explain them.
|
||||
|
||||
You can use Code Review Analytics to:
|
||||
|
|
|
@ -980,7 +980,7 @@ podAnnotations:
|
|||
|
||||
The only information to be changed here is the profile name which is `profile-one`
|
||||
in this example. Refer to the
|
||||
[AppArmor tutorial](https://kubernetes.io/docs/tutorials/clusters/apparmor/#securing-a-pod)
|
||||
[AppArmor tutorial](https://kubernetes.io/docs/tutorials/security/apparmor/#securing-a-pod)
|
||||
for more information on how AppArmor is integrated in Kubernetes.
|
||||
|
||||
#### Using PodSecurityPolicy in your deployments
|
||||
|
@ -1017,7 +1017,7 @@ securityPolicies:
|
|||
```
|
||||
|
||||
This example creates a single policy named `example` with the provided specification,
|
||||
and enables [AppArmor annotations](https://kubernetes.io/docs/tutorials/clusters/apparmor/#podsecuritypolicy-annotations) on it.
|
||||
and enables [AppArmor annotations](https://kubernetes.io/docs/tutorials/security/apparmor/#podsecuritypolicy-annotations) on it.
|
||||
|
||||
Support for installing the AppArmor managed application is provided by the
|
||||
GitLab Container Security group. If you run into unknown issues,
|
||||
|
|
|
@ -80,7 +80,7 @@ provided can manage resources in the `database.crossplane.io` API group:
|
|||
|
||||
## Configure Crossplane with a cloud provider
|
||||
|
||||
See [Configure Your Cloud Provider Account](https://crossplane.github.io/docs/v0.4/cloud-providers.html)
|
||||
See [Configure Your Cloud Provider Account](https://crossplane.github.io/docs/v1.6/)
|
||||
to configure the installed cloud provider stack with a user account.
|
||||
|
||||
The Secret, and the Provider resource referencing the Secret, must be
|
||||
|
|
|
@ -113,9 +113,9 @@ To use this integration:
|
|||
`gitlab-managed-apps` namespace.
|
||||
1. The `Service` resource must be called `elastic-stack-elasticsearch-master`
|
||||
and expose the Elasticsearch API on port `9200`.
|
||||
1. The logs are expected to be [Filebeat container logs](https://www.elastic.co/guide/en/beats/filebeat/7.x/filebeat-input-container.html)
|
||||
following the [7.x log structure](https://www.elastic.co/guide/en/beats/filebeat/7.x/exported-fields-log.html)
|
||||
and include [Kubernetes metadata](https://www.elastic.co/guide/en/beats/filebeat/7.x/add-kubernetes-metadata.html).
|
||||
1. The logs are expected to be [Filebeat container logs](https://www.elastic.co/guide/en/beats/filebeat/7.16/filebeat-input-container.html)
|
||||
following the [7.x log structure](https://www.elastic.co/guide/en/beats/filebeat/7.16/exported-fields-log.html)
|
||||
and include [Kubernetes metadata](https://www.elastic.co/guide/en/beats/filebeat/7.16/add-kubernetes-metadata.html).
|
||||
|
||||
You can manage your Elastic Stack however you like, but as an example, you can
|
||||
use [this Elastic Stack chart](https://gitlab.com/gitlab-org/charts/elastic-stack) to get up and
|
||||
|
|
|
@ -120,7 +120,7 @@ you want to manage with the Cluster Management Project.
|
|||
|
||||
## Backup and uninstall cert-manager v0.10
|
||||
|
||||
1. Follow the [official docs](https://docs.cert-manager.io/en/release-0.10/tasks/backup-restore-crds.html) on how to
|
||||
1. Follow the [official docs](https://cert-manager.io/docs/tutorials/backup/) on how to
|
||||
backup your cert-manager v0.10 data.
|
||||
1. Uninstall cert-manager by editing the setting all the occurrences of `installed: true` to `installed: false` in the
|
||||
`applications/cert-manager/helmfile.yaml` file.
|
||||
|
|
|
@ -52,7 +52,7 @@ export, after which the email is prepared.
|
|||
|
||||
## Sorting
|
||||
|
||||
Exported issues are always sorted by `Issue ID`.
|
||||
Exported issues are always sorted by `Title`.
|
||||
|
||||
## Format
|
||||
|
||||
|
@ -63,11 +63,11 @@ the values:
|
|||
|
||||
| Column | Description |
|
||||
|------------------------------------------|-----------------------------------------------------------|
|
||||
| Title | Issue `title` |
|
||||
| Description | Issue `description` |
|
||||
| Issue ID | Issue `iid` |
|
||||
| URL | A link to the issue on GitLab |
|
||||
| Title | Issue `title` |
|
||||
| State | `Open` or `Closed` |
|
||||
| Description | Issue `description` |
|
||||
| Author | Full name of the issue author |
|
||||
| Author Username | Username of the author, with the `@` symbol omitted |
|
||||
| Assignee | Full name of the issue assignee |
|
||||
|
@ -85,6 +85,10 @@ the values:
|
|||
| [Epic](../../group/epics/index.md) ID | ID of the parent epic, introduced in 12.7 |
|
||||
| [Epic](../../group/epics/index.md) Title | Title of the parent epic, introduced in 12.7 |
|
||||
|
||||
In GitLab 14.7 and earlier, the first two columns were `Issue ID` and `URL`,
|
||||
which [caused an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/34769)
|
||||
when importing back into GitLab.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Export Issues to CSV is not available at the Group's Issues List.
|
||||
|
|
|
@ -18,11 +18,11 @@ The following table shows what attributes will be present in the CSV.
|
|||
|
||||
| Column | Description |
|
||||
|--------------------|--------------------------------------------------------------|
|
||||
| Title | Merge request title |
|
||||
| Description | Merge request description |
|
||||
| MR ID | MR `iid` |
|
||||
| URL | A link to the merge request on GitLab |
|
||||
| Title | Merge request title |
|
||||
| State | Opened, Closed, Locked, or Merged |
|
||||
| Description | Merge request description |
|
||||
| Source Branch | Source branch |
|
||||
| Target Branch | Target branch |
|
||||
| Source Project ID | ID of the source project |
|
||||
|
@ -39,6 +39,10 @@ The following table shows what attributes will be present in the CSV.
|
|||
| Created At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
|
||||
| Updated At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
|
||||
|
||||
In GitLab 14.7 and earlier, the first two columns were `MR ID` and `URL`,
|
||||
which [caused an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/34769)
|
||||
when importing back into GitLab.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Export merge requests to CSV is not available at the Group's merge request list.
|
||||
|
|
|
@ -17,16 +17,16 @@ You can also open the Web IDE when viewing a file, from the repository file list
|
|||
and from merge requests:
|
||||
|
||||
- *When viewing a file, or the repository file list* -
|
||||
1. In the upper right corner of the page, select **Edit in Web IDE** if it is visible.
|
||||
1. If **Edit in Web IDE** is not visible:
|
||||
1. In the upper right corner of the page, select **Open in Web IDE** if it is visible.
|
||||
1. If **Open in Web IDE** is not visible:
|
||||
1. Select the **(angle-down)** next to **Edit** or **Gitpod**, depending on your configuration.
|
||||
1. Select **Edit in Web IDE** from the list to display it as the editing option.
|
||||
1. Select **Edit in Web IDE** to open the editor.
|
||||
1. Select **Open in Web IDE** from the list to display it as the editing option.
|
||||
1. Select **Open in Web IDE** to open the editor.
|
||||
- *When viewing a merge request* -
|
||||
1. Go to your merge request, and select the **Overview** tab.
|
||||
1. Scroll to the widgets section, after the merge request description.
|
||||
1. Select **Edit in Web IDE** if it is visible.
|
||||
1. If **Edit in Web IDE** is not visible:
|
||||
1. Select **Open in Web IDE** if it is visible.
|
||||
1. If **Open in Web IDE** is not visible:
|
||||
1. Select the **(angle-down)** next to **Open in Gitpod**.
|
||||
1. Select **Open in Web IDE** from the list to display it as the editing option.
|
||||
1. Select **Open in Web IDE** to open the editor.
|
||||
|
@ -221,7 +221,7 @@ different branch.
|
|||
To edit Markdown files in the Web IDE:
|
||||
|
||||
1. Go to your repository, and navigate to the Markdown page you want to edit.
|
||||
1. Select **Edit in Web IDE**, and GitLab loads the page in a tab in the editor.
|
||||
1. Select **Open in Web IDE**, and GitLab loads the page in a tab in the editor.
|
||||
1. Make your changes to the file. GitLab supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown).
|
||||
1. When your changes are complete, select **Commit** in the left sidebar.
|
||||
1. Add a commit message, select the branch you want to commit to, and select **Commit**.
|
||||
|
|
|
@ -195,6 +195,16 @@ module Gitlab
|
|||
MAX_TIMESTAMP_VALUE > timestamp ? timestamp : MAX_TIMESTAMP_VALUE.dup
|
||||
end
|
||||
|
||||
def self.all_uncached(&block)
|
||||
# Calls to #uncached only disable caching for the current connection. Since the load balancer
|
||||
# can potentially upgrade from read to read-write mode (using a different connection), we specify
|
||||
# up-front that we'll explicitly use the primary for the duration of the operation.
|
||||
Gitlab::Database::LoadBalancing::Session.current.use_primary do
|
||||
base_models = database_base_models.values
|
||||
base_models.reduce(block) { |blk, model| -> { model.uncached(&blk) } }.call
|
||||
end
|
||||
end
|
||||
|
||||
def self.allow_cross_joins_across_databases(url:)
|
||||
# this method is implemented in:
|
||||
# spec/support/database/prevent_cross_joins.rb
|
||||
|
|
|
@ -58,6 +58,7 @@ module Gitlab
|
|||
push_frontend_feature_flag(:new_header_search, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:bootstrap_confirmation_modals, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:sandboxed_mermaid, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:source_editor_toolbar, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
# Exposes the state of a feature flag to the frontend code.
|
||||
|
|
|
@ -29,7 +29,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def restore
|
||||
ActiveRecord::Base.uncached do
|
||||
Gitlab::Database.all_uncached do
|
||||
ActiveRecord::Base.no_touching do
|
||||
update_params!
|
||||
|
||||
|
|
|
@ -13229,9 +13229,6 @@ msgstr ""
|
|||
msgid "Edit identity for %{user_name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit in Web IDE"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit in pipeline editor"
|
||||
msgstr ""
|
||||
|
||||
|
@ -31671,6 +31668,9 @@ msgstr ""
|
|||
msgid "Runners|Never contacted"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|New group runners view"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|New registration token generated!"
|
||||
msgstr ""
|
||||
|
||||
|
@ -31737,6 +31737,9 @@ msgstr ""
|
|||
msgid "Runners|Revision"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Rocket launch illustration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner"
|
||||
msgstr ""
|
||||
|
||||
|
@ -31803,6 +31806,12 @@ msgstr ""
|
|||
msgid "Runners|Tags"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Take me there!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|The new view gives you more space and better visibility into your fleet of runners."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ gem 'confiner', '~> 0.2'
|
|||
gem 'chemlab', '~> 0.9'
|
||||
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
|
||||
|
||||
gem "pact", "~> 1.12"
|
||||
|
||||
gem 'deprecation_toolkit', '~> 1.5.1', require: false
|
||||
|
||||
group :development do
|
||||
|
|
|
@ -28,6 +28,7 @@ GEM
|
|||
require_all (>= 2, < 4)
|
||||
uuid (>= 2.3, < 3)
|
||||
ast (2.4.2)
|
||||
awesome_print (1.9.2)
|
||||
binding_ninja (0.2.3)
|
||||
builder (3.2.4)
|
||||
byebug (9.1.0)
|
||||
|
@ -91,6 +92,8 @@ GEM
|
|||
ffi-compiler (1.0.1)
|
||||
ffi (>= 1.0.0)
|
||||
rake
|
||||
filelock (1.1.1)
|
||||
find_a_port (1.0.1)
|
||||
fog-core (2.1.0)
|
||||
builder
|
||||
excon (~> 0.58)
|
||||
|
@ -173,6 +176,7 @@ GEM
|
|||
concurrent-ruby (~> 1.0)
|
||||
ice_nine (0.11.2)
|
||||
influxdb-client (1.17.0)
|
||||
json (2.6.1)
|
||||
jwt (2.3.0)
|
||||
knapsack (4.0.0)
|
||||
rake
|
||||
|
@ -205,6 +209,29 @@ GEM
|
|||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
oj (3.13.11)
|
||||
os (1.1.4)
|
||||
pact (1.59.0)
|
||||
pact-mock_service (~> 3.0, >= 3.3.1)
|
||||
pact-support (~> 1.15)
|
||||
rack-test (>= 0.6.3, < 2.0.0)
|
||||
rspec (~> 3.0)
|
||||
term-ansicolor (~> 1.0)
|
||||
thor (>= 0.20, < 2.0)
|
||||
webrick (~> 1.3)
|
||||
pact-mock_service (3.6.2)
|
||||
filelock (~> 1.1)
|
||||
find_a_port (~> 1.0.1)
|
||||
json
|
||||
pact-support (~> 1.12, >= 1.12.0)
|
||||
rack (~> 2.0)
|
||||
rspec (>= 2.14)
|
||||
term-ansicolor (~> 1.0)
|
||||
thor (>= 0.19, < 2.0)
|
||||
webrick (~> 1.3)
|
||||
pact-support (1.15.1)
|
||||
awesome_print (~> 1.1)
|
||||
randexp (~> 0.1.7)
|
||||
rspec (>= 2.14)
|
||||
term-ansicolor (~> 1.0)
|
||||
parallel (1.19.2)
|
||||
parallel_tests (2.29.0)
|
||||
parallel
|
||||
|
@ -228,6 +255,7 @@ GEM
|
|||
rack (>= 1.0, < 3)
|
||||
rainbow (3.0.0)
|
||||
rake (13.0.6)
|
||||
randexp (0.1.7)
|
||||
regexp_parser (2.1.1)
|
||||
representable (3.1.1)
|
||||
declarative (< 0.1.0)
|
||||
|
@ -282,12 +310,18 @@ GEM
|
|||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
slack-notifier (2.4.0)
|
||||
sync (0.5.0)
|
||||
systemu (2.6.5)
|
||||
table_print (1.5.7)
|
||||
term-ansicolor (1.7.1)
|
||||
tins (~> 1.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
thor (1.2.1)
|
||||
thread_safe (0.3.6)
|
||||
timecop (0.9.1)
|
||||
tins (1.31.0)
|
||||
sync
|
||||
trailblazer-option (0.1.2)
|
||||
tzinfo (2.0.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
|
@ -337,6 +371,7 @@ DEPENDENCIES
|
|||
influxdb-client (~> 1.17)
|
||||
knapsack (~> 4.0)
|
||||
octokit (~> 4.21)
|
||||
pact (~> 1.12)
|
||||
parallel (~> 1.19)
|
||||
parallel_tests (~> 2.29)
|
||||
pry-byebug (~> 3.5.1)
|
||||
|
|
32
qa/bin/contract
Executable file
32
qa/bin/contract
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rake'
|
||||
|
||||
host = ARGV.shift
|
||||
ENV['CONTRACT_HOST'] ||= host
|
||||
|
||||
list = []
|
||||
|
||||
loop do
|
||||
keyword = ARGV.shift
|
||||
case keyword
|
||||
when '--mr'
|
||||
ENV['CONTRACT_MR'] ||= ARGV.shift
|
||||
list.push 'test:merge_request'
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
app = Rake.application
|
||||
|
||||
Dir.chdir('contracts/provider') do
|
||||
app.init
|
||||
app.add_import 'Rakefile'
|
||||
app.load_rakefile
|
||||
|
||||
list.each do |element|
|
||||
app[element].invoke
|
||||
end
|
||||
end
|
2
qa/contracts/.gitignore
vendored
Normal file
2
qa/contracts/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
logs/
|
||||
consumer/node_modules
|
1
qa/contracts/consumer/.node-version
Normal file
1
qa/contracts/consumer/.node-version
Normal file
|
@ -0,0 +1 @@
|
|||
14.17.5
|
42
qa/contracts/consumer/endpoints/merge_request.js
Normal file
42
qa/contracts/consumer/endpoints/merge_request.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
'use strict';
|
||||
|
||||
const axios = require('axios');
|
||||
|
||||
exports.getMetadata = (endpoint) => {
|
||||
const url = endpoint.url;
|
||||
|
||||
return axios
|
||||
.request({
|
||||
method: 'GET',
|
||||
baseURL: url,
|
||||
url: '/diffs_metadata.json',
|
||||
headers: { Accept: '*/*' },
|
||||
})
|
||||
.then((response) => response.data);
|
||||
};
|
||||
|
||||
exports.getDiscussions = (endpoint) => {
|
||||
const url = endpoint.url;
|
||||
|
||||
return axios
|
||||
.request({
|
||||
method: 'GET',
|
||||
baseURL: url,
|
||||
url: '/discussions.json',
|
||||
headers: { Accept: '*/*' },
|
||||
})
|
||||
.then((response) => response.data);
|
||||
};
|
||||
|
||||
exports.getDiffs = (endpoint) => {
|
||||
const url = endpoint.url;
|
||||
|
||||
return axios
|
||||
.request({
|
||||
method: 'GET',
|
||||
baseURL: url,
|
||||
url: '/diffs_batch.json?page=0',
|
||||
headers: { Accept: '*/*' },
|
||||
})
|
||||
.then((response) => response.data);
|
||||
};
|
89
qa/contracts/consumer/fixtures/diffs.fixture.js
Normal file
89
qa/contracts/consumer/fixtures/diffs.fixture.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
'use strict';
|
||||
|
||||
const { Matchers } = require('@pact-foundation/pact');
|
||||
|
||||
const body = {
|
||||
diff_files: Matchers.eachLike({
|
||||
content_sha: Matchers.string('b0c94059db75b2473d616d4b1fde1a77533355a3'),
|
||||
submodule: Matchers.boolean(false),
|
||||
edit_path: Matchers.string('/gitlab-qa-bot/...'),
|
||||
ide_edit_path: Matchers.string('/gitlab-qa-bot/...'),
|
||||
old_path_html: Matchers.string('Gemfile'),
|
||||
new_path_html: Matchers.string('Gemfile'),
|
||||
blob: {
|
||||
id: Matchers.string('855071bb3928d140764885964f7be1bb3e582495'),
|
||||
path: Matchers.string('Gemfile'),
|
||||
name: Matchers.string('Gemfile'),
|
||||
mode: Matchers.string('1234567'),
|
||||
readable_text: Matchers.boolean(true),
|
||||
icon: Matchers.string('doc-text'),
|
||||
},
|
||||
can_modify_blob: Matchers.boolean(false),
|
||||
file_identifier_hash: Matchers.string('67d82b8716a5b6c52c7abf0b2cd99c7594ed3587'),
|
||||
file_hash: Matchers.string('67d82b8716a5b6c52c7abf0b2cd99c7594ed3587'),
|
||||
file_path: Matchers.string('Gemfile'),
|
||||
old_path: Matchers.string('Gemfile'),
|
||||
new_path: Matchers.string('Gemfile'),
|
||||
new_file: Matchers.boolean(false),
|
||||
renamed_file: Matchers.boolean(false),
|
||||
deleted_file: Matchers.boolean(false),
|
||||
diff_refs: {
|
||||
base_sha: Matchers.string('67d82b8716a5b6c52c7abf0b2cd99c7594ed3587'),
|
||||
start_sha: Matchers.string('67d82b8716a5b6c52c7abf0b2cd99c7594ed3587'),
|
||||
head_sha: Matchers.string('67d82b8716a5b6c52c7abf0b2cd99c7594ed3587'),
|
||||
},
|
||||
mode_changed: Matchers.boolean(false),
|
||||
a_mode: Matchers.string('123456'),
|
||||
b_mode: Matchers.string('123456'),
|
||||
viewer: {
|
||||
name: Matchers.string('text'),
|
||||
collapsed: Matchers.boolean(false),
|
||||
},
|
||||
old_size: Matchers.integer(2288),
|
||||
new_size: Matchers.integer(2288),
|
||||
added_lines: Matchers.integer(1),
|
||||
removed_lines: Matchers.integer(1),
|
||||
load_collapsed_diff_url: Matchers.string('/gitlab-qa-bot/...'),
|
||||
view_path: Matchers.string('/gitlab-qa-bot/...'),
|
||||
context_lines_path: Matchers.string('/gitlab-qa-bot/...'),
|
||||
highlighted_diff_lines: Matchers.eachLike({
|
||||
// The following values can also be null which is not supported
|
||||
//line_code: Matchers.string('de3150c01c3a946a6168173c4116741379fe3579_1_1'),
|
||||
//old_line: Matchers.integer(1),
|
||||
//new_line: Matchers.integer(1),
|
||||
text: Matchers.string('source'),
|
||||
rich_text: Matchers.string('<span></span>'),
|
||||
can_receive_suggestion: Matchers.boolean(true),
|
||||
}),
|
||||
is_fully_expanded: Matchers.boolean(false),
|
||||
}),
|
||||
pagination: {
|
||||
total_pages: Matchers.integer(1),
|
||||
},
|
||||
};
|
||||
|
||||
const Diffs = {
|
||||
body: Matchers.extractPayload(body),
|
||||
|
||||
success: {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body: body,
|
||||
},
|
||||
|
||||
request: {
|
||||
uponReceiving: 'a request for diff lines',
|
||||
withRequest: {
|
||||
method: 'GET',
|
||||
path: '/diffs_batch.json',
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
},
|
||||
query: 'page=0',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
exports.Diffs = Diffs;
|
85
qa/contracts/consumer/fixtures/discussions.fixture.js
Normal file
85
qa/contracts/consumer/fixtures/discussions.fixture.js
Normal file
|
@ -0,0 +1,85 @@
|
|||
'use strict';
|
||||
|
||||
const { Matchers } = require('@pact-foundation/pact');
|
||||
|
||||
const body = Matchers.eachLike({
|
||||
id: Matchers.string('fd73763cbcbf7b29eb8765d969a38f7d735e222a'),
|
||||
reply_id: Matchers.string('fd73763cbcbf7b29eb8765d969a38f7d735e222a'),
|
||||
project_id: Matchers.integer(6954442),
|
||||
confidential: Matchers.boolean(false),
|
||||
diff_discussion: Matchers.boolean(false),
|
||||
expanded: Matchers.boolean(false),
|
||||
for_commit: Matchers.boolean(false),
|
||||
individual_note: Matchers.boolean(true),
|
||||
resolvable: Matchers.boolean(false),
|
||||
resolved_by_push: Matchers.boolean(false),
|
||||
notes: Matchers.eachLike({
|
||||
id: Matchers.string('76489845'),
|
||||
author: {
|
||||
id: Matchers.integer(1675733),
|
||||
username: Matchers.string('gitlab-qa-bot'),
|
||||
name: Matchers.string('gitlab-qa-bot'),
|
||||
state: Matchers.string('active'),
|
||||
avatar_url: Matchers.string(
|
||||
'https://secure.gravatar.com/avatar/8355ad0f2761367fae6b9c4fe80994b9?s=80&d=identicon',
|
||||
),
|
||||
show_status: Matchers.boolean(false),
|
||||
path: Matchers.string('/gitlab-qa-bot'),
|
||||
},
|
||||
created_at: Matchers.iso8601DateTimeWithMillis('2022-02-22T07:06:55.038Z'),
|
||||
updated_at: Matchers.iso8601DateTimeWithMillis('2022-02-22T07:06:55.038Z'),
|
||||
system: Matchers.boolean(false),
|
||||
noteable_id: Matchers.integer(8333422),
|
||||
noteable_type: Matchers.string('MergeRequest'),
|
||||
resolvable: Matchers.boolean(false),
|
||||
resolved: Matchers.boolean(true),
|
||||
confidential: Matchers.boolean(false),
|
||||
noteable_iid: Matchers.integer(1),
|
||||
note: Matchers.string('This is a test comment'),
|
||||
note_html: Matchers.string(
|
||||
'<p data-sourcepos="1:1-1:22" dir="auto">This is a test comment</p>',
|
||||
),
|
||||
current_user: {
|
||||
can_edit: Matchers.boolean(true),
|
||||
can_award_emoji: Matchers.boolean(true),
|
||||
can_resolve: Matchers.boolean(false),
|
||||
can_resolve_discussion: Matchers.boolean(false),
|
||||
},
|
||||
is_noteable_author: Matchers.boolean(true),
|
||||
discussion_id: Matchers.string('fd73763cbcbf7b29eb8765d969a38f7d735e222a'),
|
||||
emoji_awardable: Matchers.boolean(true),
|
||||
report_abuse_path: Matchers.string('/gitlab-qa-bot/...'),
|
||||
noteable_note_url: Matchers.string('https://staging.gitlab.com/gitlab-qa-bot/...'),
|
||||
cached_markdown_version: Matchers.integer(1900552),
|
||||
human_access: Matchers.string('Maintainer'),
|
||||
is_contributor: Matchers.boolean(false),
|
||||
project_name: Matchers.string('contract-testing'),
|
||||
path: Matchers.string('/gitlab-qa-bot/...'),
|
||||
}),
|
||||
resolved: Matchers.boolean(true),
|
||||
});
|
||||
|
||||
const Discussions = {
|
||||
body: Matchers.extractPayload(body),
|
||||
|
||||
success: {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body: body,
|
||||
},
|
||||
|
||||
request: {
|
||||
uponReceiving: 'a request for discussions',
|
||||
withRequest: {
|
||||
method: 'GET',
|
||||
path: '/discussions.json',
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
exports.Discussions = Discussions;
|
96
qa/contracts/consumer/fixtures/metadata.fixture.js
Normal file
96
qa/contracts/consumer/fixtures/metadata.fixture.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
'use strict';
|
||||
|
||||
const { Matchers } = require('@pact-foundation/pact');
|
||||
|
||||
const body = {
|
||||
real_size: Matchers.string('1'),
|
||||
size: Matchers.integer(1),
|
||||
branch_name: Matchers.string('testing-branch-1'),
|
||||
source_branch_exists: Matchers.boolean(true),
|
||||
target_branch_name: Matchers.string('master'),
|
||||
merge_request_diff: {
|
||||
created_at: Matchers.iso8601DateTimeWithMillis('2022-02-17T11:47:08.804Z'),
|
||||
commits_count: Matchers.integer(1),
|
||||
latest: Matchers.boolean(true),
|
||||
short_commit_sha: Matchers.string('aee1ffec'),
|
||||
base_version_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773',
|
||||
),
|
||||
head_version_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_head=true',
|
||||
),
|
||||
version_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773',
|
||||
),
|
||||
compare_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773&start_sha=aee1ffec2299c0cfb17c8821e931339b73a3759f',
|
||||
),
|
||||
},
|
||||
latest_diff: Matchers.boolean(true),
|
||||
latest_version_path: Matchers.string('/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs'),
|
||||
added_lines: Matchers.integer(1),
|
||||
removed_lines: Matchers.integer(1),
|
||||
render_overflow_warning: Matchers.boolean(false),
|
||||
email_patch_path: Matchers.string('/gitlab-qa-bot/contract-testing/-/merge_requests/1.patch'),
|
||||
plain_diff_path: Matchers.string('/gitlab-qa-bot/contract-testing/-/merge_requests/1.diff'),
|
||||
merge_request_diffs: Matchers.eachLike({
|
||||
commits_count: Matchers.integer(1),
|
||||
latest: Matchers.boolean(true),
|
||||
short_commit_sha: Matchers.string('aee1ffec'),
|
||||
base_version_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773',
|
||||
),
|
||||
head_version_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_head=true',
|
||||
),
|
||||
version_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773',
|
||||
),
|
||||
compare_path: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773&start_sha=aee1ffec2299c0cfb17c8821e931339b73a3759f',
|
||||
),
|
||||
}),
|
||||
definition_path_prefix: Matchers.string(
|
||||
'/gitlab-qa-bot/contract-testing/-/blob/aee1ffec2299c0cfb17c8821e931339b73a3759f',
|
||||
),
|
||||
diff_files: Matchers.eachLike({
|
||||
added_lines: Matchers.integer(1),
|
||||
removed_lines: Matchers.integer(1),
|
||||
new_path: Matchers.string('Gemfile'),
|
||||
old_path: Matchers.string('Gemfile'),
|
||||
new_file: Matchers.boolean(false),
|
||||
deleted_file: Matchers.boolean(false),
|
||||
submodule: Matchers.boolean(false),
|
||||
file_identifier_hash: Matchers.string('67d82b8716a5b6c52c7abf0b2cd99c7594ed3587'),
|
||||
file_hash: Matchers.string('de3150c01c3a946a6168173c4116741379fe3579'),
|
||||
}),
|
||||
has_conflicts: Matchers.boolean(false),
|
||||
can_merge: Matchers.boolean(false),
|
||||
project_path: Matchers.string('gitlab-qa-bot/contract-testing'),
|
||||
project_name: Matchers.string('contract-testing'),
|
||||
};
|
||||
|
||||
const Metadata = {
|
||||
body: Matchers.extractPayload(body),
|
||||
|
||||
success: {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body: body,
|
||||
},
|
||||
|
||||
request: {
|
||||
uponReceiving: 'a request for Metadata',
|
||||
withRequest: {
|
||||
method: 'GET',
|
||||
path: '/diffs_metadata.json',
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
exports.Metadata = Metadata;
|
17
qa/contracts/consumer/package.json
Normal file
17
qa/contracts/consumer/package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "consumer",
|
||||
"version": "1.0.0",
|
||||
"description": "consumer side contract testing",
|
||||
"license": "MIT",
|
||||
"repository": "https://gitlab.com/gitlab-org/gitlab.git",
|
||||
"dependencies": {
|
||||
"@pact-foundation/pact": "^9.17.2",
|
||||
"axios": "^0.26.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-pact": "^0.9.1",
|
||||
"prettier": "^2.5.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest specs/ --runInBand"
|
||||
}
|
||||
}
|
35
qa/contracts/consumer/specs/diffs.spec.js
Normal file
35
qa/contracts/consumer/specs/diffs.spec.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
const { pactWith } = require('jest-pact');
|
||||
|
||||
const { Diffs } = require('../fixtures/diffs.fixture');
|
||||
const { getDiffs } = require('../endpoints/merge_request');
|
||||
|
||||
pactWith(
|
||||
{
|
||||
consumer: 'Merge Request Page',
|
||||
provider: 'Merge Request Diffs Endpoint',
|
||||
log: '../logs/consumer.log',
|
||||
dir: '../contracts',
|
||||
},
|
||||
|
||||
(provider) => {
|
||||
describe('Diffs Endpoint', () => {
|
||||
beforeEach(() => {
|
||||
const interaction = {
|
||||
...Diffs.request,
|
||||
willRespondWith: Diffs.success,
|
||||
};
|
||||
return provider.addInteraction(interaction);
|
||||
});
|
||||
|
||||
it('return a successful body', () => {
|
||||
return getDiffs({
|
||||
url: provider.mockService.baseUrl,
|
||||
}).then((diffs) => {
|
||||
expect(diffs).toEqual(Diffs.body);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
35
qa/contracts/consumer/specs/discussions.spec.js
Normal file
35
qa/contracts/consumer/specs/discussions.spec.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
const { pactWith } = require('jest-pact');
|
||||
|
||||
const { Discussions } = require('../fixtures/discussions.fixture');
|
||||
const { getDiscussions } = require('../endpoints/merge_request');
|
||||
|
||||
pactWith(
|
||||
{
|
||||
consumer: 'Merge Request Page',
|
||||
provider: 'Merge Request Discussions Endpoint',
|
||||
log: '../logs/consumer.log',
|
||||
dir: '../contracts',
|
||||
},
|
||||
|
||||
(provider) => {
|
||||
describe('Discussions Endpoint', () => {
|
||||
beforeEach(() => {
|
||||
const interaction = {
|
||||
...Discussions.request,
|
||||
willRespondWith: Discussions.success,
|
||||
};
|
||||
return provider.addInteraction(interaction);
|
||||
});
|
||||
|
||||
it('return a successful body', () => {
|
||||
return getDiscussions({
|
||||
url: provider.mockService.baseUrl,
|
||||
}).then((discussions) => {
|
||||
expect(discussions).toEqual(Discussions.body);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
35
qa/contracts/consumer/specs/metadata.spec.js
Normal file
35
qa/contracts/consumer/specs/metadata.spec.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
const { pactWith } = require('jest-pact');
|
||||
|
||||
const { Metadata } = require('../fixtures/metadata.fixture');
|
||||
const { getMetadata } = require('../endpoints/merge_request');
|
||||
|
||||
pactWith(
|
||||
{
|
||||
consumer: 'Merge Request Page',
|
||||
provider: 'Merge Request Metadata Endpoint',
|
||||
log: '../logs/consumer.log',
|
||||
dir: '../contracts',
|
||||
},
|
||||
|
||||
(provider) => {
|
||||
describe('Metadata Endpoint', () => {
|
||||
beforeEach(() => {
|
||||
const interaction = {
|
||||
...Metadata.request,
|
||||
willRespondWith: Metadata.success,
|
||||
};
|
||||
return provider.addInteraction(interaction);
|
||||
});
|
||||
|
||||
it('return a successful body', () => {
|
||||
return getMetadata({
|
||||
url: provider.mockService.baseUrl,
|
||||
}).then((metadata) => {
|
||||
expect(metadata).toEqual(Metadata.body);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
|
@ -0,0 +1,228 @@
|
|||
{
|
||||
"consumer": {
|
||||
"name": "Merge Request Page"
|
||||
},
|
||||
"provider": {
|
||||
"name": "Merge Request Diffs Endpoint"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"description": "a request for diff lines",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"path": "/diffs_batch.json",
|
||||
"query": "page=0",
|
||||
"headers": {
|
||||
"Accept": "*/*"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": {
|
||||
"diff_files": [
|
||||
{
|
||||
"content_sha": "b0c94059db75b2473d616d4b1fde1a77533355a3",
|
||||
"submodule": false,
|
||||
"edit_path": "/gitlab-qa-bot/...",
|
||||
"ide_edit_path": "/gitlab-qa-bot/...",
|
||||
"old_path_html": "Gemfile",
|
||||
"new_path_html": "Gemfile",
|
||||
"blob": {
|
||||
"id": "855071bb3928d140764885964f7be1bb3e582495",
|
||||
"path": "Gemfile",
|
||||
"name": "Gemfile",
|
||||
"mode": "1234567",
|
||||
"readable_text": true,
|
||||
"icon": "doc-text"
|
||||
},
|
||||
"can_modify_blob": false,
|
||||
"file_identifier_hash": "67d82b8716a5b6c52c7abf0b2cd99c7594ed3587",
|
||||
"file_hash": "67d82b8716a5b6c52c7abf0b2cd99c7594ed3587",
|
||||
"file_path": "Gemfile",
|
||||
"old_path": "Gemfile",
|
||||
"new_path": "Gemfile",
|
||||
"new_file": false,
|
||||
"renamed_file": false,
|
||||
"deleted_file": false,
|
||||
"diff_refs": {
|
||||
"base_sha": "67d82b8716a5b6c52c7abf0b2cd99c7594ed3587",
|
||||
"start_sha": "67d82b8716a5b6c52c7abf0b2cd99c7594ed3587",
|
||||
"head_sha": "67d82b8716a5b6c52c7abf0b2cd99c7594ed3587"
|
||||
},
|
||||
"mode_changed": false,
|
||||
"a_mode": "123456",
|
||||
"b_mode": "123456",
|
||||
"viewer": {
|
||||
"name": "text",
|
||||
"collapsed": false
|
||||
},
|
||||
"old_size": 2288,
|
||||
"new_size": 2288,
|
||||
"added_lines": 1,
|
||||
"removed_lines": 1,
|
||||
"load_collapsed_diff_url": "/gitlab-qa-bot/...",
|
||||
"view_path": "/gitlab-qa-bot/...",
|
||||
"context_lines_path": "/gitlab-qa-bot/...",
|
||||
"highlighted_diff_lines": [
|
||||
{
|
||||
"text": "source",
|
||||
"rich_text": "<span></span>",
|
||||
"can_receive_suggestion": true
|
||||
}
|
||||
],
|
||||
"is_fully_expanded": false
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total_pages": 1
|
||||
}
|
||||
},
|
||||
"matchingRules": {
|
||||
"$.body.diff_files": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.diff_files[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].content_sha": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].submodule": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].edit_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].ide_edit_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].old_path_html": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].new_path_html": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].blob.id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].blob.path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].blob.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].blob.mode": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].blob.readable_text": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].blob.icon": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].can_modify_blob": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].file_identifier_hash": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].file_hash": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].file_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].old_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].new_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].new_file": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].renamed_file": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].deleted_file": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].diff_refs.base_sha": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].diff_refs.start_sha": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].diff_refs.head_sha": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].mode_changed": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].a_mode": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].b_mode": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].viewer.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].viewer.collapsed": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].old_size": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].new_size": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].added_lines": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].removed_lines": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].load_collapsed_diff_url": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].view_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].context_lines_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].highlighted_diff_lines": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.diff_files[*].highlighted_diff_lines[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].highlighted_diff_lines[*].text": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].highlighted_diff_lines[*].rich_text": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].highlighted_diff_lines[*].can_receive_suggestion": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].is_fully_expanded": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.pagination.total_pages": {
|
||||
"match": "type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
{
|
||||
"consumer": {
|
||||
"name": "Merge Request Page"
|
||||
},
|
||||
"provider": {
|
||||
"name": "Merge Request Discussions Endpoint"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"description": "a request for discussions",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"path": "/discussions.json",
|
||||
"headers": {
|
||||
"Accept": "*/*"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"id": "fd73763cbcbf7b29eb8765d969a38f7d735e222a",
|
||||
"reply_id": "fd73763cbcbf7b29eb8765d969a38f7d735e222a",
|
||||
"project_id": 6954442,
|
||||
"confidential": false,
|
||||
"diff_discussion": false,
|
||||
"expanded": false,
|
||||
"for_commit": false,
|
||||
"individual_note": true,
|
||||
"resolvable": false,
|
||||
"resolved_by_push": false,
|
||||
"notes": [
|
||||
{
|
||||
"id": "76489845",
|
||||
"author": {
|
||||
"id": 1675733,
|
||||
"username": "gitlab-qa-bot",
|
||||
"name": "gitlab-qa-bot",
|
||||
"state": "active",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/8355ad0f2761367fae6b9c4fe80994b9?s=80&d=identicon",
|
||||
"show_status": false,
|
||||
"path": "/gitlab-qa-bot"
|
||||
},
|
||||
"created_at": "2022-02-22T07:06:55.038Z",
|
||||
"updated_at": "2022-02-22T07:06:55.038Z",
|
||||
"system": false,
|
||||
"noteable_id": 8333422,
|
||||
"noteable_type": "MergeRequest",
|
||||
"resolvable": false,
|
||||
"resolved": true,
|
||||
"confidential": false,
|
||||
"noteable_iid": 1,
|
||||
"note": "This is a test comment",
|
||||
"note_html": "<p data-sourcepos=\"1:1-1:22\" dir=\"auto\">This is a test comment</p>",
|
||||
"current_user": {
|
||||
"can_edit": true,
|
||||
"can_award_emoji": true,
|
||||
"can_resolve": false,
|
||||
"can_resolve_discussion": false
|
||||
},
|
||||
"is_noteable_author": true,
|
||||
"discussion_id": "fd73763cbcbf7b29eb8765d969a38f7d735e222a",
|
||||
"emoji_awardable": true,
|
||||
"report_abuse_path": "/gitlab-qa-bot/...",
|
||||
"noteable_note_url": "https://staging.gitlab.com/gitlab-qa-bot/...",
|
||||
"cached_markdown_version": 1900552,
|
||||
"human_access": "Maintainer",
|
||||
"is_contributor": false,
|
||||
"project_name": "contract-testing",
|
||||
"path": "/gitlab-qa-bot/..."
|
||||
}
|
||||
],
|
||||
"resolved": true
|
||||
}
|
||||
],
|
||||
"matchingRules": {
|
||||
"$.body": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].reply_id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].project_id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].confidential": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].diff_discussion": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].expanded": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].for_commit": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].individual_note": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].resolvable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].resolved_by_push": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body[*].notes[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.username": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.state": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.avatar_url": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.show_status": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].author.path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].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[*].notes[*].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[*].notes[*].system": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].noteable_id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].noteable_type": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].resolvable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].resolved": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].confidential": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].noteable_iid": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].note": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].note_html": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].current_user.can_edit": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].current_user.can_award_emoji": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].current_user.can_resolve": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].current_user.can_resolve_discussion": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].is_noteable_author": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].discussion_id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].emoji_awardable": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].report_abuse_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].noteable_note_url": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].cached_markdown_version": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].human_access": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].is_contributor": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].project_name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].notes[*].path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body[*].resolved": {
|
||||
"match": "type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
"consumer": {
|
||||
"name": "Merge Request Page"
|
||||
},
|
||||
"provider": {
|
||||
"name": "Merge Request Metadata Endpoint"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"description": "a request for Metadata",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"path": "/diffs_metadata.json",
|
||||
"headers": {
|
||||
"Accept": "*/*"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": {
|
||||
"real_size": "1",
|
||||
"size": 1,
|
||||
"branch_name": "testing-branch-1",
|
||||
"source_branch_exists": true,
|
||||
"target_branch_name": "master",
|
||||
"merge_request_diff": {
|
||||
"created_at": "2022-02-17T11:47:08.804Z",
|
||||
"commits_count": 1,
|
||||
"latest": true,
|
||||
"short_commit_sha": "aee1ffec",
|
||||
"base_version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773",
|
||||
"head_version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_head=true",
|
||||
"version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773",
|
||||
"compare_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773&start_sha=aee1ffec2299c0cfb17c8821e931339b73a3759f"
|
||||
},
|
||||
"latest_diff": true,
|
||||
"latest_version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs",
|
||||
"added_lines": 1,
|
||||
"removed_lines": 1,
|
||||
"render_overflow_warning": false,
|
||||
"email_patch_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1.patch",
|
||||
"plain_diff_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1.diff",
|
||||
"merge_request_diffs": [
|
||||
{
|
||||
"commits_count": 1,
|
||||
"latest": true,
|
||||
"short_commit_sha": "aee1ffec",
|
||||
"base_version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773",
|
||||
"head_version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_head=true",
|
||||
"version_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773",
|
||||
"compare_path": "/gitlab-qa-bot/contract-testing/-/merge_requests/1/diffs?diff_id=10581773&start_sha=aee1ffec2299c0cfb17c8821e931339b73a3759f"
|
||||
}
|
||||
],
|
||||
"definition_path_prefix": "/gitlab-qa-bot/contract-testing/-/blob/aee1ffec2299c0cfb17c8821e931339b73a3759f",
|
||||
"diff_files": [
|
||||
{
|
||||
"added_lines": 1,
|
||||
"removed_lines": 1,
|
||||
"new_path": "Gemfile",
|
||||
"old_path": "Gemfile",
|
||||
"new_file": false,
|
||||
"deleted_file": false,
|
||||
"submodule": false,
|
||||
"file_identifier_hash": "67d82b8716a5b6c52c7abf0b2cd99c7594ed3587",
|
||||
"file_hash": "de3150c01c3a946a6168173c4116741379fe3579"
|
||||
}
|
||||
],
|
||||
"has_conflicts": false,
|
||||
"can_merge": false,
|
||||
"project_path": "gitlab-qa-bot/contract-testing",
|
||||
"project_name": "contract-testing"
|
||||
},
|
||||
"matchingRules": {
|
||||
"$.body.real_size": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.size": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.branch_name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.source_branch_exists": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.target_branch_name": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.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.merge_request_diff.commits_count": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.latest": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.short_commit_sha": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.base_version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.head_version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diff.compare_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.latest_diff": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.latest_version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.added_lines": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.removed_lines": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.render_overflow_warning": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.email_patch_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.plain_diff_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.merge_request_diffs[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].commits_count": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].latest": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].short_commit_sha": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].base_version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].head_version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].version_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.merge_request_diffs[*].compare_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.definition_path_prefix": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files": {
|
||||
"min": 1
|
||||
},
|
||||
"$.body.diff_files[*].*": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].added_lines": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].removed_lines": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].new_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].old_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].new_file": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].deleted_file": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].submodule": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].file_identifier_hash": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.diff_files[*].file_hash": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.has_conflicts": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.can_merge": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.project_path": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.body.project_name": {
|
||||
"match": "type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
17
qa/contracts/provider/Rakefile
Normal file
17
qa/contracts/provider/Rakefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'pact/tasks/verification_task'
|
||||
|
||||
Pact::VerificationTask.new(:metadata) do |pact|
|
||||
pact.uri '../contracts/merge_request_page-merge_request_metadata_endpoint.json', pact_helper: './spec/metadata_helper.rb'
|
||||
end
|
||||
|
||||
Pact::VerificationTask.new(:discussions) do |pact|
|
||||
pact.uri '../contracts/merge_request_page-merge_request_discussions_endpoint.json', pact_helper: './spec/discussions_helper.rb'
|
||||
end
|
||||
|
||||
Pact::VerificationTask.new(:diffs) do |pact|
|
||||
pact.uri '../contracts/merge_request_page-merge_request_diffs_endpoint.json', pact_helper: './spec/diffs_helper.rb'
|
||||
end
|
||||
|
||||
task 'test:merge_request' => ['pact:verify:metadata', 'pact:verify:discussions', 'pact:verify:diffs']
|
26
qa/contracts/provider/environments/base.rb
Normal file
26
qa/contracts/provider/environments/base.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'faraday'
|
||||
|
||||
module Environments
|
||||
class Base
|
||||
attr_writer :base_url, :merge_request
|
||||
|
||||
def call(env)
|
||||
@payload
|
||||
end
|
||||
|
||||
def http(endpoint)
|
||||
Faraday.default_adapter = :net_http
|
||||
response = Faraday.get(@base_url + endpoint)
|
||||
@payload = [response.status, response.headers, [response.body]]
|
||||
self
|
||||
end
|
||||
|
||||
def merge_request(endpoint)
|
||||
if endpoint.include? '.json'
|
||||
http(@merge_request + endpoint)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
12
qa/contracts/provider/environments/local.rb
Normal file
12
qa/contracts/provider/environments/local.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative './base'
|
||||
|
||||
module Environments
|
||||
class Local < Base
|
||||
def initialize
|
||||
@base_url = ENV['CONTRACT_HOST']
|
||||
@merge_request = ENV['CONTRACT_MR']
|
||||
end
|
||||
end
|
||||
end
|
15
qa/contracts/provider/spec/diffs_helper.rb
Normal file
15
qa/contracts/provider/spec/diffs_helper.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../environments/local'
|
||||
|
||||
module DiffsHelper
|
||||
local = Environments::Local.new
|
||||
|
||||
Pact.service_provider "Merge Request Diffs Endpoint" do
|
||||
app { local.merge_request('/diffs_batch.json?page=0') }
|
||||
|
||||
honours_pact_with 'Merge Request Page' do
|
||||
pact_uri '../contracts/merge_request_page-merge_request_diffs_endpoint.json'
|
||||
end
|
||||
end
|
||||
end
|
15
qa/contracts/provider/spec/discussions_helper.rb
Normal file
15
qa/contracts/provider/spec/discussions_helper.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../environments/local'
|
||||
|
||||
module DiscussionsHelper
|
||||
local = Environments::Local.new
|
||||
|
||||
Pact.service_provider "Merge Request Discussions Endpoint" do
|
||||
app { local.merge_request('/discussions.json') }
|
||||
|
||||
honours_pact_with 'Merge Request Page' do
|
||||
pact_uri '../contracts/merge_request_page-merge_request_discussions_endpoint.json'
|
||||
end
|
||||
end
|
||||
end
|
15
qa/contracts/provider/spec/metadata_helper.rb
Normal file
15
qa/contracts/provider/spec/metadata_helper.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../environments/local'
|
||||
|
||||
module MetadataHelper
|
||||
local = Environments::Local.new
|
||||
|
||||
Pact.service_provider "Merge Request Metadata Endpoint" do
|
||||
app { local.merge_request('/diffs_metadata.json') }
|
||||
|
||||
honours_pact_with 'Merge Request Page' do
|
||||
pact_uri '../contracts/merge_request_page-merge_request_metadata_endpoint.json'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,6 +13,24 @@ RSpec.describe 'Group CI/CD settings' do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
describe 'new group runners view banner' do
|
||||
it 'displays banner' do
|
||||
visit group_settings_ci_cd_path(group)
|
||||
|
||||
expect(page).to have_content(s_('Runners|New group runners view'))
|
||||
expect(page).to have_link(href: group_runners_path(group))
|
||||
end
|
||||
|
||||
it 'does not display banner' do
|
||||
stub_feature_flags(runner_list_group_view_vue_ui: false)
|
||||
|
||||
visit group_settings_ci_cd_path(group)
|
||||
|
||||
expect(page).not_to have_content(s_('Runners|New group runners view'))
|
||||
expect(page).not_to have_link(href: group_runners_path(group))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'runners registration token' do
|
||||
let!(:token) { group.runners_token }
|
||||
|
||||
|
|
|
@ -279,6 +279,46 @@ RSpec.describe Gitlab::Database do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.all_uncached' do
|
||||
let(:base_model) do
|
||||
Class.new do
|
||||
def self.uncached
|
||||
@uncached = true
|
||||
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:model1) { Class.new(base_model) }
|
||||
let(:model2) { Class.new(base_model) }
|
||||
|
||||
before do
|
||||
allow(described_class).to receive(:database_base_models)
|
||||
.and_return({ model1: model1, model2: model2 }.with_indifferent_access)
|
||||
end
|
||||
|
||||
it 'wraps the given block in uncached calls for each primary connection', :aggregate_failures do
|
||||
expect(model1.instance_variable_get(:@uncached)).to be_nil
|
||||
expect(model2.instance_variable_get(:@uncached)).to be_nil
|
||||
|
||||
expect(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary).and_yield
|
||||
|
||||
expect(model2).to receive(:uncached).and_call_original
|
||||
expect(model1).to receive(:uncached).and_call_original
|
||||
|
||||
yielded_to_block = false
|
||||
described_class.all_uncached do
|
||||
expect(model1.instance_variable_get(:@uncached)).to be(true)
|
||||
expect(model2.instance_variable_get(:@uncached)).to be(true)
|
||||
|
||||
yielded_to_block = true
|
||||
end
|
||||
|
||||
expect(yielded_to_block).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.read_only?' do
|
||||
it 'returns false' do
|
||||
expect(described_class.read_only?).to eq(false)
|
||||
|
|
|
@ -432,6 +432,12 @@ RSpec.describe WebHook do
|
|||
|
||||
expect(hook).not_to be_temporarily_disabled
|
||||
end
|
||||
|
||||
it 'can ignore the feature flag' do
|
||||
stub_feature_flags(web_hooks_disable_failed: false)
|
||||
|
||||
expect(hook).to be_temporarily_disabled(ignore_flag: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -454,6 +460,12 @@ RSpec.describe WebHook do
|
|||
|
||||
expect(hook).not_to be_permanently_disabled
|
||||
end
|
||||
|
||||
it 'can ignore the feature flag' do
|
||||
stub_feature_flags(web_hooks_disable_failed: false)
|
||||
|
||||
expect(hook).to be_permanently_disabled(ignore_flag: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1755,4 +1755,100 @@ RSpec.describe ProjectPolicy do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'register_project_runners' do
|
||||
context 'admin' do
|
||||
let(:current_user) { admin }
|
||||
|
||||
context 'when admin mode is enabled', :enable_admin_mode do
|
||||
context 'with runner_registration_control FF disabled' do
|
||||
before do
|
||||
stub_feature_flags(runner_registration_control: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
end
|
||||
|
||||
context 'with runner_registration_control FF enabled' do
|
||||
before do
|
||||
stub_feature_flags(runner_registration_control: true)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
|
||||
context 'with project runner registration disabled' do
|
||||
before do
|
||||
stub_application_setting(valid_runner_registrars: ['group'])
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when admin mode is disabled' do
|
||||
it { is_expected.to be_disallowed(:register_project_runners) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with owner' do
|
||||
let(:current_user) { owner }
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
|
||||
context 'with runner_registration_control FF disabled' do
|
||||
before do
|
||||
stub_feature_flags(runner_registration_control: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
end
|
||||
|
||||
context 'with runner_registration_control FF enabled' do
|
||||
before do
|
||||
stub_feature_flags(runner_registration_control: true)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
|
||||
context 'with project runner registration disabled' do
|
||||
before do
|
||||
stub_application_setting(valid_runner_registrars: ['group'])
|
||||
end
|
||||
|
||||
it { is_expected.to be_disallowed(:register_project_runners) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with maintainer' do
|
||||
let(:current_user) { maintainer }
|
||||
|
||||
it { is_expected.to be_allowed(:register_project_runners) }
|
||||
end
|
||||
|
||||
context 'with reporter' do
|
||||
let(:current_user) { reporter }
|
||||
|
||||
it { is_expected.to be_disallowed(:register_project_runners) }
|
||||
end
|
||||
|
||||
context 'with guest' do
|
||||
let(:current_user) { guest }
|
||||
|
||||
it { is_expected.to be_disallowed(:register_project_runners) }
|
||||
end
|
||||
|
||||
context 'with non member' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it { is_expected.to be_disallowed(:register_project_runners) }
|
||||
end
|
||||
|
||||
context 'with anonymous' do
|
||||
let(:current_user) { nil }
|
||||
|
||||
it { is_expected.to be_disallowed(:register_project_runners) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -95,12 +95,37 @@ RSpec.describe WebHooks::LogExecutionService do
|
|||
it 'resets the failure count' do
|
||||
expect { service.execute }.to change(project_hook, :recent_failures).to(0)
|
||||
end
|
||||
|
||||
it 'sends a message to AuthLogger if the hook as not previously enabled' do
|
||||
project_hook.update!(recent_failures: ::WebHook::FAILURE_THRESHOLD + 1)
|
||||
|
||||
expect(Gitlab::AuthLogger).to receive(:info).with include(
|
||||
message: 'WebHook change active_state',
|
||||
# identification
|
||||
hook_id: project_hook.id,
|
||||
hook_type: project_hook.type,
|
||||
project_id: project_hook.project_id,
|
||||
group_id: nil,
|
||||
# relevant data
|
||||
prev_state: :permanently_disabled,
|
||||
new_state: :enabled,
|
||||
duration: 1.2,
|
||||
response_status: '200',
|
||||
recent_hook_failures: 0
|
||||
)
|
||||
|
||||
service.execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when response_category is :failed' do
|
||||
let(:response_category) { :failed }
|
||||
|
||||
before do
|
||||
data[:response_status] = '400'
|
||||
end
|
||||
|
||||
it 'increments the failure count' do
|
||||
expect { service.execute }.to change(project_hook, :recent_failures).by(1)
|
||||
end
|
||||
|
@ -127,11 +152,36 @@ RSpec.describe WebHooks::LogExecutionService do
|
|||
expect { service.execute }.not_to change(project_hook, :recent_failures)
|
||||
end
|
||||
end
|
||||
|
||||
it 'sends a message to AuthLogger if the state would change' do
|
||||
project_hook.update!(recent_failures: ::WebHook::FAILURE_THRESHOLD)
|
||||
|
||||
expect(Gitlab::AuthLogger).to receive(:info).with include(
|
||||
message: 'WebHook change active_state',
|
||||
# identification
|
||||
hook_id: project_hook.id,
|
||||
hook_type: project_hook.type,
|
||||
project_id: project_hook.project_id,
|
||||
group_id: nil,
|
||||
# relevant data
|
||||
prev_state: :enabled,
|
||||
new_state: :permanently_disabled,
|
||||
duration: (be > 0),
|
||||
response_status: data[:response_status],
|
||||
recent_hook_failures: ::WebHook::FAILURE_THRESHOLD + 1
|
||||
)
|
||||
|
||||
service.execute
|
||||
end
|
||||
end
|
||||
|
||||
context 'when response_category is :error' do
|
||||
let(:response_category) { :error }
|
||||
|
||||
before do
|
||||
data[:response_status] = '500'
|
||||
end
|
||||
|
||||
it 'does not increment the failure count' do
|
||||
expect { service.execute }.not_to change(project_hook, :recent_failures)
|
||||
end
|
||||
|
@ -144,6 +194,25 @@ RSpec.describe WebHooks::LogExecutionService do
|
|||
expect { service.execute }.to change(project_hook, :backoff_count).by(1)
|
||||
end
|
||||
|
||||
it 'sends a message to AuthLogger if the state would change' do
|
||||
expect(Gitlab::AuthLogger).to receive(:info).with include(
|
||||
message: 'WebHook change active_state',
|
||||
# identification
|
||||
hook_id: project_hook.id,
|
||||
hook_type: project_hook.type,
|
||||
project_id: project_hook.project_id,
|
||||
group_id: nil,
|
||||
# relevant data
|
||||
prev_state: :enabled,
|
||||
new_state: :temporarily_disabled,
|
||||
duration: (be > 0),
|
||||
response_status: data[:response_status],
|
||||
recent_hook_failures: 0
|
||||
)
|
||||
|
||||
service.execute
|
||||
end
|
||||
|
||||
context 'when the previous cool-off was near the maximum' do
|
||||
before do
|
||||
project_hook.update!(disabled_until: 5.minutes.ago, backoff_count: 8)
|
||||
|
|
|
@ -11,12 +11,14 @@ RSpec.describe 'projects/runners/specific_runners.html.haml' do
|
|||
@project = project
|
||||
@assignable_runners = []
|
||||
@project_runners = []
|
||||
allow(view).to receive(:current_user).and_return(user)
|
||||
allow(view).to receive(:reset_registration_token_namespace_project_settings_ci_cd_path).and_return('banana_url')
|
||||
end
|
||||
|
||||
context 'when project runner registration is allowed' do
|
||||
before do
|
||||
stub_application_setting(valid_runner_registrars: ['project'])
|
||||
allow(view).to receive(:can?).with(user, :register_project_runners, project).and_return(true)
|
||||
end
|
||||
|
||||
it 'enables the Remove project button for a project' do
|
||||
|
@ -32,7 +34,7 @@ RSpec.describe 'projects/runners/specific_runners.html.haml' do
|
|||
stub_application_setting(valid_runner_registrars: ['group'])
|
||||
end
|
||||
|
||||
it 'does not enable the the Remove project button for a project' do
|
||||
it 'does not enable the Remove project button for a project' do
|
||||
render 'projects/runners/specific_runners', project: project
|
||||
|
||||
expect(rendered).to have_content 'Please contact an admin to register runners.'
|
||||
|
|
Loading…
Reference in a new issue