diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index f5393ef47d6..92c63ec9e2a 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -13,7 +13,7 @@
// directory.
@import '@gitlab/at.js/dist/css/jquery.atwho';
@import 'dropzone/dist/basic';
-@import 'select2/select2';
+@import 'select2';
// GitLab UI framework
@import 'framework';
diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss
index c0699844387..7f529791fc0 100644
--- a/app/assets/stylesheets/components/related_items_list.scss
+++ b/app/assets/stylesheets/components/related_items_list.scss
@@ -123,21 +123,11 @@ $item-remove-button-space: 42px;
.item-milestone {
text-decoration: none;
max-width: $item-milestone-max-width;
-
- .ic-clock {
- margin-right: $gl-padding-4;
- }
}
.item-weight {
max-width: $item-weight-max-width;
}
-
- .item-milestone .ic-clock,
- .item-weight .ic-weight,
- .item-due-date .ic-calendar {
- color: $gl-text-color-secondary;
- }
}
.item-assignees {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index d15cd64f415..6de90f3bfcd 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -164,9 +164,8 @@
right: 8px;
}
- .ic-chevron-down {
+ .dropdown-menu-toggle-icon {
position: absolute;
- top: $gl-padding-8;
right: $gl-padding-8;
color: $gray-darkest;
}
@@ -627,7 +626,7 @@
.fa,
.input-icon,
- .ic-search {
+ .dropdown-input-search {
position: absolute;
top: $gl-padding-8;
right: 20px;
diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb
index d1f04609693..74a1e15f42b 100644
--- a/app/models/concerns/relative_positioning.rb
+++ b/app/models/concerns/relative_positioning.rb
@@ -297,13 +297,13 @@ module RelativePositioning
if max_pos.nil?
self.relative_position = START_POSITION
- elsif gap_too_small?(max_pos, MAX_POSITION)
+ elsif gap_too_small?(max_pos, MAX_POSITION + 1)
max = relative_siblings.order(Gitlab::Database.nulls_last_order('relative_position', 'DESC')).first
max.move_sequence_before(true)
max.reset
- self.relative_position = self.class.position_between(max.relative_position, MAX_POSITION)
+ self.relative_position = self.class.position_between(max.relative_position, MAX_POSITION + 1)
else
- self.relative_position = self.class.position_between(max_pos, MAX_POSITION)
+ self.relative_position = self.class.position_between(max_pos, MAX_POSITION + 1)
end
end
@@ -312,13 +312,13 @@ module RelativePositioning
if min_pos.nil?
self.relative_position = START_POSITION
- elsif gap_too_small?(min_pos, MIN_POSITION)
+ elsif gap_too_small?(min_pos, MIN_POSITION - 1)
min = relative_siblings.order(Gitlab::Database.nulls_last_order('relative_position', 'ASC')).first
min.move_sequence_after(true)
min.reset
- self.relative_position = self.class.position_between(MIN_POSITION, min.relative_position)
+ self.relative_position = self.class.position_between(MIN_POSITION - 1, min.relative_position)
else
- self.relative_position = self.class.position_between(MIN_POSITION, min_pos)
+ self.relative_position = self.class.position_between(MIN_POSITION - 1, min_pos)
end
end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 37487261f2c..bec75657530 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -28,7 +28,7 @@ module Projects
Projects::UnlinkForkService.new(project, current_user).execute
- attempt_destroy_transaction(project)
+ attempt_destroy(project)
system_hook_service.execute_hooks_for(project, :destroy)
log_info("Project \"#{project.full_path}\" was deleted")
@@ -98,29 +98,35 @@ module Projects
log_error("Deletion failed on #{project.full_path} with the following message: #{message}")
end
- def attempt_destroy_transaction(project)
+ def attempt_destroy(project)
unless remove_registry_tags
raise_error(s_('DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator.'))
end
project.leave_pool_repository
- Project.transaction do
- log_destroy_event
- trash_relation_repositories!
- trash_project_repositories!
-
- # Rails attempts to load all related records into memory before
- # destroying: https://github.com/rails/rails/issues/22510
- # This ensures we delete records in batches.
- #
- # Exclude container repositories because its before_destroy would be
- # called multiple times, and it doesn't destroy any database records.
- project.destroy_dependent_associations_in_batches(exclude: [:container_repositories, :snippets])
- project.destroy!
+ if Gitlab::Ci::Features.project_transactionless_destroy?(project)
+ destroy_project_related_records(project)
+ else
+ Project.transaction { destroy_project_related_records(project) }
end
end
+ def destroy_project_related_records(project)
+ log_destroy_event
+ trash_relation_repositories!
+ trash_project_repositories!
+
+ # Rails attempts to load all related records into memory before
+ # destroying: https://github.com/rails/rails/issues/22510
+ # This ensures we delete records in batches.
+ #
+ # Exclude container repositories because its before_destroy would be
+ # called multiple times, and it doesn't destroy any database records.
+ project.destroy_dependent_associations_in_batches(exclude: [:container_repositories, :snippets])
+ project.destroy!
+ end
+
def log_destroy_event
log_info("Attempting to destroy #{project.full_path} (#{project.id})")
end
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index b869298e99d..973b79f4f64 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -16,12 +16,7 @@
%head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" }
- - if ActionController::Base.asset_host
- %link{ rel: 'dns-prefetch', href: ActionController::Base.asset_host }
- %link{ rel: 'preconnect', href: ActionController::Base.asset_host, crossorigin: '' }
-
- - if Gitlab::CurrentSettings.snowplow_enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname
- %link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' }
+ = render 'layouts/loading_hints'
%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' }
diff --git a/app/views/layouts/_loading_hints.html.haml b/app/views/layouts/_loading_hints.html.haml
new file mode 100644
index 00000000000..c9fe1a4a150
--- /dev/null
+++ b/app/views/layouts/_loading_hints.html.haml
@@ -0,0 +1,10 @@
+- if ActionController::Base.asset_host
+ %link{ rel: 'dns-prefetch', href: ActionController::Base.asset_host }
+ %link{ rel: 'preconnect', href: ActionController::Base.asset_host, crossorigin: '' }
+- if user_application_theme == 'gl-dark'
+ %link{ { rel: 'preload', href: stylesheet_url('application_dark'), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: '' } : {} }
+- else
+ %link{ { rel: 'preload', href: stylesheet_url('application'), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: '' } : {} }
+%link{ { rel: 'preload', href: stylesheet_url("highlight/themes/#{user_color_scheme}"), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: '' } : {} }
+- if Gitlab::CurrentSettings.snowplow_enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname
+ %link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' }
diff --git a/changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml b/changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml
new file mode 100644
index 00000000000..7a8a90a5fdd
--- /dev/null
+++ b/changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update Managed Cluster Applications to v0.29.0, including WAF for ingress, a smaller CI template, and version updates to a few applications
+merge_request: 39890
+author:
+type: changed
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 1301e8c4ca1..2b855054246 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -121,8 +121,8 @@ Disqus
Dockerfile
Dockerfiles
dogfood
-dogfoods
dogfooding
+dogfoods
dotenv
downvoted
downvotes
@@ -200,9 +200,9 @@ interdependency
interruptible
Irker
Istio
+Jaeger
jasmine-jquery
JavaScript
-Jaeger
Jenkins
Jenkinsfile
Jira
@@ -214,6 +214,7 @@ kanbans
Kaniko
Karma
Kerberos
+keyset
Kibana
Kinesis
Knative
@@ -258,14 +259,14 @@ middlewares
migratus
Minikube
MinIO
-mitmproxy
+misconfiguration
+misconfigurations
misconfigure
misconfigured
misconfigures
-misconfiguration
-misconfigurations
misconfiguring
mitigations
+mitmproxy
mixin
mixins
mockup
@@ -287,10 +288,10 @@ Nokogiri
npm
Nurtch
OAuth
-Okta
offboarded
offboarding
offboards
+Okta
OmniAuth
onboarding
OpenID
@@ -301,12 +302,12 @@ parallelizations
passwordless
Patroni
performant
+PgBouncer
phaser
phasers
Pipfile
Pipfiles
Piwik
-PgBouncer
plaintext
Poedit
polyfill
@@ -347,12 +348,12 @@ rebase
rebased
rebases
rebasing
-Redcarpet
-Redis
-Redmine
reCAPTCHA
+Redcarpet
redirection
redirections
+Redis
+Redmine
refactorings
referer
referers
@@ -370,21 +371,21 @@ repurposing
requeue
requeued
requeues
-reusability
Restlet
+resync
resynced
resyncing
resyncs
+reusability
+reverified
+reverifies
+reverify
rollout
rollouts
rsync
rsynced
rsyncing
rsyncs
-resync
-reverified
-reverifies
-reverify
Rubix
Rubocop
Rubular
@@ -397,21 +398,21 @@ runtimes
Salesforce
SAML
sandboxing
+sanitization
sbt
scatterplot
scatterplots
Sendmail
Sentry
-serverless
-Sidekiq
-Sisense
-sharding
-shfmt
-Shibboleth
-sanitization
serializer
serializers
serializing
+serverless
+sharding
+shfmt
+Shibboleth
+Sidekiq
+Sisense
Sitespeed
Slack
Slony
@@ -431,7 +432,6 @@ strace
strikethrough
strikethroughs
stunnel
-subpath
subfolder
subfolders
subgraph
@@ -443,14 +443,15 @@ sublicensing
subnet
subnets
subnetting
-subtree
-subtrees
+subpath
subqueried
subqueries
subquery
subquerying
substring
substrings
+subtree
+subtrees
syslog
tcpdump
Tiller
@@ -465,9 +466,9 @@ tooltip
tooltips
Trello
triaging
-TypeScript
Twilio
Twitter
+TypeScript
Ubuntu
unapplied
unarchive
@@ -504,8 +505,8 @@ unoptimizes
unoptimizing
unprioritized
unprotect
-unprotects
unprotected
+unprotects
unpublish
unpublished
unpublishes
@@ -524,6 +525,8 @@ unstage
unstaged
unstages
unstaging
+unstar
+unstars
unstarted
unstash
unstashed
@@ -558,8 +561,8 @@ webserver
whitepaper
whitepapers
wireframe
-wireframes
wireframed
+wireframes
wireframing
Wireshark
Wordpress
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 2e36a754c79..0e415146194 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -677,7 +677,7 @@ documentation](index.md#configure-gitaly-servers).
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your front door GitLab URL or an internal load balancer.
- # Examples: 'https://example.gitlab.com', 'http://1.2.3.4'
+ # Examples: 'https://gitlab.example.com', 'http://1.2.3.4'
gitlab_rails['internal_api_url'] = 'http://GITLAB_HOST'
```
diff --git a/doc/api/projects.md b/doc/api/projects.md
index ee9779b54e0..d10b246517c 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -22,7 +22,7 @@ Values for the project visibility level are:
## Project merge method
-There are currently three options for `merge_method` to choose from:
+There are three options for `merge_method` to choose from:
- `merge`:
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
@@ -44,28 +44,28 @@ GET /projects
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. `repository_size`, `storage_size`, or `wiki_size` fields are only allowed for admins. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of projects matching the search criteria |
-| `search_namespaces` | boolean | no | Include ancestor namespaces when matching search criteria. Default is `false` |
-| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
-| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
-| `membership` | boolean | no | Limit by projects that the current user is a member of |
-| `starred` | boolean | no | Limit by projects starred by the current user |
-| `statistics` | boolean | no | Include project statistics |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
-| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
-| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
-| `with_programming_language` | string | no | Limit by projects which use the given programming language |
-| `wiki_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
-| `repository_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the repository checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
-| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md#valid-access-levels) |
| `id_after` | integer | no | Limit results to projects with IDs greater than the specified ID |
| `id_before` | integer | no | Limit results to projects with IDs less than the specified ID |
| `last_activity_after` | datetime | no | Limit results to projects with last_activity after specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
| `last_activity_before` | datetime | no | Limit results to projects with last_activity before specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
+| `membership` | boolean | no | Limit by projects that the current user is a member of |
+| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md#valid-access-levels) |
+| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. `repository_size`, `storage_size`, or `wiki_size` fields are only allowed for admins. Default is `created_at` |
+| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
+| `repository_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the repository checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
| `repository_storage` | string | no | Limit results to projects stored on repository_storage. Available for admins only. |
+| `search_namespaces` | boolean | no | Include ancestor namespaces when matching search criteria. Default is `false` |
+| `search` | string | no | Return list of projects matching the search criteria |
+| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
+| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
+| `starred` | boolean | no | Limit by projects starred by the current user |
+| `statistics` | boolean | no | Include project statistics |
+| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
+| `wiki_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
+| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `with_programming_language` | string | no | Limit by projects which use the given programming language |
NOTE: **Note:**
This endpoint supports [keyset pagination](README.md#keyset-based-pagination) for selected `order_by` options.
@@ -295,9 +295,10 @@ When the user is authenticated and `simple` is not set this returns something li
```
NOTE: **Note:**
-For users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) the `marked_for_deletion_at` attribute has been deprecated and will be removed in API v5 in favor of the `marked_for_deletion_on` attribute.
+For users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) the `marked_for_deletion_at`
+attribute has been deprecated and will be removed in API v5 in favor of the `marked_for_deletion_on` attribute.
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
the `approvals_before_merge` parameter:
```json
@@ -319,9 +320,9 @@ GET /projects?custom_attributes[key]=value&custom_attributes[other_key]=other_va
### Pagination limits
-From GitLab 13.0, [offset-based pagination](README.md#offset-based-pagination) will be
+In GitLab 13.0 and later, [offset-based pagination](README.md#offset-based-pagination) is
[limited to 50,000 records](https://gitlab.com/gitlab-org/gitlab/-/issues/34565).
-[Keyset pagination](README.md#keyset-based-pagination) will be required to retrieve projects
+[Keyset pagination](README.md#keyset-based-pagination) is required to retrieve projects
beyond this limit.
Note that keyset pagination only supports `order_by=id`. Other sorting options are not available.
@@ -918,7 +919,7 @@ GET /projects/:id
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
the `approvals_before_merge` parameter:
```json
@@ -933,7 +934,7 @@ the `approvals_before_merge` parameter:
**Note**: The `web_url` and `avatar_url` attributes on `namespace` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27427) in GitLab 11.11.
If the project is a fork, and you provide a valid token to authenticate, the
-`forked_from_project` field will appear in the response.
+`forked_from_project` field appears in the response.
```json
{
@@ -1031,7 +1032,7 @@ POST /projects
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `name` | string | yes if path is not provided | The name of the new project. Equals path if not provided. |
-| `path` | string | yes if name is not provided | Repository name for new project. Generated based on name if not provided (generated lowercased with dashes). |
+| `path` | string | yes if name is not provided | Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes). |
| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) |
| `default_branch` | string | no | `master` by default |
| `description` | string | no | Short project description |
@@ -1072,7 +1073,7 @@ POST /projects
| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) |
| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled |
| `build_coverage_regex` | string | no | Test coverage parsing |
-| `ci_config_path` | string | no | The path to CI config file |
+| `ci_config_path` | string | no | The path to CI configuration file |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project |
| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) |
| `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins |
@@ -1144,7 +1145,7 @@ POST /projects/user/:user_id
| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) |
| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled |
| `build_coverage_regex` | string | no | Test coverage parsing |
-| `ci_config_path` | string | no | The path to CI config file |
+| `ci_config_path` | string | no | The path to CI configuration file |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project |
| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) |
| `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins |
@@ -1215,7 +1216,7 @@ PUT /projects/:id
| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) |
| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled |
| `build_coverage_regex` | string | no | Test coverage parsing |
-| `ci_config_path` | string | no | The path to CI config file |
+| `ci_config_path` | string | no | The path to CI configuration file |
| `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone) |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project |
| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) |
@@ -1240,7 +1241,7 @@ where `password` is a public access key with the `api` scope enabled.
Forks a project into the user namespace of the authenticated user or the one provided.
The forking operation for a project is asynchronous and is completed in a
-background job. The request will return immediately. To determine whether the
+background job. The request returns immediately. To determine whether the
fork of the project has completed, query the `import_status` for the new project.
```plaintext
@@ -1250,11 +1251,11 @@ POST /projects/:id/fork
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `namespace` | integer/string | no | (deprecated) The ID or path of the namespace that the project will be forked to |
-| `namespace_id` | integer | no | The ID of the namespace that the project will be forked to |
-| `namespace_path` | string | no | The path of the namespace that the project will be forked to |
-| `path` | string | no | The path that will be assigned to the resultant project after forking |
-| `name` | string | no | The name that will be assigned to the resultant project after forking |
+| `namespace` | integer/string | no | (deprecated) The ID or path of the namespace that the project is forked to |
+| `namespace_id` | integer | no | The ID of the namespace that the project is forked to |
+| `namespace_path` | string | no | The path of the namespace that the project is forked to |
+| `path` | string | no | The path assigned to the resultant project after forking |
+| `name` | string | no | The name assigned to the resultant project after forking |
## List Forks of a project
@@ -1614,8 +1615,8 @@ Example response:
## Archive a project
-Archives the project if the user is either admin or the project owner of this project. This action is
-idempotent, thus archiving an already archived project will not change the project.
+Archives the project if the user is either an administrator or the owner of this project. This action is
+idempotent, thus archiving an already archived project does not change the project.
```plaintext
POST /projects/:id/archive
@@ -1724,8 +1725,8 @@ Example response:
## Unarchive a project
-Unarchives the project if the user is either admin or the project owner of this project. This action is
-idempotent, thus unarchiving a non-archived project will not change the project.
+Unarchives the project if the user is either an administrator or the owner of this project. This action is
+idempotent, thus unarchiving a non-archived project does not change the project.
```plaintext
POST /projects/:id/unarchive
@@ -1880,12 +1881,12 @@ POST /projects/:id/uploads
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `file` | string | yes | The file to be uploaded |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-To upload a file from your filesystem, use the `--form` argument. This causes
+To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`.
-The `file=` parameter must point to a file on your filesystem and be preceded
+The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
@@ -1917,10 +1918,10 @@ POST /projects/:id/share
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `group_id` | integer | yes | The ID of the group to share with |
-| `group_access` | integer | yes | The [access level](members.md#valid-access-levels) to grant the group |
| `expires_at` | string | no | Share expiration date in ISO 8601 format: 2016-09-26 |
+| `group_access` | integer | yes | The [access level](members.md#valid-access-levels) to grant the group |
+| `group_id` | integer | yes | The ID of the group to share with |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
## Delete a shared project link within a group
@@ -1932,8 +1933,8 @@ DELETE /projects/:id/share/:group_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `group_id` | integer | yes | The ID of the group |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/share/17"
@@ -1966,8 +1967,8 @@ GET /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of a project hook |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```json
{
@@ -2001,22 +2002,22 @@ POST /projects/:id/hooks
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `url` | string | yes | The hook URL |
-| `push_events` | boolean | no | Trigger hook on push events |
-| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
-| `issues_events` | boolean | no | Trigger hook on issues events |
| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
-| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
-| `tag_push_events` | boolean | no | Trigger hook on tag push events |
-| `note_events` | boolean | no | Trigger hook on note events |
| `confidential_note_events` | boolean | no | Trigger hook on confidential note events |
-| `job_events` | boolean | no | Trigger hook on job events |
-| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
-| `wiki_page_events` | boolean | no | Trigger hook on wiki events |
| `deployment_events` | boolean | no | Trigger hook on deployment events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
-| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `issues_events` | boolean | no | Trigger hook on issues events |
+| `job_events` | boolean | no | Trigger hook on job events |
+| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
+| `note_events` | boolean | no | Trigger hook on note events |
+| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
+| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
+| `push_events` | boolean | no | Trigger hook on push events |
+| `tag_push_events` | boolean | no | Trigger hook on tag push events |
+| `token` | string | no | Secret token to validate received payloads; this is not returned in the response |
+| `url` | string | yes | The hook URL |
+| `wiki_page_events` | boolean | no | Trigger hook on wiki events |
### Edit project hook
@@ -2028,23 +2029,23 @@ PUT /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `hook_id` | integer | yes | The ID of the project hook |
-| `url` | string | yes | The hook URL |
-| `push_events` | boolean | no | Trigger hook on push events |
-| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
-| `issues_events` | boolean | no | Trigger hook on issues events |
| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
-| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
-| `tag_push_events` | boolean | no | Trigger hook on tag push events |
-| `note_events` | boolean | no | Trigger hook on note events |
| `confidential_note_events` | boolean | no | Trigger hook on confidential note events |
-| `job_events` | boolean | no | Trigger hook on job events |
-| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
-| `wiki_events` | boolean | no | Trigger hook on wiki events |
| `deployment_events` | boolean | no | Trigger hook on deployment events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
-| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
+| `hook_id` | integer | yes | The ID of the project hook |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `issues_events` | boolean | no | Trigger hook on issues events |
+| `job_events` | boolean | no | Trigger hook on job events |
+| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
+| `note_events` | boolean | no | Trigger hook on note events |
+| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
+| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
+| `push_events` | boolean | no | Trigger hook on push events |
+| `tag_push_events` | boolean | no | Trigger hook on tag push events |
+| `token` | string | no | Secret token to validate received payloads; this is not returned in the response |
+| `url` | string | yes | The hook URL |
+| `wiki_events` | boolean | no | Trigger hook on wiki events |
### Delete project hook
@@ -2057,11 +2058,11 @@ DELETE /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of the project hook |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
Note the JSON response differs if the hook is available or not. If the project hook
-is available before it is returned in the JSON response or an empty response is returned.
+is available before it's returned in the JSON response or an empty response is returned.
## Fork relationship
@@ -2075,8 +2076,8 @@ POST /projects/:id/fork/:forked_from_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `forked_from_id` | ID | yes | The ID of the project that was forked from |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
### Delete an existing forked from relationship
@@ -2100,15 +2101,15 @@ GET /projects
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `search` | string | yes | A string contained in the project name |
| `order_by` | string | no | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields |
+| `search` | string | yes | A string contained in the project name |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order |
```shell
curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects?search=test"
```
-## Start the Housekeeping task for a Project
+## Start the Housekeeping task for a project
> Introduced in GitLab 9.0.
@@ -2153,7 +2154,7 @@ GET /projects/:id/push_rule
}
```
-Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) can also see
the `commit_committer_check` and `reject_unsigned_commits` parameters:
```json
@@ -2176,18 +2177,18 @@ POST /projects/:id/push_rule
| Attribute | Type | Required | Description |
| --------------------------------------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, for example `@my-company.com$` |
+| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, for example `(feature|hotfix)\/*` |
+| `commit_committer_check` **(PREMIUM)** | boolean | no | Users can only push commits to this repository that were committed with one of their own verified emails. |
+| `commit_message_negative_regex` **(STARTER)** | string | no | No commit message is allowed to match this, for example `ssh\:\/\/` |
+| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, for example `Fixed \d+\..*` |
| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
+| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, for example `(jar|exe)$` |
+| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
| `member_check` **(STARTER)** | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` **(STARTER)** | boolean | no | GitLab will reject any files that are likely to contain secrets |
-| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
-| `commit_message_negative_regex` **(STARTER)** | string | no | No commit message is allowed to match this, e.g. `ssh\:\/\/` |
-| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, e.g. `(feature|hotfix)\/*` |
-| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
-| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, e.g. `(jar|exe)$` |
-| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
-| `commit_committer_check` **(PREMIUM)** | boolean | no | Users can only push commits to this repository that were committed with one of their own verified emails. |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commit when it is not signed through GPG. |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commit when it's not signed through GPG. |
### Edit project push rule
@@ -2199,17 +2200,17 @@ PUT /projects/:id/push_rule
| Attribute | Type | Required | Description |
| --------------------------------------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, for example `@my-company.com$` |
+| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, for example `(feature|hotfix)\/*` |
+| `commit_committer_check` **(PREMIUM)** | boolean | no | Users can only push commits to this repository that were committed with one of their own verified emails. |
+| `commit_message_negative_regex` **(STARTER)** | string | no | No commit message is allowed to match this, for example `ssh\:\/\/` |
+| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, for example `Fixed \d+\..*` |
| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
+| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, for example `(jar|exe)$` |
+| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
| `member_check` **(STARTER)** | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` **(STARTER)** | boolean | no | GitLab will reject any files that are likely to contain secrets |
-| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
-| `commit_message_negative_regex` **(STARTER)** | string | no | No commit message is allowed to match this, e.g. `ssh\:\/\/` |
-| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, e.g. `(feature|hotfix)\/*` |
-| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
-| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, e.g. `(jar|exe)$` |
-| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
-| `commit_committer_check` **(PREMIUM)** | boolean | no | Users can only push commits to this repository that were committed with one of their own verified emails. |
| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commits when they are not GPG signed. |
### Delete project push rule
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_1-1.png b/doc/integration/img/jira_dev_panel_jira_setup_1-1.png
deleted file mode 100644
index cef903ac9b4..00000000000
Binary files a/doc/integration/img/jira_dev_panel_jira_setup_1-1.png and /dev/null differ
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index dc19d42ee2e..333d7c09d30 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -92,9 +92,6 @@ If you're using GitLab.com and Jira Cloud, we recommend you use the [GitLab for
If you're using Jira Cloud, go to **Settings (gear) > Products > DVCS accounts**.
1. Click **Link GitHub Enterprise account** to start creating a new integration.
(We're pretending to be GitHub in this integration, until there's additional platform support in Jira.)
-
- 
-
1. Complete the form:
Select **GitHub Enterprise** for the **Host** field.
@@ -134,6 +131,93 @@ steps with additional Jira DVCS accounts.
Now that the integration is configured, read more about how to test and use it in [Usage](#usage).
+#### Troubleshooting your DVCS connection
+
+Refer to the items in this section if you're having problems with your DVCS connector.
+
+##### Jira cannot access GitLab server
+
+```plaintext
+Error obtaining access token. Cannot access https://gitlab.example.com from Jira.
+```
+
+This error message is generated in Jira, after completing the **Add New Account**
+form and authorizing access. It indicates a connectivity issue from Jira to
+GitLab. No other error messages appear in any logs.
+
+If there was an issue with SSL/TLS, this error message will be generated.
+
+- The [GitLab Jira integration](jira.md) requires GitLab to connect to Jira. Any
+ TLS issues that arise from a private certificate authority or self-signed
+ certificate [are resolved on the GitLab server](https://docs.gitlab.com/omnibus/settings/ssl.html#other-certificate-authorities),
+ as GitLab is the TLS client.
+- The Jira Development Panel integration requires Jira to connect to GitLab, which
+ causes Jira to be the TLS client. If your GitLab server's certificate is not
+ issued by a public certificate authority, the Java truststore on Jira's server
+ needs to have the appropriate certificate added to it (such as your organization's
+ root certificate).
+
+Refer to Atlassian's documentation and Atlassian Support for assistance setting up Jira correctly:
+
+- [Adding a certificate to the trust store](https://confluence.atlassian.com/kb/how-to-import-a-public-ssl-certificate-into-a-jvm-867025849.html).
+ - Simplest approach is to use [keytool](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html).
+ - Add additional roots to Java's default truststore (`cacerts`) to allow Jira to
+ also trust public certificate authorities.
+ - If the integration stops working after upgrading Jira's Java runtime, this
+ might be because the `cacerts` truststore got replaced.
+
+- [Troubleshooting connectivity up to and including TLS handshaking](https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html),
+ using the a java class called `SSLPoke`.
+
+- Download the class from Atlassian's knowledgebase to Jira's server, for example to `/tmp`.
+- Use the same Java runtime as Jira.
+- Pass all networking-related parameters that Jira is called with, such as proxy
+ settings or an alternative root truststore (`-Djavax.net.ssl.trustStore`):
+
+```shell
+${JAVA_HOME}/bin/java -Djavax.net.ssl.trustStore=/var/atlassian/application-data/jira/cacerts -classpath /tmp SSLPoke gitlab.example.com 443
+```
+
+The message `Successfully connected` indicates a successful TLS handshake.
+
+If there are problems, the Java TLS library generates errors that you can
+look up for more detail.
+
+##### Jira error adding account and no repositories listed
+
+```plaintext
+Error!
+Failed adding the account: [Error retrieving list of repositories]
+```
+
+This error message is generated in Jira after completing the **Add New Account**
+form in Jira and authorizing access. Attempting to click **Try Again** returns
+`Account is already integrated with JIRA.` The account is set up in the DVCS
+accounts view, but no repositories are listed.
+
+Potential resolutions:
+
+- If you're using GitLab versions 11.10-12.7, upgrade to GitLab 12.8.10 or later
+ to resolve an identified [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/37012).
+- The Jira Development Panel integration requires GitLab Premium, GitLab.com Silver,
+ or a higher tier. If you're using a lower tier of GitLab, you'll need to upgrade
+ to use this feature.
+
+[Contact GitLab Support](https://about.gitlab.com/support) if none of these reasons apply.
+
+#### Fixing synchonization issues
+
+If Jira displays incorrect information (such as deleted branches), you may need to
+resynchronize the information. To do so:
+
+1. In Jira, go to **Jira Administration > Applications > DVCS accounts**.
+1. At the account (group or subgroup) level, Jira displays an option to
+ **Refresh repositories** in the `...` (ellipsis) menu.
+1. For each project, there's a sync button displayed next to the **last activity** date.
+ To perform a *soft resync*, click the button, or complete a *full sync* by shift clicking
+ the button. For more information, see
+ [Atlassian's documentation](https://confluence.atlassian.com/adminjiracloud/synchronize-an-account-972332890.html).
+
### GitLab for Jira app
You can integrate GitLab.com and Jira Cloud using the [GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-for-jira) app in the Atlassian Marketplace.
diff --git a/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png b/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png
new file mode 100644
index 00000000000..b792fbc9af1
Binary files /dev/null and b/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png differ
diff --git a/doc/user/application_security/img/interacting_with_vulnerability_v13_0.png b/doc/user/application_security/img/interacting_with_vulnerability_v13_0.png
deleted file mode 100644
index 19d47712f9e..00000000000
Binary files a/doc/user/application_security/img/interacting_with_vulnerability_v13_0.png and /dev/null differ
diff --git a/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png b/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png
new file mode 100644
index 00000000000..db698995469
Binary files /dev/null and b/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index c003b512808..14f44a04760 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -121,7 +121,7 @@ information with several options:
- [Solution](#solutions-for-vulnerabilities-auto-remediation): For some vulnerabilities,
a solution is provided for how to fix the vulnerability.
-
+
### View details of a DAST vulnerability
@@ -198,9 +198,10 @@ Pressing the "Dismiss Selected" button will dismiss all the selected vulnerabili
### Creating an issue for a vulnerability
-You can create an issue for a vulnerability by selecting the **Create issue**
-button from within the vulnerability modal, or by using the action buttons to the right of
-a vulnerability row in the group security dashboard.
+You can create an issue for a vulnerability by visiting the vulnerability's page and clicking
+**Create issue**, which you can find in the **Related issues** section.
+
+
This creates a [confidential issue](../project/issues/confidential_issues.md) in the project the
vulnerability came from, and pre-populates it with some useful information taken from the vulnerability
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 3b04c7aac18..6f51da8e020 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -894,7 +894,7 @@ GitLab Runner is installed into the `gitlab-managed-apps` namespace of your clus
In order for GitLab Runner to function, you **must** specify the following:
-- `gitlabUrl` - the GitLab server full URL (for example, `https://example.gitlab.com`) to register the Runner against.
+- `gitlabUrl` - the GitLab server full URL (for example, `https://gitlab.example.com`) to register the Runner against.
- `runnerRegistrationToken` - The registration token for adding new Runners to GitLab. This must be
[retrieved from your GitLab instance](../../ci/runners/README.md).
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 9a2bd2e8806..a6e6bac30de 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -236,7 +236,7 @@ Alternatively, the [SCIM API](../../../api/scim.md#get-a-list-of-saml-users) can
For example:
```shell
-curl 'https://example.gitlab.com/api/scim/v2/groups/GROUP_NAME/Users?startIndex=1"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json"
+curl 'https://gitlab.example.com/api/scim/v2/groups/GROUP_NAME/Users?startIndex=1"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json"
```
To see how this compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](index.md#saml-debugging-tools).
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index 4e5b924a1b7..ef2de127d56 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -318,7 +318,7 @@ through Git.
For example:
```plaintext
-machine example.gitlab.com
+machine gitlab.example.com
login
password
```
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index f11cd4d9539..1c7b00b184a 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -22,7 +22,9 @@ Features include:
- The Jira issue shows the activity and is closed or otherwise transitioned as specified in your GitLab settings.
- **View a list of Jira issues directly in GitLab** **(PREMIUM)**
-For additional features, you can install the [Jira Development Panel integration](../../../integration/jira_development_panel.md). This enables you to:
+For additional features, you can install the
+[Jira Development Panel integration](../../../integration/jira_development_panel.md) **(PREMIUM)**.
+This enables you to:
- In a Jira issue, display relevant GitLab information in the [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/), including related branches, commits, and merge requests.
- Use Jira [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) in GitLab to add Jira comments, log time spent on the issue, or apply any issue transition.
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 20880d0c4fa..003959ab086 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -322,8 +322,9 @@ The four types of links are "Runbook," "Package," "Image," and "Other."
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) in GitLab 12.6.
Each time a release is created, GitLab takes a snapshot of data that's related to it.
-This data is saved in a JSON file and called *release evidence*. It includes linked milestones
-and issues and can facilitate internal processes like external audits.
+This data is saved in a JSON file and called *release evidence*. The feature currently
+includes test artifacts and linked milestones (and will include issues) to facilitate
+internal processes, like external audits.
To access the release evidence, on the Releases page, click the link to the JSON file that's listed
under the **Evidence collection** heading.
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index 8247f69c61a..c06bff48939 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -49,7 +49,7 @@ download all the advertised refs.
1. Clone a fresh copy of the repository using `--bare` and `--mirror`:
```shell
- git clone --bare --mirror https://example.gitlab.com/my/project.git
+ git clone --bare --mirror https://gitlab.example.com/my/project.git
```
1. Using `git filter-repo`, purge any files from the history of your repository.
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index cbc4895f014..c10d03ed5aa 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -54,7 +54,8 @@ When the project access token is [revoked](#revoking-a-project-access-token) the
records will be moved to a system-wide user with the username "Ghost User". For more information,
see [Associated Records](../../profile/account/delete_account.md#associated-records).
-Project bot users are a [GitLab-created service account](../../../subscriptions/index.md#self-managed) and do not count as a licensed seat.
+Project bot users are a [GitLab-created service account](../../../subscriptions/index.md#self-managed), but count as a licensed seat.
+These users will not count against your licensed seat in the future when [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/223695) is resolved.
## Revoking a project access token
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index 2f6667d3600..934d1a4c9f1 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -79,6 +79,10 @@ module Gitlab
def self.expand_names_for_cross_pipeline_artifacts?(project)
::Feature.enabled?(:ci_expand_names_for_cross_pipeline_artifacts, project)
end
+
+ def self.project_transactionless_destroy?(project)
+ Feature.enabled?(:project_transactionless_destroy, project, default_enabled: false)
+ end
end
end
end
diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
index 3d0bacda853..7050b41e045 100644
--- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
@@ -1,27 +1,11 @@
apply:
stage: deploy
- image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.24.2"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.29.0"
environment:
name: production
variables:
TILLER_NAMESPACE: gitlab-managed-apps
GITLAB_MANAGED_APPS_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/config.yaml
- INGRESS_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/ingress/values.yaml
- CERT_MANAGER_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cert-manager/values.yaml
- SENTRY_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/sentry/values.yaml
- GITLAB_RUNNER_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/gitlab-runner/values.yaml
- CILIUM_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cilium/values.yaml
- CILIUM_HUBBLE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cilium/hubble-values.yaml
- JUPYTERHUB_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/jupyterhub/values.yaml
- PROMETHEUS_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/prometheus/values.yaml
- ELASTIC_STACK_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/elastic-stack/values.yaml
- VAULT_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/vault/values.yaml
- CROSSPLANE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/crossplane/values.yaml
- FLUENTD_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/fluentd/values.yaml
- KNATIVE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/knative/values.yaml
- POSTHOG_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/posthog/values.yaml
- FALCO_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/falco/values.yaml
- APPARMOR_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/apparmor/values.yaml
script:
- gitlab-managed-apps /usr/local/share/gitlab-managed-apps/helmfile.yaml
only:
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 9908369426a..47be22f35ec 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -78,7 +78,7 @@ module Gitlab
included do
before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
- helper_method :experiment_enabled?
+ helper_method :experiment_enabled?, :experiment_tracking_category_and_group
end
def set_experimentation_subject_id_cookie
@@ -118,6 +118,10 @@ module Gitlab
::Experiment.add_user(experiment_key, tracking_group(experiment_key), current_user)
end
+ def experiment_tracking_category_and_group(experiment_key)
+ "#{tracking_category(experiment_key)}:#{tracking_group(experiment_key, '_group')}"
+ end
+
private
def dnt_enabled?
@@ -144,7 +148,7 @@ module Gitlab
{
category: tracking_category(experiment_key),
action: action,
- property: "#{tracking_group(experiment_key)}_group",
+ property: tracking_group(experiment_key, "_group"),
label: experimentation_subject_id,
value: value
}.compact
@@ -154,10 +158,12 @@ module Gitlab
Experimentation.experiment(experiment_key).tracking_category
end
- def tracking_group(experiment_key)
+ def tracking_group(experiment_key, suffix = nil)
return unless Experimentation.enabled?(experiment_key)
- experiment_enabled?(experiment_key) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
+ group = experiment_enabled?(experiment_key) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
+
+ suffix ? "#{group}#{suffix}" : group
end
def forced_enabled?(experiment_key)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 2cfa87b9436..12a7ecb6bb3 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -21693,6 +21693,9 @@ msgstr ""
msgid "SecurityReports|Issue Created"
msgstr ""
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
+msgstr ""
+
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index 4c079b98c90..489582521b5 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
it 'shows a reply button' do
reply_button = find('.js-reply-button', match: :first)
- expect(reply_button).to have_selector('.ic-comment')
+ expect(reply_button).to have_selector('[data-testid="comment-icon"]')
end
it 'shows reply placeholder when clicking reply button' do
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index 70d47516246..6218578cac6 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'Project deploy keys', :js do
page.within(find('.qa-deploy-keys-settings')) do
expect(page).to have_selector('.deploy-key', count: 1)
- accept_confirm { find('.ic-remove').click }
+ accept_confirm { find('[data-testid="remove-icon"]').click }
wait_for_requests
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index a05910cd892..7f2ef61bcbe 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe 'Environments page', :js do
expect(page).to have_css('.environments-container')
expect(page.all('.environment-name').length).to eq(1)
- expect(page.all('.ic-stop').length).to eq(0)
+ expect(page.all('[data-testid="stop-icon"]').length).to eq(0)
end
end
end
@@ -301,7 +301,7 @@ RSpec.describe 'Environments page', :js do
end
it 'has a dropdown for actionable jobs' do
- expect(page).to have_selector('.dropdown-new.btn.btn-default .ic-play')
+ expect(page).to have_selector('.dropdown-new.btn.btn-default [data-testid="play-icon"]')
end
it "has link to the delayed job's action" do
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 8beecedf85f..8c7b7bc70a2 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
+ find('.deploy-key', text: private_deploy_key.title).find('[data-testid="pencil-icon"]').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
check 'deploy_key_deploy_keys_projects_attributes_0_can_push'
@@ -84,7 +84,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
project.deploy_keys << public_deploy_key
visit project_settings_repository_path(project)
- find('.deploy-key', text: public_deploy_key.title).find('.ic-pencil').click
+ find('.deploy-key', text: public_deploy_key.title).find('[data-testid="pencil-icon"]').click
check 'deploy_key_deploy_keys_projects_attributes_0_can_push'
click_button 'Save changes'
@@ -102,7 +102,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
find('.js-deployKeys-tab-available_project_keys').click
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
+ find('.deploy-key', text: private_deploy_key.title).find('[data-testid="pencil-icon"]').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
click_button 'Save changes'
@@ -116,7 +116,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click }
+ accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('[data-testid="remove-icon"]').click }
expect(page).not_to have_content(private_deploy_key.title)
end
diff --git a/spec/frontend/collapsed_sidebar_todo_spec.js b/spec/frontend/collapsed_sidebar_todo_spec.js
index 0c74491aa74..b1a304fabcd 100644
--- a/spec/frontend/collapsed_sidebar_todo_spec.js
+++ b/spec/frontend/collapsed_sidebar_todo_spec.js
@@ -47,9 +47,9 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
expect(
document
- .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg use')
- .getAttribute('xlink:href'),
- ).toContain('todo-add');
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg')
+ .getAttribute('data-testid'),
+ ).toBe('todo-add-icon');
expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
@@ -72,9 +72,9 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
expect(
document
- .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone use')
- .getAttribute('xlink:href'),
- ).toContain('todo-done');
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone')
+ .getAttribute('data-testid'),
+ ).toBe('todo-done-icon');
done();
});
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index 7d942d969bb..0b1cbd28274 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -55,20 +55,20 @@ describe('Deploy keys key', () => {
it('shows pencil button for editing', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-pencil')).toExist();
+ expect(wrapper.find('.btn [data-testid="pencil-icon"]')).toExist();
});
it('shows disable button when the project is not deletable', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-cancel')).toExist();
+ expect(wrapper.find('.btn [data-testid="cancel-icon"]')).toExist();
});
it('shows remove button when the project is deletable', () => {
createComponent({
deployKey: { ...deployKey, destroyed_when_orphaned: true, almost_orphaned: true },
});
- expect(wrapper.find('.btn .ic-remove')).toExist();
+ expect(wrapper.find('.btn [data-testid="remove-icon"]')).toExist();
});
});
@@ -147,7 +147,7 @@ describe('Deploy keys key', () => {
it('shows pencil button for editing', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-pencil')).toExist();
+ expect(wrapper.find('.btn [data-testid="pencil-icon"]')).toExist();
});
it('shows disable button when key is enabled', () => {
@@ -155,7 +155,7 @@ describe('Deploy keys key', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-cancel')).toExist();
+ expect(wrapper.find('.btn [data-testid="cancel-icon"]')).toExist();
});
});
});
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index d440bf73e15..fe32bf918dd 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -144,16 +144,16 @@ describe('Environment', () => {
});
it('should open a closed folder', () => {
- expect(wrapper.find('.folder-icon.ic-chevron-right').exists()).toBe(false);
+ expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(false);
});
it('should close an opened folder', () => {
- expect(wrapper.find('.folder-icon.ic-chevron-down').exists()).toBe(true);
+ expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(true);
// close folder
wrapper.find('.folder-name').trigger('click');
wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.folder-icon.ic-chevron-down').exists()).toBe(false);
+ expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
});
});
diff --git a/spec/frontend/groups/components/item_actions_spec.js b/spec/frontend/groups/components/item_actions_spec.js
index c0dc1a816e6..f5df8c180d5 100644
--- a/spec/frontend/groups/components/item_actions_spec.js
+++ b/spec/frontend/groups/components/item_actions_spec.js
@@ -57,8 +57,8 @@ describe('ItemActionsComponent', () => {
expect(editBtn.getAttribute('href')).toBe(group.editPath);
expect(editBtn.getAttribute('aria-label')).toBe('Edit group');
expect(editBtn.dataset.originalTitle).toBe('Edit group');
- expect(editBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(editBtn.querySelector('svg use').getAttribute('xlink:href')).toContain('#settings');
+ expect(editBtn.querySelectorAll('svg').length).not.toBe(0);
+ expect(editBtn.querySelector('svg').getAttribute('data-testid')).toBe('settings-icon');
newVm.$destroy();
});
@@ -75,8 +75,8 @@ describe('ItemActionsComponent', () => {
expect(leaveBtn.getAttribute('href')).toBe(group.leavePath);
expect(leaveBtn.getAttribute('aria-label')).toBe('Leave this group');
expect(leaveBtn.dataset.originalTitle).toBe('Leave this group');
- expect(leaveBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(leaveBtn.querySelector('svg use').getAttribute('xlink:href')).toContain('#leave');
+ expect(leaveBtn.querySelectorAll('svg').length).not.toBe(0);
+ expect(leaveBtn.querySelector('svg').getAttribute('data-testid')).toBe('leave-icon');
newVm.$destroy();
});
diff --git a/spec/frontend/groups/components/item_caret_spec.js b/spec/frontend/groups/components/item_caret_spec.js
index bfe27be9b51..4ff7482414c 100644
--- a/spec/frontend/groups/components/item_caret_spec.js
+++ b/spec/frontend/groups/components/item_caret_spec.js
@@ -27,12 +27,12 @@ describe('ItemCaretComponent', () => {
it('should render caret down icon if `isGroupOpen` prop is `true`', () => {
vm = createComponent(true);
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-down');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('angle-down-icon');
});
it('should render caret right icon if `isGroupOpen` prop is `false`', () => {
vm = createComponent();
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-right');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('angle-right-icon');
});
});
});
diff --git a/spec/frontend/groups/components/item_stats_value_spec.js b/spec/frontend/groups/components/item_stats_value_spec.js
index da6f145fa19..11246390444 100644
--- a/spec/frontend/groups/components/item_stats_value_spec.js
+++ b/spec/frontend/groups/components/item_stats_value_spec.js
@@ -72,7 +72,7 @@ describe('ItemStatsValueComponent', () => {
});
it('renders element icon correctly', () => {
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('folder');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('folder-icon');
});
it('renders value count correctly', () => {
diff --git a/spec/frontend/groups/components/item_type_icon_spec.js b/spec/frontend/groups/components/item_type_icon_spec.js
index 251b5b5ff4c..477c413ddcd 100644
--- a/spec/frontend/groups/components/item_type_icon_spec.js
+++ b/spec/frontend/groups/components/item_type_icon_spec.js
@@ -27,12 +27,12 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.GROUP, true);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder-open');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('folder-open-icon');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('folder-o-icon');
vm.$destroy();
});
@@ -41,12 +41,12 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.PROJECT);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('bookmark');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('bookmark-icon');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).not.toContain('bookmark');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).not.toBe('bookmark-icon');
vm.$destroy();
});
});
diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js
index 4bd27d23f76..2a106ad37c0 100644
--- a/spec/frontend/ide/components/file_row_extra_spec.js
+++ b/spec/frontend/ide/components/file_row_extra_spec.js
@@ -153,14 +153,14 @@ describe('IDE extra file row component', () => {
describe('merge request icon', () => {
it('hides when not a merge request change', () => {
- expect(vm.$el.querySelector('.ic-git-merge')).toBe(null);
+ expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null);
});
it('shows when a merge request change', done => {
vm.file.mrChange = true;
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ic-git-merge')).not.toBe(null);
+ expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null);
done();
});
diff --git a/spec/frontend/ide/components/jobs/detail/description_spec.js b/spec/frontend/ide/components/jobs/detail/description_spec.js
index babae00d2f7..65b579105b0 100644
--- a/spec/frontend/ide/components/jobs/detail/description_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/description_spec.js
@@ -23,6 +23,8 @@ describe('IDE job description', () => {
});
it('renders CI icon', () => {
- expect(vm.$el.querySelector('.ci-status-icon .ic-status_success_borderless')).not.toBe(null);
+ expect(
+ vm.$el.querySelector('.ci-status-icon [data-testid="status_success_borderless-icon"]'),
+ ).not.toBe(null);
});
});
diff --git a/spec/frontend/ide/components/jobs/item_spec.js b/spec/frontend/ide/components/jobs/item_spec.js
index 2f97d39e98e..93c01640b54 100644
--- a/spec/frontend/ide/components/jobs/item_spec.js
+++ b/spec/frontend/ide/components/jobs/item_spec.js
@@ -24,7 +24,7 @@ describe('IDE jobs item', () => {
});
it('renders CI icon', () => {
- expect(vm.$el.querySelector('.ic-status_success_borderless')).not.toBe(null);
+ expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null);
});
it('does not render view logs button if not started', done => {
diff --git a/spec/frontend/ide/components/merge_requests/item_spec.js b/spec/frontend/ide/components/merge_requests/item_spec.js
index b1da89d7a9b..20adaa7abbc 100644
--- a/spec/frontend/ide/components/merge_requests/item_spec.js
+++ b/spec/frontend/ide/components/merge_requests/item_spec.js
@@ -33,7 +33,7 @@ describe('IDE merge request item', () => {
store,
});
};
- const findIcon = () => wrapper.find('.ic-mobile-issue-close');
+ const findIcon = () => wrapper.find('[data-testid="mobile-issue-close-icon"]');
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/ide/components/nav_dropdown_button_spec.js b/spec/frontend/ide/components/nav_dropdown_button_spec.js
index 2aa3992a6d8..c98aa313f40 100644
--- a/spec/frontend/ide/components/nav_dropdown_button_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_button_spec.js
@@ -23,7 +23,7 @@ describe('NavDropdown', () => {
vm.$mount();
};
- const findIcon = name => vm.$el.querySelector(`.ic-${name}`);
+ const findIcon = name => vm.$el.querySelector(`[data-testid="${name}-icon"]`);
const findMRIcon = () => findIcon('merge-request');
const findBranchIcon = () => findIcon('branch');
diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js
index ce123d925c8..2f91ab7af0a 100644
--- a/spec/frontend/ide/components/nav_dropdown_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_spec.js
@@ -39,7 +39,7 @@ describe('IDE NavDropdown', () => {
});
};
- const findIcon = name => wrapper.find(`.ic-${name}`);
+ const findIcon = name => wrapper.find(`[data-testid="${name}-icon"]`);
const findMRIcon = () => findIcon('merge-request');
const findNavForm = () => wrapper.find('.ide-nav-form');
const showDropdown = () => {
diff --git a/spec/frontend/ide/components/new_dropdown/button_spec.js b/spec/frontend/ide/components/new_dropdown/button_spec.js
index 3c611b7de8f..66317296ee9 100644
--- a/spec/frontend/ide/components/new_dropdown/button_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/button_spec.js
@@ -28,7 +28,7 @@ describe('IDE new entry dropdown button component', () => {
});
it('renders icon', () => {
- expect(vm.$el.querySelector('.ic-doc-new')).not.toBe(null);
+ expect(vm.$el.querySelector('[data-testid="doc-new-icon"]')).not.toBe(null);
});
it('emits click event', () => {
diff --git a/spec/frontend/jobs/components/log/collapsible_section_spec.js b/spec/frontend/jobs/components/log/collapsible_section_spec.js
index bf2f8c05806..66f22162c97 100644
--- a/spec/frontend/jobs/components/log/collapsible_section_spec.js
+++ b/spec/frontend/jobs/components/log/collapsible_section_spec.js
@@ -35,7 +35,7 @@ describe('Job Log Collapsible Section', () => {
});
it('renders an icon with the closed state', () => {
- expect(findCollapsibleLineSvg().classes()).toContain('ic-angle-right');
+ expect(findCollapsibleLineSvg().attributes('data-testid')).toBe('angle-right-icon');
});
});
@@ -52,7 +52,7 @@ describe('Job Log Collapsible Section', () => {
});
it('renders an icon with the open state', () => {
- expect(findCollapsibleLineSvg().classes()).toContain('ic-angle-down');
+ expect(findCollapsibleLineSvg().attributes('data-testid')).toBe('angle-down-icon');
});
it('renders collapsible lines content', () => {
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
index 02cdb31d27e..a6285fe64b5 100644
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ b/spec/frontend/jobs/components/log/log_spec.js
@@ -42,6 +42,8 @@ describe('Job Log', () => {
wrapper.destroy();
});
+ const findCollapsibleLine = () => wrapper.find('.collapsible-line');
+
describe('line numbers', () => {
it('renders a line number for each open line', () => {
expect(wrapper.find('#L1').text()).toBe('1');
@@ -56,18 +58,18 @@ describe('Job Log', () => {
describe('collapsible sections', () => {
it('renders a clickable header section', () => {
- expect(wrapper.find('.collapsible-line').attributes('role')).toBe('button');
+ expect(findCollapsibleLine().attributes('role')).toBe('button');
});
it('renders an icon with the open state', () => {
- expect(wrapper.find('.collapsible-line svg').classes()).toContain('ic-angle-down');
+ expect(findCollapsibleLine().contains('[data-testid="angle-down-icon"]')).toBe(true);
});
describe('on click header section', () => {
it('calls toggleCollapsibleLine', () => {
jest.spyOn(wrapper.vm, 'toggleCollapsibleLine');
- wrapper.find('.collapsible-line').trigger('click');
+ findCollapsibleLine().trigger('click');
expect(wrapper.vm.toggleCollapsibleLine).toHaveBeenCalled();
});
diff --git a/spec/frontend/matchers.js b/spec/frontend/matchers.js
index 53c6a72eea0..50feba86a61 100644
--- a/spec/frontend/matchers.js
+++ b/spec/frontend/matchers.js
@@ -9,8 +9,8 @@ export default {
}
const iconReferences = [].slice.apply(element.querySelectorAll('svg use'));
- const matchingIcon = iconReferences.find(reference =>
- reference.getAttribute('xlink:href').endsWith(`#${iconName}`),
+ const matchingIcon = iconReferences.find(
+ reference => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`,
);
const pass = Boolean(matchingIcon);
@@ -22,7 +22,7 @@ export default {
message = `${element.outerHTML} does not contain the sprite icon "${iconName}"!`;
const existingIcons = iconReferences.map(reference => {
- const iconUrl = reference.getAttribute('xlink:href');
+ const iconUrl = reference.getAttribute('href');
return `"${iconUrl.replace(/^.+#/, '')}"`;
});
if (existingIcons.length > 0) {
diff --git a/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js b/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
index 1905ca0d5e1..533528e1dca 100644
--- a/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
+++ b/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
@@ -126,7 +126,7 @@ describe('Grouped code quality reports app', () => {
});
it('renders a help icon with more information', () => {
- expect(findWidget().html()).toContain('ic-question');
+ expect(findWidget().contains('[data-testid="question-icon"]')).toBe(true);
});
});
@@ -140,7 +140,7 @@ describe('Grouped code quality reports app', () => {
});
it('does not render a help icon', () => {
- expect(findWidget().html()).not.toContain('ic-question');
+ expect(findWidget().contains('[data-testid="question-icon"]')).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_shared/components/icon_spec.js b/spec/frontend/vue_shared/components/icon_spec.js
deleted file mode 100644
index 16728e1705a..00000000000
--- a/spec/frontend/vue_shared/components/icon_spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import Vue from 'vue';
-import { mount } from '@vue/test-utils';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import iconsPath from '@gitlab/svgs/dist/icons.svg';
-import Icon from '~/vue_shared/components/icon.vue';
-
-jest.mock('@gitlab/svgs/dist/icons.svg', () => 'testing');
-
-describe('Sprite Icon Component', () => {
- describe('Initialization', () => {
- let icon;
-
- beforeEach(() => {
- const IconComponent = Vue.extend(Icon);
-
- icon = mountComponent(IconComponent, {
- name: 'commit',
- size: 32,
- });
- });
-
- afterEach(() => {
- icon.$destroy();
- });
-
- it('should return a defined Vue component', () => {
- expect(icon).toBeDefined();
- });
-
- it('should have