Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0ecdc32a42
commit
bd5eb9f020
|
@ -92,30 +92,4 @@ variables:
|
|||
GIT_CLONE_PATH: "/builds/gitlab-org-forks/${CI_PROJECT_NAME}"
|
||||
|
||||
include:
|
||||
- local: .gitlab/ci/build-images.gitlab-ci.yml
|
||||
- local: .gitlab/ci/cache-repo.gitlab-ci.yml
|
||||
- local: .gitlab/ci/cng.gitlab-ci.yml
|
||||
- local: .gitlab/ci/docs.gitlab-ci.yml
|
||||
- local: .gitlab/ci/frontend.gitlab-ci.yml
|
||||
- local: .gitlab/ci/global.gitlab-ci.yml
|
||||
- local: .gitlab/ci/memory.gitlab-ci.yml
|
||||
- local: .gitlab/ci/pages.gitlab-ci.yml
|
||||
- local: .gitlab/ci/qa.gitlab-ci.yml
|
||||
- local: .gitlab/ci/reports.gitlab-ci.yml
|
||||
- local: .gitlab/ci/rails.gitlab-ci.yml
|
||||
- local: .gitlab/ci/vendored-gems.gitlab-ci.yml
|
||||
- local: .gitlab/ci/review.gitlab-ci.yml
|
||||
- local: .gitlab/ci/rules.gitlab-ci.yml
|
||||
- local: .gitlab/ci/setup.gitlab-ci.yml
|
||||
- local: .gitlab/ci/dev-fixtures.gitlab-ci.yml
|
||||
- local: .gitlab/ci/test-metadata.gitlab-ci.yml
|
||||
- local: .gitlab/ci/yaml.gitlab-ci.yml
|
||||
- local: .gitlab/ci/releases.gitlab-ci.yml
|
||||
- local: .gitlab/ci/notify.gitlab-ci.yml
|
||||
- local: .gitlab/ci/dast.gitlab-ci.yml
|
||||
- local: .gitlab/ci/workhorse.gitlab-ci.yml
|
||||
- local: .gitlab/ci/graphql.gitlab-ci.yml
|
||||
# switch the remote include to a local include until this is resolved:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/327299
|
||||
# - remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/.gitlab-ci-template.yml'
|
||||
- local: .gitlab/ci/untamper-my-lockfile.yml
|
||||
- local: .gitlab/ci/*.gitlab-ci.yml
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
# current_user - which user is requesting groups
|
||||
# params:
|
||||
# with_shared: boolean (optional)
|
||||
# shared_visible_only: boolean (optional)
|
||||
# shared_min_access_level: integer (optional)
|
||||
# skip_groups: array of integers (optional)
|
||||
#
|
||||
|
@ -37,26 +38,36 @@ module Projects
|
|||
Ability.allowed?(current_user, :read_project, project)
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def all_groups
|
||||
groups = []
|
||||
groups << project.group.self_and_ancestors if project.group
|
||||
groups += [project.group.self_and_ancestors] if project.group
|
||||
groups += with_shared_groups if params[:with_shared]
|
||||
|
||||
if params[:with_shared]
|
||||
shared_groups = project.invited_groups
|
||||
return [Group.none] if groups.compact.empty?
|
||||
|
||||
if params[:shared_min_access_level]
|
||||
shared_groups = shared_groups.where(
|
||||
'project_group_links.group_access >= ?', params[:shared_min_access_level]
|
||||
)
|
||||
end
|
||||
|
||||
groups << shared_groups
|
||||
end
|
||||
|
||||
groups << Group.none if groups.compact.empty?
|
||||
groups
|
||||
end
|
||||
|
||||
def with_shared_groups
|
||||
shared_groups = project.invited_groups
|
||||
shared_groups = apply_min_access_level(shared_groups)
|
||||
|
||||
if params[:shared_visible_only]
|
||||
[
|
||||
shared_groups.public_to_user(current_user),
|
||||
shared_groups.for_authorized_group_members(current_user&.id)
|
||||
]
|
||||
else
|
||||
[shared_groups]
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def apply_min_access_level(groups)
|
||||
return groups unless params[:shared_min_access_level]
|
||||
|
||||
groups.where('project_group_links.group_access >= ?', params[:shared_min_access_level])
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def exclude_group_ids(groups)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module MergeRequests
|
||||
class SetDraft < Base
|
||||
graphql_name 'MergeRequestSetDraft'
|
||||
|
||||
argument :draft,
|
||||
GraphQL::BOOLEAN_TYPE,
|
||||
required: true,
|
||||
description: <<~DESC
|
||||
Whether or not to set the merge request as a draft.
|
||||
DESC
|
||||
|
||||
def resolve(project_path:, iid:, draft: nil)
|
||||
merge_request = authorized_find!(project_path: project_path, iid: iid)
|
||||
project = merge_request.project
|
||||
|
||||
::MergeRequests::UpdateService.new(project, current_user, wip_event: wip_event(draft))
|
||||
.execute(merge_request)
|
||||
|
||||
{
|
||||
merge_request: merge_request,
|
||||
errors: errors_on_object(merge_request)
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def wip_event(wip)
|
||||
wip ? 'wip' : 'unwip'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -54,6 +54,9 @@ module Types
|
|||
field :target_branch, GraphQL::STRING_TYPE, null: false,
|
||||
description: 'Target branch of the merge request.'
|
||||
field :work_in_progress, GraphQL::BOOLEAN_TYPE, method: :work_in_progress?, null: false,
|
||||
deprecated: { reason: 'Use `draft`', milestone: '13.12' },
|
||||
description: 'Indicates if the merge request is a draft.'
|
||||
field :draft, GraphQL::BOOLEAN_TYPE, method: :draft?, null: false,
|
||||
description: 'Indicates if the merge request is a draft.'
|
||||
field :merge_when_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true,
|
||||
description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).'
|
||||
|
|
|
@ -52,7 +52,10 @@ module Types
|
|||
mount_mutation Mutations::MergeRequests::SetLocked
|
||||
mount_mutation Mutations::MergeRequests::SetMilestone
|
||||
mount_mutation Mutations::MergeRequests::SetSubscription
|
||||
mount_mutation Mutations::MergeRequests::SetWip, calls_gitaly: true
|
||||
mount_mutation Mutations::MergeRequests::SetWip,
|
||||
calls_gitaly: true,
|
||||
deprecated: { reason: 'Use mergeRequestSetDraft', milestone: '13.12' }
|
||||
mount_mutation Mutations::MergeRequests::SetDraft, calls_gitaly: true
|
||||
mount_mutation Mutations::MergeRequests::SetAssignees
|
||||
mount_mutation Mutations::MergeRequests::ReviewerRereview
|
||||
mount_mutation Mutations::Metrics::Dashboard::Annotations::Create
|
||||
|
|
|
@ -50,6 +50,11 @@ module LearnGitlabHelper
|
|||
}
|
||||
end
|
||||
|
||||
def learn_gitlab_onboarding_available?(project)
|
||||
OnboardingProgress.onboarding?(project.namespace) &&
|
||||
LearnGitlab::Project.new(current_user).available?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def action_urls
|
||||
|
@ -64,9 +69,4 @@ module LearnGitlabHelper
|
|||
def onboarding_progress(project)
|
||||
OnboardingProgress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord
|
||||
end
|
||||
|
||||
def learn_gitlab_onboarding_available?(project)
|
||||
OnboardingProgress.onboarding?(project.namespace) &&
|
||||
LearnGitlab::Project.new(current_user).available?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,7 @@ module Enums
|
|||
unknown_failure: 0,
|
||||
config_error: 1,
|
||||
external_validation_failure: 2,
|
||||
user_not_verified: 3,
|
||||
activity_limit_exceeded: 20,
|
||||
size_limit_exceeded: 21,
|
||||
job_activity_limit_exceeded: 22,
|
||||
|
|
|
@ -11,6 +11,7 @@ module Ci
|
|||
{ unknown_failure: 'The reason for the pipeline failure is unknown.',
|
||||
config_error: 'The pipeline failed due to an error on the CI/CD configuration file.',
|
||||
external_validation_failure: 'The external pipeline validation failed.',
|
||||
user_not_verified: 'The pipeline failed due to the user not being verified',
|
||||
activity_limit_exceeded: 'The pipeline activity limit was exceeded.',
|
||||
size_limit_exceeded: 'The pipeline size limit was exceeded.',
|
||||
job_activity_limit_exceeded: 'The pipeline job activity limit was exceeded.',
|
||||
|
|
|
@ -29,11 +29,9 @@ module Ci
|
|||
build_pipeline.tap do |pipeline|
|
||||
pipeline.stages << terminal_stage_seed(pipeline).to_resource
|
||||
|
||||
if Feature.enabled?(:ci_pipeline_ensure_iid_on_save, pipeline.project, default_enabled: :yaml)
|
||||
# Project iid must be called outside a transaction, so we ensure it is set here
|
||||
# otherwise it may be set within the save! which it will lock the InternalId row for the whole transaction
|
||||
pipeline.ensure_project_iid!
|
||||
end
|
||||
# Project iid must be called outside a transaction, so we ensure it is set here
|
||||
# otherwise it may be set within the save! which it will lock the InternalId row for the whole transaction
|
||||
pipeline.ensure_project_iid!
|
||||
|
||||
pipeline.save!
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add shared_visible_only option to project's groups API
|
||||
merge_request: 61118
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Deprecate SetWip GraphQL mutation and add SetDraft mutation
|
||||
merge_request: 60803
|
||||
author:
|
||||
type: deprecated
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Ensure project iid is set before saving pipeline from web terminal
|
||||
merge_request: 61311
|
||||
author:
|
||||
type: performance
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: ci_pipeline_ensure_iid_on_save
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59341
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327662
|
||||
name: ci_require_credit_card_on_free_plan
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330104
|
||||
milestone: '13.12'
|
||||
type: development
|
||||
group: group::code review
|
||||
group: group::continuous integration
|
||||
default_enabled: false
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: ci_require_credit_card_on_trial_plan
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330105
|
||||
milestone: '13.12'
|
||||
type: development
|
||||
group: group::continuous integration
|
||||
default_enabled: false
|
|
@ -8,7 +8,8 @@ product_category: collection
|
|||
value_type: string
|
||||
status: data_available
|
||||
time_frame: none
|
||||
data_source:
|
||||
data_source: ruby
|
||||
instrumentation_class: 'Gitlab::Usage::Metrics::Instrumentations::HostnameMetric'
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
@ -2781,6 +2781,27 @@ Input type: `MergeRequestSetAssigneesInput`
|
|||
| <a id="mutationmergerequestsetassigneeserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationmergerequestsetassigneesmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | The merge request after mutation. |
|
||||
|
||||
### `Mutation.mergeRequestSetDraft`
|
||||
|
||||
Input type: `MergeRequestSetDraftInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationmergerequestsetdraftclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationmergerequestsetdraftdraft"></a>`draft` | [`Boolean!`](#boolean) | Whether or not to set the merge request as a draft. |
|
||||
| <a id="mutationmergerequestsetdraftiid"></a>`iid` | [`String!`](#string) | The IID of the merge request to mutate. |
|
||||
| <a id="mutationmergerequestsetdraftprojectpath"></a>`projectPath` | [`ID!`](#id) | The project the merge request to mutate is in. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationmergerequestsetdraftclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationmergerequestsetdrafterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationmergerequestsetdraftmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | The merge request after mutation. |
|
||||
|
||||
### `Mutation.mergeRequestSetLabels`
|
||||
|
||||
Input type: `MergeRequestSetLabelsInput`
|
||||
|
@ -2868,6 +2889,10 @@ Input type: `MergeRequestSetSubscriptionInput`
|
|||
|
||||
### `Mutation.mergeRequestSetWip`
|
||||
|
||||
WARNING:
|
||||
**Deprecated** in 13.12.
|
||||
Use mergeRequestSetDraft.
|
||||
|
||||
Input type: `MergeRequestSetWipInput`
|
||||
|
||||
#### Arguments
|
||||
|
@ -9668,6 +9693,7 @@ Maven metadata.
|
|||
| <a id="mergerequestdiscussions"></a>`discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. (see [Connections](#connections)) |
|
||||
| <a id="mergerequestdivergedfromtargetbranch"></a>`divergedFromTargetBranch` | [`Boolean!`](#boolean) | Indicates if the source branch is behind the target branch. |
|
||||
| <a id="mergerequestdownvotes"></a>`downvotes` | [`Int!`](#int) | Number of downvotes for the merge request. |
|
||||
| <a id="mergerequestdraft"></a>`draft` | [`Boolean!`](#boolean) | Indicates if the merge request is a draft. |
|
||||
| <a id="mergerequestforceremovesourcebranch"></a>`forceRemoveSourceBranch` | [`Boolean`](#boolean) | Indicates if the project settings will lead to source branch deletion after merge. |
|
||||
| <a id="mergerequesthasci"></a>`hasCi` | [`Boolean!`](#boolean) | Indicates if the merge request has CI. |
|
||||
| <a id="mergerequesthassecurityreports"></a>`hasSecurityReports` | [`Boolean!`](#boolean) | Indicates if the source branch has any security reports. |
|
||||
|
@ -9723,7 +9749,7 @@ Maven metadata.
|
|||
| <a id="mergerequestusernotescount"></a>`userNotesCount` | [`Int`](#int) | User notes count of the merge request. |
|
||||
| <a id="mergerequestuserpermissions"></a>`userPermissions` | [`MergeRequestPermissions!`](#mergerequestpermissions) | Permissions for the current user on the resource. |
|
||||
| <a id="mergerequestweburl"></a>`webUrl` | [`String`](#string) | Web URL of the merge request. |
|
||||
| <a id="mergerequestworkinprogress"></a>`workInProgress` | [`Boolean!`](#boolean) | Indicates if the merge request is a draft. |
|
||||
| <a id="mergerequestworkinprogress"></a>`workInProgress` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in 13.12. Use `draft`. |
|
||||
|
||||
#### Fields with arguments
|
||||
|
||||
|
|
|
@ -1072,6 +1072,7 @@ GET /projects/:id/groups
|
|||
| `skip_groups` | array of integers | **{dotted-circle}** No | Skip the group IDs passed. |
|
||||
| `with_shared` | boolean | **{dotted-circle}** No | Include projects shared with this group. Default is `false`. |
|
||||
| `shared_min_access_level` | integer | **{dotted-circle}** No | Limit to shared groups with at least this [access level](members.md#valid-access-levels). |
|
||||
| `shared_visible_only` | boolean | **{dotted-circle}** No | Limit to shared groups user has access to. |
|
||||
|
||||
```json
|
||||
[
|
||||
|
|
|
@ -1185,7 +1185,7 @@ are returned as the result of the mutation.
|
|||
The service-oriented architecture in GitLab means that most mutations call a Create, Delete, or Update
|
||||
service, for example `UpdateMergeRequestService`.
|
||||
For Update mutations, you might want to only update one aspect of an object, and thus only need a
|
||||
_fine-grained_ mutation, for example `MergeRequest::SetWip`.
|
||||
_fine-grained_ mutation, for example `MergeRequest::SetDraft`.
|
||||
|
||||
It's acceptable to have both fine-grained mutations and coarse-grained mutations, but be aware
|
||||
that too many fine-grained mutations can lead to organizational challenges in maintainability, code
|
||||
|
@ -1281,7 +1281,7 @@ end
|
|||
[input type](https://graphql.org/learn/schema/#input-types).
|
||||
|
||||
For example, the
|
||||
[`mergeRequestSetWip` mutation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/merge_requests/set_wip.rb)
|
||||
[`mergeRequestSetDraft` mutation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/merge_requests/set_draft.rb)
|
||||
defines these arguments (some
|
||||
[through inheritance](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/merge_requests/base.rb)):
|
||||
|
||||
|
@ -1294,17 +1294,16 @@ argument :iid, GraphQL::STRING_TYPE,
|
|||
required: true,
|
||||
description: "The IID of the merge request to mutate."
|
||||
|
||||
argument :wip,
|
||||
argument :draft,
|
||||
GraphQL::BOOLEAN_TYPE,
|
||||
required: false,
|
||||
description: <<~DESC
|
||||
Whether or not to set the merge request as a WIP.
|
||||
If not passed, the value will be toggled.
|
||||
DESC
|
||||
Whether or not to set the merge request as a draft.
|
||||
DESC
|
||||
```
|
||||
|
||||
These arguments automatically generate an input type called
|
||||
`MergeRequestSetWipInput` with the 3 arguments we specified and the
|
||||
`MergeRequestSetDraftInput` with the 3 arguments we specified and the
|
||||
`clientMutationId`.
|
||||
|
||||
### Object identifier arguments
|
||||
|
@ -1341,7 +1340,7 @@ From here, we can call the service that modifies the resource.
|
|||
|
||||
The `resolve` method should then return a hash with the same field
|
||||
names as defined on the mutation including an `errors` array. For example,
|
||||
the `Mutations::MergeRequests::SetWip` defines a `merge_request`
|
||||
the `Mutations::MergeRequests::SetDraft` defines a `merge_request`
|
||||
field:
|
||||
|
||||
```ruby
|
||||
|
@ -1379,13 +1378,13 @@ module Types
|
|||
|
||||
graphql_name "Mutation"
|
||||
|
||||
mount_mutation Mutations::MergeRequests::SetWip
|
||||
mount_mutation Mutations::MergeRequests::SetDraft
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Generates a field called `mergeRequestSetWip` that
|
||||
`Mutations::MergeRequests::SetWip` to be resolved.
|
||||
Generates a field called `mergeRequestSetDraft` that
|
||||
`Mutations::MergeRequests::SetDraft` to be resolved.
|
||||
|
||||
### Authorizing resources
|
||||
|
||||
|
@ -1395,8 +1394,8 @@ To authorize resources inside a mutation, we first provide the required
|
|||
```ruby
|
||||
module Mutations
|
||||
module MergeRequests
|
||||
class SetWip < Base
|
||||
graphql_name 'MergeRequestSetWip'
|
||||
class SetDraft < Base
|
||||
graphql_name 'MergeRequestSetDraft'
|
||||
|
||||
authorize :update_merge_request
|
||||
end
|
||||
|
|
|
@ -66,7 +66,9 @@ frequency to the `production` environment. The environment must be part of the
|
|||
[production deployment tier](../../ci/environments/index.md#deployment-tier-of-environments)
|
||||
for its deployment information to appear on the graphs.
|
||||
|
||||
![Deployment frequency](img/deployment_frequency_chart_v13_8.png)
|
||||
![Deployment frequency](img/deployment_frequency_charts_v13_12.png)
|
||||
|
||||
These charts are available for both groups and projects.
|
||||
|
||||
### Lead time charts **(ULTIMATE)**
|
||||
|
||||
|
@ -82,3 +84,5 @@ processes.
|
|||
|
||||
For time periods in which no merge requests were deployed, the charts render a
|
||||
red, dashed line.
|
||||
|
||||
These charts are only available for projects.
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB |
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
|
@ -49,3 +49,21 @@ file is in your default branch (usually `master`).
|
|||
|
||||
NOTE:
|
||||
The Web IDE does not support `.gitattribute` files, but it's [planned for a future release](https://gitlab.com/gitlab-org/gitlab/-/issues/22014).
|
||||
|
||||
## Configure maximum file size for highlighting
|
||||
|
||||
You can configure the maximum size of the file to be highlighted.
|
||||
|
||||
The file size is measured in kilobytes, and is set to a default of `512 KB`. Any file _over_ the file size is rendered in plain text.
|
||||
|
||||
1. Open the [`gitlab.yml`](https://gitlab.com/gitlab-org/gitlab-foss/blob/master/config/gitlab.yml.example) configuration file.
|
||||
|
||||
1. Add this section, replacing `maximum_text_highlight_size_kilobytes` with the value you want.
|
||||
|
||||
```yaml
|
||||
gitlab:
|
||||
extra:
|
||||
## Maximum file size for syntax highlighting
|
||||
## https://docs.gitlab.com/ee/user/project/highlighting.html
|
||||
maximum_text_highlight_size_kilobytes: 512
|
||||
```
|
||||
|
|
|
@ -101,7 +101,7 @@ assigned to them if they created the issue themselves.
|
|||
Often, multiple people work on the same issue together. This can be difficult
|
||||
to track in large teams where there is shared ownership of an issue.
|
||||
|
||||
In [GitLab Starter](https://about.gitlab.com/pricing/), you can
|
||||
To help with this, you can use GitLab to
|
||||
[assign multiple people](multiple_assignees_for_issues.md) to an issue.
|
||||
|
||||
### Epic **(PREMIUM)**
|
||||
|
|
|
@ -618,6 +618,8 @@ module API
|
|||
optional :skip_groups, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of group ids to exclude from list'
|
||||
optional :with_shared, type: Boolean, default: false,
|
||||
desc: 'Include shared groups'
|
||||
optional :shared_visible_only, type: Boolean, default: false,
|
||||
desc: 'Limit to shared groups user has access to'
|
||||
optional :shared_min_access_level, type: Integer, values: Gitlab::Access.all_values,
|
||||
desc: 'Limit returned shared groups by minimum access level to the project'
|
||||
use :pagination
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Usage
|
||||
module Metrics
|
||||
module Instrumentations
|
||||
class HostnameMetric < GenericMetric
|
||||
value do
|
||||
Gitlab.config.gitlab.host
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5613,6 +5613,9 @@ msgstr ""
|
|||
msgid "CICDAnalytics|All time"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICDAnalytics|Deployment frequency"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICDAnalytics|Projects with releases"
|
||||
msgstr ""
|
||||
|
||||
|
@ -9238,9 +9241,6 @@ msgstr ""
|
|||
msgid "Create Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create Value Stream"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create a GitLab account first, and then connect it to your %{label} account."
|
||||
msgstr ""
|
||||
|
||||
|
@ -19292,6 +19292,12 @@ msgstr ""
|
|||
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|Creating your onboarding experience..."
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|Ok, let's go"
|
||||
msgstr ""
|
||||
|
||||
msgid "LearnGitlab|Trial only"
|
||||
msgstr ""
|
||||
|
||||
|
@ -34667,6 +34673,9 @@ msgstr ""
|
|||
msgid "Upload file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload license"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload object map"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe Projects::GroupsFinder do
|
|||
let_it_be(:root_group) { create(:group, :public) }
|
||||
let_it_be(:project_group) { create(:group, :public, parent: root_group) }
|
||||
let_it_be(:shared_group_with_dev_access) { create(:group, :private, parent: root_group) }
|
||||
let_it_be(:shared_group_with_reporter_access) { create(:group, :private) }
|
||||
let_it_be(:shared_group_with_reporter_access) { create(:group, :public) }
|
||||
|
||||
let_it_be(:public_project) { create(:project, :public, group: project_group) }
|
||||
let_it_be(:private_project) { create(:project, :private, group: project_group) }
|
||||
|
@ -53,6 +53,24 @@ RSpec.describe Projects::GroupsFinder do
|
|||
is_expected.to match_array([project_group, root_group, shared_group_with_dev_access])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when shared_visible_only is on' do
|
||||
let(:params) { super().merge(shared_visible_only: true) }
|
||||
|
||||
it 'returns ancestor and public shared groups' do
|
||||
is_expected.to match_array([project_group, root_group, shared_group_with_reporter_access])
|
||||
end
|
||||
|
||||
context 'when user has access to the private shared group' do
|
||||
before do
|
||||
shared_group_with_dev_access.add_guest(current_user)
|
||||
end
|
||||
|
||||
it 'returns ancestor and shared groups user has access to' do
|
||||
is_expected.to match_array([project_group, root_group, shared_group_with_reporter_access, shared_group_with_dev_access])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when skip group option is on' do
|
||||
|
@ -74,6 +92,19 @@ RSpec.describe Projects::GroupsFinder do
|
|||
it 'returns ancestor groups for this project' do
|
||||
is_expected.to match_array([project_group, root_group])
|
||||
end
|
||||
|
||||
context 'when visible shared groups are requested' do
|
||||
let(:params) do
|
||||
{
|
||||
with_shared: true,
|
||||
shared_visible_only: true
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns ancestor groups and public shared groups for this project' do
|
||||
is_expected.to match_array([project_group, root_group, shared_group_with_reporter_access])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Mutations::MergeRequests::SetDraft do
|
||||
let_it_be(:merge_request) { create(:merge_request) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
|
||||
|
||||
specify { expect(described_class).to require_graphql_authorizations(:update_merge_request) }
|
||||
|
||||
describe '#resolve' do
|
||||
let(:draft) { true }
|
||||
let(:mutated_merge_request) { subject[:merge_request] }
|
||||
|
||||
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, draft: draft) }
|
||||
|
||||
it_behaves_like 'permission level for merge request mutation is correctly verified'
|
||||
|
||||
context 'when the user can update the merge request' do
|
||||
before do
|
||||
merge_request.project.add_developer(user)
|
||||
end
|
||||
|
||||
it 'returns the merge request as a draft' do
|
||||
expect(mutated_merge_request).to eq(merge_request)
|
||||
expect(mutated_merge_request).to be_draft
|
||||
expect(subject[:errors]).to be_empty
|
||||
end
|
||||
|
||||
it 'returns errors if/when merge request could not be updated' do
|
||||
# Make the merge request invalid
|
||||
merge_request.allow_broken = true
|
||||
merge_request.update!(source_project: nil)
|
||||
|
||||
expect(subject[:errors]).not_to be_empty
|
||||
end
|
||||
|
||||
context 'when passing draft as false' do
|
||||
let(:draft) { false }
|
||||
|
||||
it 'removes `Draft` from the title' do
|
||||
merge_request.update!(title: "Draft: working on it")
|
||||
|
||||
expect(mutated_merge_request).not_to be_draft
|
||||
end
|
||||
|
||||
it 'does not do anything if the title did not start with draft' do
|
||||
expect(mutated_merge_request).not_to be_draft
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,7 +16,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
|
|||
notes discussions user_permissions id iid title title_html description
|
||||
description_html state created_at updated_at source_project target_project
|
||||
project project_id source_project_id target_project_id source_branch
|
||||
target_branch work_in_progress merge_when_pipeline_succeeds diff_head_sha
|
||||
target_branch work_in_progress draft merge_when_pipeline_succeeds diff_head_sha
|
||||
merge_commit_sha user_notes_count user_discussions_count should_remove_source_branch
|
||||
diff_refs diff_stats diff_stats_summary
|
||||
force_remove_source_branch merge_status in_progress_merge_commit_sha
|
||||
|
|
|
@ -3,8 +3,16 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Types::MutationType do
|
||||
it 'is expected to have the MergeRequestSetWip' do
|
||||
expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetWip)
|
||||
it 'is expected to have the deprecated MergeRequestSetWip' do
|
||||
field = get_field('MergeRequestSetWip')
|
||||
|
||||
expect(field).to be_present
|
||||
expect(field.deprecation_reason).to be_present
|
||||
expect(field.resolver).to eq(Mutations::MergeRequests::SetWip)
|
||||
end
|
||||
|
||||
it 'is expected to have the MergeRequestSetDraft' do
|
||||
expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetDraft)
|
||||
end
|
||||
|
||||
describe 'deprecated and aliased mutations' do
|
||||
|
@ -27,9 +35,9 @@ RSpec.describe Types::MutationType do
|
|||
it { expect(alias_field.resolver.fields).to eq(canonical_field.resolver.fields) }
|
||||
it { expect(alias_field.resolver.arguments).to eq(canonical_field.resolver.arguments) }
|
||||
end
|
||||
end
|
||||
|
||||
def get_field(name)
|
||||
described_class.fields[GraphqlHelpers.fieldnamerize(name)]
|
||||
end
|
||||
def get_field(name)
|
||||
described_class.fields[GraphqlHelpers.fieldnamerize(name)]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::HostnameMetric do
|
||||
it_behaves_like 'a correct instrumented metric value', { time_frame: 'none', data_source: 'ruby' }, Gitlab.config.gitlab.host
|
||||
end
|
|
@ -19,6 +19,7 @@ RSpec.describe Gitlab::UsageDataMetrics do
|
|||
context 'whith instrumentation_class' do
|
||||
it 'includes top level keys' do
|
||||
expect(subject).to include(:uuid)
|
||||
expect(subject).to include(:hostname)
|
||||
end
|
||||
|
||||
it 'includes counts keys' do
|
||||
|
|
|
@ -1683,7 +1683,7 @@ RSpec.describe API::Projects do
|
|||
let_it_be(:root_group) { create(:group, :public, name: 'root group') }
|
||||
let_it_be(:project_group) { create(:group, :public, parent: root_group, name: 'project group') }
|
||||
let_it_be(:shared_group_with_dev_access) { create(:group, :private, parent: root_group, name: 'shared group') }
|
||||
let_it_be(:shared_group_with_reporter_access) { create(:group, :private) }
|
||||
let_it_be(:shared_group_with_reporter_access) { create(:group, :public) }
|
||||
let_it_be(:private_project) { create(:project, :private, group: project_group) }
|
||||
let_it_be(:public_project) { create(:project, :public, group: project_group) }
|
||||
|
||||
|
@ -1765,6 +1765,14 @@ RSpec.describe API::Projects do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when shared_visible_only is on' do
|
||||
let(:params) { super().merge(shared_visible_only: true) }
|
||||
|
||||
it_behaves_like 'successful groups response' do
|
||||
let(:expected_groups) { [root_group, project_group, shared_group_with_reporter_access] }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when search by shared group name' do
|
||||
let(:params) { super().merge(search: 'shared') }
|
||||
|
||||
|
|
|
@ -28,16 +28,6 @@ RSpec.describe Ci::CreateWebIdeTerminalService do
|
|||
end
|
||||
subject
|
||||
end
|
||||
|
||||
context 'when the ci_pipeline_ensure_iid_on_save feature flag is off' do
|
||||
it 'does not call ensure_project_iid explicitly' do
|
||||
stub_feature_flags(ci_pipeline_ensure_iid_on_save: false)
|
||||
expect_next_instance_of(Ci::Pipeline) do |instance|
|
||||
expect(instance).to receive(:ensure_project_iid!).once
|
||||
end
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
|
@ -3,6 +3,38 @@
|
|||
module CycleAnalyticsHelpers
|
||||
include GitHelpers
|
||||
|
||||
def toggle_value_stream_dropdown
|
||||
page.find('[data-testid="dropdown-value-streams"]').click
|
||||
end
|
||||
|
||||
def add_custom_stage_to_form
|
||||
page.find_button(s_('CreateValueStreamForm|Add another stage')).click
|
||||
|
||||
index = page.all('[data-testid="value-stream-stage-fields"]').length
|
||||
last_stage = page.all('[data-testid="value-stream-stage-fields"]').last
|
||||
|
||||
within last_stage do
|
||||
find('[name*="custom-stage-name-"]').fill_in with: "Cool custom stage - name #{index}"
|
||||
select_dropdown_option_by_value "custom-stage-start-event-", :merge_request_created
|
||||
select_dropdown_option_by_value "custom-stage-end-event-", :merge_request_merged
|
||||
end
|
||||
end
|
||||
|
||||
def save_value_stream(custom_value_stream_name)
|
||||
fill_in 'create-value-stream-name', with: custom_value_stream_name
|
||||
|
||||
page.find_button(s_('CreateValueStreamForm|Create Value Stream')).click
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
def create_custom_value_stream(custom_value_stream_name)
|
||||
toggle_value_stream_dropdown
|
||||
page.find_button(_('Create new Value Stream')).click
|
||||
|
||||
add_custom_stage_to_form
|
||||
save_value_stream(custom_value_stream_name)
|
||||
end
|
||||
|
||||
def wait_for_stages_to_load(selector = '.js-path-navigation')
|
||||
expect(page).to have_selector selector
|
||||
wait_for_requests
|
||||
|
|
Loading…
Reference in New Issue