Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-03-10 18:09:32 +00:00
parent d2091d1e92
commit bac259ea8b
61 changed files with 786 additions and 184 deletions

View file

@ -192,7 +192,7 @@ export default {
<gl-button
v-if="canRenderPipelineButton"
block
class="gl-mt-3 gl-mb-0 gl-md-display-none"
class="gl-mt-3 gl-mb-3 gl-md-display-none"
variant="success"
data-testid="run_pipeline_button_mobile"
:loading="state.isRunningMergeRequestPipeline"

View file

@ -85,7 +85,7 @@ export default {
this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader);
this.service
.getFolderContent(folder.folder_path)
.getFolderContent(folder.folder_path, folder.state)
.then((response) => this.store.setfolderContent(folder, response.data.environments))
.then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false))
.catch(() => {

View file

@ -21,7 +21,7 @@ export default class EnvironmentsService {
return axios.delete(endpoint, {});
}
getFolderContent(folderUrl) {
return axios.get(`${folderUrl}.json?per_page=${this.folderResults}`);
getFolderContent(folderUrl, scope) {
return axios.get(`${folderUrl}.json?per_page=${this.folderResults}&scope=${scope}`);
}
}

View file

@ -292,7 +292,7 @@ export default {
failure.text
}}</gl-alert>
<div class="gl-mb-3">
<h3>{{ s__('PipelineCharts|CI / CD Analytics') }}</h3>
<h3>{{ s__('PipelineCharts|CI/CD Analytics') }}</h3>
</div>
<h4 class="gl-my-4">{{ s__('PipelineCharts|Overall statistics') }}</h4>
<div class="row">

View file

@ -6,8 +6,8 @@ module Types
graphql_name 'DiffPositionType'
description 'Type of file the position refers to'
value 'text'
value 'image'
value 'text', description: "A text file"
value 'image', description: "An image"
end
end
end

View file

@ -58,7 +58,7 @@ module Analytics
return unless project.feature_available?(:builds, current_user) || !project.empty_repo?
navbar_sub_item(
title: _('CI / CD'),
title: _('CI/CD'),
path: 'pipelines#charts',
link: charts_project_pipelines_path(project)
)

View file

@ -1,5 +1,5 @@
- breadcrumb_title _("CI / CD Settings")
- page_title _("CI / CD")
- breadcrumb_title _("CI/CD Settings")
- page_title _("CI/CD")
- expanded = expanded_by_default?
- general_expanded = @group.errors.empty? ? expanded : true

View file

@ -171,9 +171,9 @@
= _('Repository')
= nav_link(controller: :ci_cd) do
= link_to group_settings_ci_cd_path(@group), title: _('CI / CD') do
= link_to group_settings_ci_cd_path(@group), title: _('CI/CD') do
%span
= _('CI / CD')
= _('CI/CD')
= render 'groups/sidebar/packages_settings'

View file

@ -179,13 +179,13 @@
.nav-icon-container
= sprite_icon('rocket')
%span.nav-item-name#js-onboarding-pipelines-link
= _('CI / CD')
= _('CI/CD')
%ul.sidebar-sub-level-items
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts, :test_cases, :pipeline_editor], html_options: { class: "fly-out-top-item" }) do
= link_to project_pipelines_path(@project) do
%strong.fly-out-top-item-name
= _('CI / CD')
= _('CI/CD')
%li.divider.fly-out-top-item
- if project_nav_tab? :pipelines
= nav_link(path: ['pipelines#index', 'pipelines#show']) do
@ -418,9 +418,9 @@
= _('Repository')
- if !@project.archived? && @project.feature_available?(:builds, current_user)
= nav_link(controller: :ci_cd) do
= link_to project_settings_ci_cd_path(@project), title: _('CI / CD') do
= link_to project_settings_ci_cd_path(@project), title: _('CI/CD') do
%span
= _('CI / CD')
= _('CI/CD')
- if settings_operations_available?
= nav_link(controller: [:operations]) do
= link_to project_settings_operations_path(@project), title: _('Operations'), data: { qa_selector: 'operations_settings_link' } do

View file

@ -1,4 +1,4 @@
- page_title _('CI / CD Analytics')
- page_title _('CI/CD Analytics')
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
should_render_deployment_frequency_charts: should_render_deployment_frequency_charts.to_s } }

View file

@ -1,6 +1,6 @@
- @content_class = "limit-container-width" unless fluid_layout
- page_title _("CI / CD Settings")
- page_title _("CI / CD")
- page_title _("CI/CD Settings")
- page_title _("CI/CD")
- expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true

View file

@ -13,13 +13,6 @@
.user-profile
.cover-block.user-cover-block{ class: [('border-bottom' if profile_tabs.empty?)] }
= render layout: 'users/cover_controls' do
- if current_user && current_user.id != @user.id
- if current_user.following?(@user)
= link_to user_unfollow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
= _('Unfollow')
- else
= link_to user_follow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
= _('Follow')
- if @user == current_user
= link_to profile_path, class: link_classes + 'btn gl-button btn-default btn-icon has-tooltip',
title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
@ -41,6 +34,13 @@
= link_to [:admin, @user], class: link_classes + 'btn gl-button btn-default btn-icon', title: s_('UserProfile|View user in admin area'),
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('user')
- if current_user && current_user.id != @user.id
- if current_user.following?(@user)
= link_to user_unfollow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
= _('Unfollow')
- else
= link_to user_follow_path(@user, :json) , class: link_classes + 'btn gl-button btn-confirm', method: :post do
= _('Follow')
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
.avatar-holder

View file

@ -0,0 +1,5 @@
---
title: Reorder user profile actions and use the confirm variant for the follow button
merge_request: 55999
author:
type: other

View file

@ -0,0 +1,5 @@
---
title: Add last_used_at field to cluster agent token
merge_request: 56023
author:
type: changed

View file

@ -0,0 +1,5 @@
---
title: Bump swagger-ui-dist to 3.44.1
merge_request: 55310
author: Roger Meier
type: changed

View file

@ -0,0 +1,5 @@
---
title: Fixed vestigial Anchor links in doc/development/usage_ping/dictionary.md
merge_request: 55874
author: Raimund Hook
type: fixed

View file

@ -0,0 +1,5 @@
---
title: Expand nested stopped environments
merge_request: 55676
author:
type: changed

View file

@ -0,0 +1,5 @@
---
title: Migrate group milestones when using Bulk Import
merge_request: 55981
author:
type: added

View file

@ -0,0 +1,6 @@
---
title: Change the default batch_class_name for batched_background_migrations to the
unqualified class name
merge_request: 56036
author:
type: changed

View file

@ -0,0 +1,5 @@
---
title: Update UI text to CI/CD from CI / CD
merge_request: 56070
author:
type: other

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
class ChangeBatchedBackgroundMigrationsBatchClassNameDefault < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
change_column_default :batched_background_migrations, :batch_class_name,
from: 'Gitlab::Database::BackgroundMigration::PrimaryKeyBatchingStrategy', to: 'PrimaryKeyBatchingStrategy'
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddLastUsedAtToClusterAgentToken < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :cluster_agent_tokens, :last_used_at, :datetime_with_timezone
end
end

View file

@ -0,0 +1 @@
cc131cf37f2af8f0f58c7fa6e5055e88a3b2ed413862c155b0d18383aba06058

View file

@ -0,0 +1 @@
a31b85b8ab0db2ad4daa5f2c15eacae97432e75e0e0a28f10d81f6a5aa94c8e0

View file

@ -9876,7 +9876,7 @@ CREATE TABLE batched_background_migrations (
"interval" smallint NOT NULL,
status smallint DEFAULT 0 NOT NULL,
job_class_name text NOT NULL,
batch_class_name text DEFAULT 'Gitlab::Database::BackgroundMigration::PrimaryKeyBatchingStrategy'::text NOT NULL,
batch_class_name text DEFAULT 'PrimaryKeyBatchingStrategy'::text NOT NULL,
table_name text NOT NULL,
column_name text NOT NULL,
job_arguments jsonb DEFAULT '"[]"'::jsonb NOT NULL,
@ -11156,6 +11156,7 @@ CREATE TABLE cluster_agent_tokens (
created_by_user_id bigint,
description text,
name text,
last_used_at timestamp with time zone,
CONSTRAINT check_2b79dbb315 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_4e4ec5070a CHECK ((char_length(description) <= 1024)),
CONSTRAINT check_c60daed227 CHECK ((char_length(token_encrypted) <= 255))

View file

@ -1063,6 +1063,70 @@ encounter this error.
Administrators can increase the token duration in **Admin area > Settings >
CI/CD > Container Registry > Authorization token duration (minutes)**.
### Docker login attempt fails with: 'token signed by untrusted key'
[Registry relies on GitLab to validate credentials](https://docs.gitlab.com/omnibus/architecture/registry/).
If the registry fails to authenticate valid login attempts, you get the following error message:
```shell
# docker login gitlab.company.com:4567
Username: user
Password:
Error response from daemon: login attempt to https://gitlab.company.com:4567/v2/ failed with status: 401 Unauthorized
```
And more specifically, this appears in the `/var/log/gitlab/registry/current` log file:
```plaintext
level=info msg="token signed by untrusted key with ID: "TOKE:NL6Q:7PW6:EXAM:PLET:OKEN:BG27:RCIB:D2S3:EXAM:PLET:OKEN""
level=warning msg="error authorizing context: invalid token" go.version=go1.12.7 http.request.host="gitlab.company.com:4567" http.request.id=74613829-2655-4f96-8991-1c9fe33869b8 http.request.method=GET http.request.remoteaddr=10.72.11.20 http.request.uri="/v2/" http.request.useragent="docker/19.03.2 go/go1.12.8 git-commit/6a30dfc kernel/3.10.0-693.2.2.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.2 \(linux\))"
```
GitLab uses the contents of the certificate key pair's two sides to encrypt the authentication token
for the Registry. This message means that those contents do not align.
Check which files are in use:
- `grep -A6 'auth:' /var/opt/gitlab/registry/config.yml`
```yaml
## Container Registry Certificate
auth:
token:
realm: https://gitlab.my.net/jwt/auth
service: container_registry
issuer: omnibus-gitlab-issuer
--> rootcertbundle: /var/opt/gitlab/registry/gitlab-registry.crt
autoredirect: false
```
- `grep -A9 'Container Registry' /var/opt/gitlab/gitlab-rails/etc/gitlab.yml`
```yaml
## Container Registry Key
registry:
enabled: true
host: gitlab.company.com
port: 4567
api_url: http://127.0.0.1:5000 # internal address to the registry, will be used by GitLab to directly communicate with API
path: /var/opt/gitlab/gitlab-rails/shared/registry
--> key: /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key
issuer: omnibus-gitlab-issuer
notification_secret:
```
The output of these `openssl` commands should match, proving that the cert-key pair is a match:
```shell
openssl x509 -noout -modulus -in /var/opt/gitlab/registry/gitlab-registry.crt | openssl sha256
openssl rsa -noout -modulus -in /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key | openssl sha256
```
If the two pieces of the certificate do not align, remove the files and run `gitlab-ctl reconfigure`
to regenerate the pair. If you have overridden the automatically generated self-signed pair with
your own certificates and have made sure that their contents align, you can delete the 'registry'
section in your `/etc/gitlab/gitlab-secrets.json` and run `gitlab-ctl reconfigure`.
### AWS S3 with the GitLab registry error when pushing large images
When using AWS S3 with the GitLab registry, an error may occur when pushing

View file

@ -5386,8 +5386,8 @@ Type of file the position refers to.
| Value | Description |
| ----- | ----------- |
| `image` | |
| `text` | |
| `image` | An image |
| `text` | A text file |
### `EntryType`

View file

@ -45,8 +45,8 @@ GET /projects
| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
| `id_after` | integer | **{dotted-circle}** No | Limit results to projects with IDs greater than the specified ID. |
| `id_before` | integer | **{dotted-circle}** No | Limit results to projects with IDs less than the specified ID. |
| `last_activity_after` | datetime | **{dotted-circle}** No | Limit results to projects with last_activity after specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
| `last_activity_before` | datetime | **{dotted-circle}** No | Limit results to projects with last_activity before specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
| `last_activity_after` | datetime | **{dotted-circle}** No | Limit results to projects with last_activity after specified time. Format: ISO 8601 `YYYY-MM-DDTHH:MM:SSZ` |
| `last_activity_before` | datetime | **{dotted-circle}** No | Limit results to projects with last_activity before specified time. Format: ISO 8601 `YYYY-MM-DDTHH:MM:SSZ` |
| `membership` | boolean | **{dotted-circle}** No | Limit by projects that the current user is a member of. |
| `min_access_level` | integer | **{dotted-circle}** No | Limit by current user minimal [access level](members.md#valid-access-levels). |
| `order_by` | string | **{dotted-circle}** No | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. `repository_size`, `storage_size`, `packages_size` or `wiki_size` fields are only allowed for admins. Default is `created_at`. |
@ -1005,10 +1005,13 @@ If the project is a fork, and you provide a valid token to authenticate, the
}
```
### Templates for issues and merge requests **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55718) in GitLab 13.10.
Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/)
can also see the `issues_template` and `merge_requests_template` parameters:
[introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55718)
in GitLab 13.10.
can also see the `issues_template` and `merge_requests_template` parameters for managing
[issue and merge request description templates](../user/project/description_templates.md).
```json
{
@ -1110,7 +1113,7 @@ POST /projects
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
@ -1184,7 +1187,7 @@ POST /projects/user/:user_id
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
@ -1257,7 +1260,7 @@ PUT /projects/:id
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|----------------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `analytics_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). |
@ -1317,8 +1320,8 @@ PUT /projects/:id
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `wiki_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable wiki for this project. Use `wiki_access_level` instead. |
| `issues_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Issues. Description is parsed with GitLab Flavored Markdown. |
| `merge_requests_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Merge Requests. Description is parsed with GitLab Flavored Markdown. |
| `issues_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Issues. Description is parsed with GitLab Flavored Markdown. See [Templates for issues and merge requests](#templates-for-issues-and-merge-requests). |
| `merge_requests_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Merge Requests. Description is parsed with GitLab Flavored Markdown. See [Templates for issues and merge requests](#templates-for-issues-and-merge-requests). |
## Fork project
@ -2537,12 +2540,6 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
Read more in the [Project Badges](project_badges.md) documentation.
## Issue and merge request description templates
The non-default [issue and merge request description templates](../user/project/description_templates.md)
are managed inside the project's repository. So you can manage them with the API
through the [Repositories API](repositories.md) and the [Repository Files API](repository_files.md).
## Download snapshot of a Git repository
> Introduced in GitLab 10.7

View file

@ -347,13 +347,112 @@ example, you can find which tests take longest to run or which execute the most
queries. This can be handy for optimizing our tests or identifying performance
issues in our code.
## Memory profiling
## Memory optimization
We can use two approaches, often in combination, to track down memory issues:
We can use a set of different techniques, often in combination, to track down memory issues:
- Leaving the code intact and wrapping a profiler around it.
- Use memory allocation counters for requests and services.
- Monitor memory usage of the process while disabling/enabling different parts of the code we suspect could be problematic.
### Memory allocations
Ruby shipped with GitLab includes a special patch to allow [tracing memory allocations](https://gitlab.com/gitlab-org/gitlab/-/issues/296530).
This patch is available by default for
[Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4948),
[CNG](https://gitlab.com/gitlab-org/build/CNG/-/merge_requests/591),
[GitLab CI](https://gitlab.com/gitlab-org/gitlab-build-images/-/merge_requests/355),
[GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit/-/merge_requests/149)
and can additionally be enabled for [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/advanced.md#apply-custom-patches-for-ruby).
This patch provides a set of 3 metrics that makes it easier to understand efficiency of memory usage for a given codepath:
- `mem_objects`: the number of objects allocated.
- `mem_bytes`: the number of bytes allocated by malloc.
- `mem_mallocs`: the number of malloc allocations.
The number of objects and bytes allocated impact how often GC cycles happen.
Fewer objects allocations result in a significantly more responsive application.
It is advised that web server requests do not allocate more than `100k mem_objects`
and `100M mem_bytes`. You can view the current usage on [GitLab.com](https://log.gprd.gitlab.net/goto/3a9678bb595e3f89a0c7b5c61bcc47b9).
#### Checking memory pressure of own code
There are two ways of measuring your own code:
1. Review `api_json.log`, `development_json.log`, `sidekiq.log` that includes memory allocation counters.
1. Use `Gitlab::Memory::Instrumentation.with_memory_allocations` for a given codeblock and log it.
1. Use [Measuring module](service_measurement.md)
```json
{"time":"2021-02-15T11:20:40.821Z","severity":"INFO","duration_s":0.27412,"db_duration_s":0.05755,"view_duration_s":0.21657,"status":201,"method":"POST","path":"/api/v4/projects/user/1","mem_objects":86705,"mem_bytes":4277179,"mem_mallocs":22693,"correlation_id":"...}
```
#### Different types of allocations
The `mem_*` values represent different aspects of how objects and memory are allocated in Ruby:
- The following example will create around of `1000` of `mem_objects` since strings
can be frozen, and while the underlying string object remains the same, we still need to allocate 1000 references to this string:
```ruby
Gitlab::Memory::Instrumentation.with_memory_allocations do
1_000.times { '0123456789' }
end
=> {:mem_objects=>1001, :mem_bytes=>0, :mem_mallocs=>0}
```
- The following example will create around of `1000` of `mem_objects`, as strings are created dynamically.
Each of them will not allocate additional memory, as they fit into Ruby slot of 40 bytes:
```ruby
Gitlab::Memory::Instrumentation.with_memory_allocations do
s = '0'
1_000.times { s * 23 }
end
=> {:mem_objects=>1002, :mem_bytes=>0, :mem_mallocs=>0}
```
- The following example will create around of `1000` of `mem_objects`, as strings are created dynamically.
Each of them will allocate additional memory as strings are larger than Ruby slot of 40 bytes:
```ruby
Gitlab::Memory::Instrumentation.with_memory_allocations do
s = '0'
1_000.times { s * 24 }
end
=> {:mem_objects=>1002, :mem_bytes=>32000, :mem_mallocs=>1000}
```
- The following example will allocate over 40kB of data, and perform only a single memory allocation.
The existing object will be reallocated/resized on subsequent iterations:
```ruby
Gitlab::Memory::Instrumentation.with_memory_allocations do
str = ''
append = '0123456789012345678901234567890123456789' # 40 bytes
1_000.times { str.concat(append) }
end
=> {:mem_objects=>3, :mem_bytes=>49152, :mem_mallocs=>1}
```
- The following example will create over 1k of objects, perform over 1k of allocations, each time mutating the object.
This does result in copying a lot of data and perform a lot of memory allocations
(as represented by `mem_bytes` counter) indicating very inefficient method of appending string:
```ruby
Gitlab::Memory::Instrumentation.with_memory_allocations do
str = ''
append = '0123456789012345678901234567890123456789' # 40 bytes
1_000.times { str += append }
end
=> {:mem_objects=>1003, :mem_bytes=>21968752, :mem_mallocs=>1000}
```
### Using Memory Profiler
We can use `memory_profiler` for profiling.

View file

@ -2818,7 +2818,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.ldap_group_links`
Number of groups that are synced via LDAP group sync `https://docs.gitlab.com/ee/user/group/index.html#manage-group-memberships-via-ldap-starter-only`
Number of groups that are synced via LDAP group sync `https://docs.gitlab.com/ee/user/group/index.html#manage-group-memberships-via-ldap`
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216174822_ldap_group_links.yml)
@ -2830,7 +2830,7 @@ Tiers: `premium`, `ultimate`
### `counts.ldap_keys`
Number of keys synced as part of LDAP `https://docs.gitlab.com/ee/administration/auth/ldap/#ldap-sync-configuration-settings-starter-only`
Number of keys synced as part of LDAP `https://docs.gitlab.com/ee/administration/auth/ldap/#ldap-sync-configuration-settings`
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216174824_ldap_keys.yml)
@ -14158,7 +14158,7 @@ Tiers: `free`
### `usage_activity_by_stage.manage.ldap_admin_sync_enabled`
Has the instance configured LDAP Admin Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#administrator-sync-starter-only`?
Has the instance configured LDAP Admin Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#administrator-sync`?
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180811_ldap_admin_sync_enabled.yml)
@ -14170,7 +14170,7 @@ Tiers:
### `usage_activity_by_stage.manage.ldap_group_sync_enabled`
Has the instance configured LDAP Group Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#group-sync-starter-only`?
Has the instance configured LDAP Group Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#group-sync`?
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180809_ldap_group_sync_enabled.yml)
@ -14194,7 +14194,7 @@ Tiers: `free`
### `usage_activity_by_stage.manage.ldap_servers`
Number of LDAP servers configured for the instance `https://docs.gitlab.com/ee/administration/auth/ldap/#multiple-ldap-servers-starter-only`
Number of LDAP servers configured for the instance `https://docs.gitlab.com/ee/administration/auth/ldap/#multiple-ldap-servers`
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180807_ldap_servers.yml)

View file

@ -158,6 +158,7 @@ A **project** in GitLab is what holds a repository, which holds your files.
Often, the word "repository" is shortened to "repo".
<!-- vale gitlab.Spelling = YES -->
<!-- vale gitlab.SubstitutionWarning = YES -->
### Fork
When you want to copy someone else's repository, you [**fork**](../user/project/repository/forking_workflow.md#creating-a-fork)
@ -175,7 +176,7 @@ To create a copy of a remote repository's files on your computer, you can either
**download** or **clone**. If you download, you cannot sync it with the
remote repository on GitLab.
Cloning a repository is the same as downloading, except it preserves the Git connection
[Cloning](#clone-a-repository) a repository is the same as downloading, except it preserves the Git connection
with the remote repository. This allows you to modify the files locally and
upload the changes to the remote repository on GitLab.
@ -210,11 +211,13 @@ to GitLab, see how to [convert a local folder into a Git repository](#convert-a-
### Clone a repository
To start working locally on an existing remote repository, clone it with the
command `git clone <repository path>`. You can either clone it via [HTTPS](#clone-via-https) or [SSH](#clone-via-ssh), according to your preferred [authentication method](#git-authentication-methods).
command `git clone <repository path>`. You can either clone it via [HTTPS](#clone-via-https)
or [SSH](#clone-via-ssh), according to your preferred [authentication method](#git-authentication-methods).
You can find both paths (HTTPS and SSH) by navigating to your project's landing page
and clicking **Clone**. GitLab prompts you with both paths, from which you can copy
and paste in your command line.
and paste in your command line. You can also
[clone and open directly in Visual Studio Code](../user/project/repository/index.md#clone-and-open-in-apple-xcode).
For example, considering our [sample project](https://gitlab.com/gitlab-tests/sample-project/):

View file

@ -49,6 +49,14 @@ The following resources are migrated to the target instance:
- parent epic ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/297459))
- emoji award ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/297466))
- events ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/297465))
- Milestones ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292427))
- title
- description
- state (active / closed)
- start date
- due date
- created at
- updated at
Any other items are **not** migrated.

View file

@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Package Registry
# Package Registry **(FREE)**
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.

View file

@ -146,6 +146,10 @@ After you add the description, hit **Save changes** for the settings to take
effect. Now, every time a new merge request or issue is created, it is
pre-filled with the text you entered in the template(s).
[GitLab versions 13.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/885)
provide `issues_template` and `merge_requests_template` attributes in the
[Projects API](../../api/projects.md) to help you keep your templates up to date.
## Description template example
We make use of description templates for issues and merge requests in the GitLab project.

View file

@ -49,8 +49,9 @@ The steps you take depend on whether you are importing from GitHub.com or GitHub
[GitHub Rake task](../../../administration/raketasks/github_import.md) to import
projects without the constraints of a [Sidekiq](../../../development/sidekiq_style_guide.md) worker.
- If you're importing from GitHub Enterprise to your self-managed GitLab instance, you must first enable
[GitHub integration](../../../integration/github.md). However, you cannot import projects from GitHub Enterprise to GitLab.com.
- If you're importing from GitHub.com to your self-managed GitLab instance, you do not need to set up GitHub integration.
[GitHub integration](../../../integration/github.md).
- To import projects from GitHub Enterprise to GitLab.com, use the [Import API](../../../api/import.md).
- If you're importing from GitHub.com to your self-managed GitLab instance, you do not need to set up GitHub integration. You can use the [Import API](../../../api/import.md).
## How it works

View file

@ -166,8 +166,8 @@ There are two main ways of how you can discover snippets in GitLab.
For exploring all snippets that are visible to you, you can go to the Snippets
dashboard of your GitLab instance via the top navigation. For GitLab.com you can
navigate to an [overview]((https://gitlab.com/dashboard/snippets)) that shows snippets
you created and allows you to explore all snippets.
visit [GitLab Snippets](http://snippets.gitlab.com/) or navigate to an [overview]((https://gitlab.com/dashboard/snippets)) that shows snippets
you created and allows you to explore all snippets.
To discover snippets that belong to a specific project, navigate
to the Snippets page via the left side navigation on the project page.

View file

@ -0,0 +1,54 @@
# frozen_string_literal: true
module BulkImports
module Groups
module Graphql
module GetMilestonesQuery
extend self
def to_s
<<-'GRAPHQL'
query ($full_path: ID!, $cursor: String) {
group(fullPath: $full_path) {
milestones(first: 100, after: $cursor, includeDescendants: false) {
page_info: pageInfo {
end_cursor: endCursor
has_next_page: hasNextPage
}
nodes {
title
description
state
start_date: startDate
due_date: dueDate
created_at: createdAt
updated_at: updatedAt
}
}
}
}
GRAPHQL
end
def variables(context)
{
full_path: context.entity.source_full_path,
cursor: context.entity.next_page_for(:milestones)
}
end
def base_path
%w[data group milestones]
end
def data_path
base_path << 'nodes'
end
def page_info_path
base_path << 'page_info'
end
end
end
end
end

View file

@ -0,0 +1,42 @@
# frozen_string_literal: true
module BulkImports
module Groups
module Pipelines
class MilestonesPipeline
include Pipeline
extractor BulkImports::Common::Extractors::GraphqlExtractor,
query: BulkImports::Groups::Graphql::GetMilestonesQuery
transformer Common::Transformers::ProhibitedAttributesTransformer
def load(context, data)
return unless data
raise ::BulkImports::Pipeline::NotAllowedError unless authorized?
context.group.milestones.create!(data)
end
def after_run(extracted_data)
context.entity.update_tracker_for(
relation: :milestones,
has_next_page: extracted_data.has_next_page?,
next_page: extracted_data.next_page
)
if extracted_data.has_next_page?
run
end
end
private
def authorized?
context.current_user.can?(:admin_milestone, context.group)
end
end
end
end
end

View file

@ -24,7 +24,8 @@ module BulkImports
BulkImports::Groups::Pipelines::GroupPipeline,
BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline,
BulkImports::Groups::Pipelines::MembersPipeline,
BulkImports::Groups::Pipelines::LabelsPipeline
BulkImports::Groups::Pipelines::LabelsPipeline,
BulkImports::Groups::Pipelines::MilestonesPipeline
]
end
end

View file

@ -1,11 +1,22 @@
# frozen_string_literal: true
module Gitlab
module Database
module BackgroundMigration
module BackgroundMigration
module BatchingStrategies
# Generic batching class for use with a BatchedBackgroundMigration.
# Batches over the given table and column combination, returning the MIN() and MAX()
# values for the next batch as an array.
#
# If no more batches exist in the table, returns nil.
class PrimaryKeyBatchingStrategy
include Gitlab::Database::DynamicModelHelpers
# Finds and returns the next batch in the table.
#
# table_name - The table to batch over
# column_name - The column to batch over
# batch_min_value - The minimum value which the next batch will start at
# batch_size - The size of the next batch
def next_batch(table_name, column_name, batch_min_value:, batch_size:)
model_class = define_batchable_model(table_name)

View file

@ -99,10 +99,18 @@ module Gitlab
initial_config
end
def find_sha(project)
branches = project&.repository&.branches || []
unless branches.empty?
project.repository.root_ref_sha
end
end
def build_context(project:, sha:, user:, parent_pipeline:)
Config::External::Context.new(
project: project,
sha: sha || project&.repository&.root_ref_sha,
sha: sha || find_sha(project),
user: user,
parent_pipeline: parent_pipeline,
variables: project&.predefined_variables&.to_runner_variables)

View file

@ -21,7 +21,7 @@ module Gitlab
def initialize(project:, current_user:, sha: nil)
@project = project
@current_user = current_user
@sha = sha || project.repository.commit.sha
@sha = sha || project.repository.commit&.sha
end
def validate(content, dry_run: false)

View file

@ -4,6 +4,9 @@ module Gitlab
module Database
module BackgroundMigration
class BatchedMigration < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord
JOB_CLASS_MODULE = 'Gitlab::BackgroundMigration'
BATCH_CLASS_MODULE = "#{JOB_CLASS_MODULE}::BatchingStrategies".freeze
self.table_name = :batched_background_migrations
has_many :batched_jobs, foreign_key: :batched_background_migration_id
@ -20,10 +23,6 @@ module Gitlab
finished: 3
}
def self.remove_toplevel_prefix(name)
name&.sub(/\A::/, '')
end
def interval_elapsed?
last_job.nil? || last_job.created_at <= Time.current - interval
end
@ -37,19 +36,19 @@ module Gitlab
end
def job_class
job_class_name.constantize
"#{JOB_CLASS_MODULE}::#{job_class_name}".constantize
end
def batch_class
batch_class_name.constantize
"#{BATCH_CLASS_MODULE}::#{batch_class_name}".constantize
end
def job_class_name=(class_name)
write_attribute(:job_class_name, self.class.remove_toplevel_prefix(class_name))
write_attribute(:job_class_name, class_name.demodulize)
end
def batch_class_name=(class_name)
write_attribute(:batch_class_name, self.class.remove_toplevel_prefix(class_name))
write_attribute(:batch_class_name, class_name.demodulize)
end
end
end

View file

@ -5207,15 +5207,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
msgid "CI / CD"
msgstr ""
msgid "CI / CD Analytics"
msgstr ""
msgid "CI / CD Settings"
msgstr ""
msgid "CI Lint"
msgstr ""
@ -5234,6 +5225,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
msgid "CI/CD Analytics"
msgstr ""
msgid "CI/CD Settings"
msgstr ""
msgid "CI/CD configuration"
msgstr ""
@ -6277,6 +6274,21 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
msgid "Cloud License"
msgstr ""
msgid "CloudLicense|Activate"
msgstr ""
msgid "CloudLicense|Paste your activation code"
msgstr ""
msgid "CloudLicense|Paste your activation code below"
msgstr ""
msgid "CloudLicense|This instance is currently using the Core plan."
msgstr ""
msgid "Cluster"
msgstr ""
@ -22141,7 +22153,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
msgid "PipelineCharts|CI / CD Analytics"
msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"

View file

@ -141,7 +141,7 @@
"sql.js": "^0.4.0",
"string-hash": "1.1.3",
"style-loader": "^1.3.0",
"swagger-ui-dist": "^3.43.0",
"swagger-ui-dist": "^3.44.1",
"three": "^0.84.0",
"three-orbit-controls": "^82.1.0",
"three-stl-loader": "^1.0.4",

View file

@ -25,7 +25,7 @@ module QA
def go_to_ci_cd_settings
hover_settings do
within_submenu do
click_link('CI / CD')
click_link('CI/CD')
end
end
end

View file

@ -6,7 +6,7 @@ FactoryBot.define do
batch_size { 5 }
sub_batch_size { 1 }
interval { 2.minutes }
job_class_name { 'Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob' }
job_class_name { 'CopyColumnUsingBackgroundMigrationJob' }
table_name { :events }
column_name { :id }
end

View file

@ -132,13 +132,13 @@ RSpec.describe 'Project active tab' do
it_behaves_like 'page has active sub tab', _('Value Stream')
end
context 'on project Analytics/"CI / CD"' do
context 'on project Analytics/"CI/CD"' do
before do
click_tab(_('CI / CD'))
click_tab(_('CI/CD'))
end
it_behaves_like 'page has active tab', _('Analytics')
it_behaves_like 'page has active sub tab', _('CI / CD')
it_behaves_like 'page has active sub tab', _('CI/CD')
end
end
end

View file

@ -429,39 +429,69 @@ RSpec.describe 'Environments page', :js do
end
describe 'environments folders' do
before do
create(:environment, :will_auto_stop,
project: project,
name: 'staging/review-1',
state: :available)
create(:environment, :will_auto_stop,
project: project,
name: 'staging/review-2',
state: :available)
end
it 'users unfurls an environment folder' do
visit_environments(project)
expect(page).not_to have_content 'review-1'
expect(page).not_to have_content 'review-2'
expect(page).to have_content 'staging 2'
within('.folder-row') do
find('.folder-name', text: 'staging').click
describe 'available environments' do
before do
create(:environment, :will_auto_stop,
project: project,
name: 'staging/review-1',
state: :available)
create(:environment, :will_auto_stop,
project: project,
name: 'staging/review-2',
state: :available)
end
expect(page).to have_content 'review-1'
expect(page).to have_content 'review-2'
within('.ci-table') do
within('[data-qa-selector="environment_item"]', text: 'review-1') do
expect(find('.js-auto-stop').text).not_to be_empty
it 'users unfurls an environment folder' do
visit_environments(project)
expect(page).not_to have_content 'review-1'
expect(page).not_to have_content 'review-2'
expect(page).to have_content 'staging 2'
within('.folder-row') do
find('.folder-name', text: 'staging').click
end
within('[data-qa-selector="environment_item"]', text: 'review-2') do
expect(find('.js-auto-stop').text).not_to be_empty
expect(page).to have_content 'review-1'
expect(page).to have_content 'review-2'
within('.ci-table') do
within('[data-qa-selector="environment_item"]', text: 'review-1') do
expect(find('.js-auto-stop').text).not_to be_empty
end
within('[data-qa-selector="environment_item"]', text: 'review-2') do
expect(find('.js-auto-stop').text).not_to be_empty
end
end
end
end
describe 'stopped environments' do
before do
create(:environment, :will_auto_stop,
project: project,
name: 'staging/review-1',
state: :stopped)
create(:environment, :will_auto_stop,
project: project,
name: 'staging/review-2',
state: :stopped)
end
it 'users unfurls an environment folder' do
visit_environments(project, scope: 'stopped')
expect(page).not_to have_content 'review-1'
expect(page).not_to have_content 'review-2'
expect(page).to have_content 'staging 2'
within('.folder-row') do
find('.folder-name', text: 'staging').click
end
expect(page).to have_content 'review-1'
expect(page).to have_content 'review-2'
end
end
end
describe 'environments folders view' do

View file

@ -201,7 +201,7 @@ RSpec.describe 'Projects > User sees sidebar' do
expect(page).to have_content 'Operations'
expect(page).not_to have_content 'Repository'
expect(page).not_to have_content 'CI / CD'
expect(page).not_to have_content 'CI/CD'
expect(page).not_to have_content 'Merge Requests'
end
end
@ -213,7 +213,7 @@ RSpec.describe 'Projects > User sees sidebar' do
visit project_path(project)
within('.nav-sidebar') do
expect(page).to have_content 'CI / CD'
expect(page).to have_content 'CI/CD'
end
end

View file

@ -155,12 +155,12 @@ RSpec.describe 'User uses shortcuts', :js do
end
end
context 'when navigating to the CI / CD pages' do
context 'when navigating to the CI/CD pages' do
it 'redirects to the Jobs page' do
find('body').native.send_key('g')
find('body').native.send_key('j')
expect(page).to have_active_navigation('CI / CD')
expect(page).to have_active_navigation('CI/CD')
expect(page).to have_active_sub_navigation('Jobs')
end
end

View file

@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetMilestonesQuery do
it 'has a valid query' do
entity = create(:bulk_import_entity)
context = BulkImports::Pipeline::Context.new(entity)
query = GraphQL::Query.new(
GitlabSchema,
described_class.to_s,
variables: described_class.variables(context)
)
result = GitlabSchema.static_validator.validate(query)
expect(result[:errors]).to be_empty
end
describe '#data_path' do
it 'returns data path' do
expected = %w[data group milestones nodes]
expect(described_class.data_path).to eq(expected)
end
end
describe '#page_info_path' do
it 'returns pagination information path' do
expected = %w[data group milestones page_info]
expect(described_class.page_info_path).to eq(expected)
end
end
end

View file

@ -0,0 +1,151 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:cursor) { 'cursor' }
let_it_be(:timestamp) { Time.new(2020, 01, 01).utc }
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
let(:entity) do
create(
:bulk_import_entity,
bulk_import: bulk_import,
source_full_path: 'source/full/path',
destination_name: 'My Destination Group',
destination_namespace: group.full_path,
group: group
)
end
let(:context) { BulkImports::Pipeline::Context.new(entity) }
subject { described_class.new(context) }
def milestone_data(title)
{
'title' => title,
'description' => 'desc',
'state' => 'closed',
'start_date' => '2020-10-21',
'due_date' => '2020-10-22',
'created_at' => timestamp.to_s,
'updated_at' => timestamp.to_s
}
end
def extracted_data(title:, has_next_page:, cursor: nil)
page_info = {
'end_cursor' => cursor,
'has_next_page' => has_next_page
}
BulkImports::Pipeline::ExtractedData.new(data: [milestone_data(title)], page_info: page_info)
end
before do
group.add_owner(user)
end
describe '#run' do
it 'imports group milestones' do
first_page = extracted_data(title: 'milestone1', has_next_page: true, cursor: cursor)
last_page = extracted_data(title: 'milestone2', has_next_page: false)
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
allow(extractor)
.to receive(:extract)
.and_return(first_page, last_page)
end
expect { subject.run }.to change(Milestone, :count).by(2)
expect(group.milestones.pluck(:title)).to contain_exactly('milestone1', 'milestone2')
milestone = group.milestones.last
expect(milestone.description).to eq('desc')
expect(milestone.state).to eq('closed')
expect(milestone.start_date.to_s).to eq('2020-10-21')
expect(milestone.due_date.to_s).to eq('2020-10-22')
expect(milestone.created_at).to eq(timestamp)
expect(milestone.updated_at).to eq(timestamp)
end
end
describe '#after_run' do
context 'when extracted data has next page' do
it 'updates tracker information and runs pipeline again' do
data = extracted_data(title: 'milestone', has_next_page: true, cursor: cursor)
expect(subject).to receive(:run)
subject.after_run(data)
tracker = entity.trackers.find_by(relation: :milestones)
expect(tracker.has_next_page).to eq(true)
expect(tracker.next_page).to eq(cursor)
end
end
context 'when extracted data has no next page' do
it 'updates tracker information and does not run pipeline' do
data = extracted_data(title: 'milestone', has_next_page: false)
expect(subject).not_to receive(:run)
subject.after_run(data)
tracker = entity.trackers.find_by(relation: :milestones)
expect(tracker.has_next_page).to eq(false)
expect(tracker.next_page).to be_nil
end
end
end
describe '#load' do
it 'creates the milestone' do
data = milestone_data('milestone')
expect { subject.load(context, data) }.to change(Milestone, :count).by(1)
end
context 'when user is not authorized to create the milestone' do
before do
allow(user).to receive(:can?).with(:admin_milestone, group).and_return(false)
end
it 'raises NotAllowedError' do
data = extracted_data(title: 'milestone', has_next_page: false)
expect { subject.load(context, data) }.to raise_error(::BulkImports::Pipeline::NotAllowedError)
end
end
end
describe 'pipeline parts' do
it { expect(described_class).to include_module(BulkImports::Pipeline) }
it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
it 'has extractors' do
expect(described_class.get_extractor)
.to eq(
klass: BulkImports::Common::Extractors::GraphqlExtractor,
options: {
query: BulkImports::Groups::Graphql::GetMilestonesQuery
}
)
end
it 'has transformers' do
expect(described_class.transformers)
.to contain_exactly(
{ klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }
)
end
end
end

View file

@ -22,6 +22,7 @@ RSpec.describe BulkImports::Importers::GroupImporter do
expect_to_run_pipeline BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline, context: context
expect_to_run_pipeline BulkImports::Groups::Pipelines::MembersPipeline, context: context
expect_to_run_pipeline BulkImports::Groups::Pipelines::LabelsPipeline, context: context
expect_to_run_pipeline BulkImports::Groups::Pipelines::MilestonesPipeline, context: context
if Gitlab.ee?
expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicsPipeline'.constantize, context: context)

View file

@ -0,0 +1,45 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy, '#next_batch' do
let(:batching_strategy) { described_class.new }
let(:namespaces) { table(:namespaces) }
let!(:namespace1) { namespaces.create!(name: 'batchtest1', path: 'batch-test1') }
let!(:namespace2) { namespaces.create!(name: 'batchtest2', path: 'batch-test2') }
let!(:namespace3) { namespaces.create!(name: 'batchtest3', path: 'batch-test3') }
let!(:namespace4) { namespaces.create!(name: 'batchtest4', path: 'batch-test4') }
context 'when starting on the first batch' do
it 'returns the bounds of the next batch' do
batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace1.id, batch_size: 3)
expect(batch_bounds).to eq([namespace1.id, namespace3.id])
end
end
context 'when additional batches remain' do
it 'returns the bounds of the next batch' do
batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace2.id, batch_size: 3)
expect(batch_bounds).to eq([namespace2.id, namespace4.id])
end
end
context 'when on the final batch' do
it 'returns the bounds of the next batch' do
batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3)
expect(batch_bounds).to eq([namespace4.id, namespace4.id])
end
end
context 'when no additional batches remain' do
it 'returns nil' do
batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id + 1, batch_size: 1)
expect(batch_bounds).to be_nil
end
end
end

View file

@ -122,7 +122,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
describe '#batch_class' do
let(:batch_class) { Gitlab::Database::BackgroundMigration::PrimaryKeyBatchingStrategy}
let(:batch_class) { Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy}
let(:batched_migration) { build(:batched_background_migration) }
it 'returns the class of the batch strategy for the migration' do
@ -130,31 +130,31 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
shared_examples_for 'an attr_writer that normalizes assigned class names' do |attribute_name|
shared_examples_for 'an attr_writer that demodulizes assigned class names' do |attribute_name|
let(:batched_migration) { build(:batched_background_migration) }
context 'when the toplevel namespace prefix exists' do
it 'removes the leading prefix' do
context 'when a module name exists' do
it 'removes the module name' do
batched_migration.public_send(:"#{attribute_name}=", '::Foo::Bar')
expect(batched_migration[attribute_name]).to eq('Foo::Bar')
expect(batched_migration[attribute_name]).to eq('Bar')
end
end
context 'when the toplevel namespace prefix does not exist' do
context 'when a module name does not exist' do
it 'does not change the given class name' do
batched_migration.public_send(:"#{attribute_name}=", '::Foo::Bar')
batched_migration.public_send(:"#{attribute_name}=", 'Bar')
expect(batched_migration[attribute_name]).to eq('Foo::Bar')
expect(batched_migration[attribute_name]).to eq('Bar')
end
end
end
describe '#job_class_name=' do
it_behaves_like 'an attr_writer that normalizes assigned class names', :job_class_name
it_behaves_like 'an attr_writer that demodulizes assigned class names', :job_class_name
end
describe '#batch_class_name=' do
it_behaves_like 'an attr_writer that normalizes assigned class names', :batch_class_name
it_behaves_like 'an attr_writer that demodulizes assigned class names', :batch_class_name
end
end

View file

@ -1,44 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Database::BackgroundMigration::PrimaryKeyBatchingStrategy, '#next_batch' do
let(:batching_strategy) { described_class.new }
let_it_be(:event1) { create(:event) }
let_it_be(:event2) { create(:event) }
let_it_be(:event3) { create(:event) }
let_it_be(:event4) { create(:event) }
context 'when starting on the first batch' do
it 'returns the bounds of the next batch' do
batch_bounds = batching_strategy.next_batch(:events, :id, batch_min_value: event1.id, batch_size: 3)
expect(batch_bounds).to eq([event1.id, event3.id])
end
end
context 'when additional batches remain' do
it 'returns the bounds of the next batch' do
batch_bounds = batching_strategy.next_batch(:events, :id, batch_min_value: event2.id, batch_size: 3)
expect(batch_bounds).to eq([event2.id, event4.id])
end
end
context 'when on the final batch' do
it 'returns the bounds of the next batch' do
batch_bounds = batching_strategy.next_batch(:events, :id, batch_min_value: event4.id, batch_size: 3)
expect(batch_bounds).to eq([event4.id, event4.id])
end
end
context 'when no additional batches remain' do
it 'returns nil' do
batch_bounds = batching_strategy.next_batch(:events, :id, batch_min_value: event4.id + 1, batch_size: 1)
expect(batch_bounds).to be_nil
end
end
end

View file

@ -406,6 +406,24 @@ RSpec.describe API::Lint do
end
end
context 'with an empty repository' do
let_it_be(:empty_project) { create(:project_empty_repo) }
let_it_be(:yaml_content) do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
end
before do
empty_project.add_developer(api_user)
end
it 'passes validation without errors' do
post api("/projects/#{empty_project.id}/ci/lint", api_user), params: { content: yaml_content }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['valid']).to eq(true)
expect(json_response['errors']).to eq([])
end
end
context 'when unauthenticated' do
let_it_be(:api_user) { nil }

View file

@ -5,7 +5,7 @@ RSpec.shared_context 'project navbar structure' do
{
nav_item: _('Analytics'),
nav_sub_items: [
_('CI / CD'),
_('CI/CD'),
(_('Code Review') if Gitlab.ee?),
(_('Merge Request') if Gitlab.ee?),
_('Repository'),
@ -63,7 +63,7 @@ RSpec.shared_context 'project navbar structure' do
nav_sub_items: []
},
{
nav_item: _('CI / CD'),
nav_item: _('CI/CD'),
nav_sub_items: [
_('Pipelines'),
s_('Pipelines|Editor'),
@ -111,7 +111,7 @@ RSpec.shared_context 'project navbar structure' do
_('Webhooks'),
_('Access Tokens'),
_('Repository'),
_('CI / CD'),
_('CI/CD'),
_('Operations')
].compact
}
@ -138,7 +138,7 @@ RSpec.shared_context 'group navbar structure' do
_('Integrations'),
_('Projects'),
_('Repository'),
_('CI / CD'),
_('CI/CD'),
_('Packages & Registries'),
_('Webhooks')
]

View file

@ -204,7 +204,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it 'does not show the ci/cd settings tab' do
render
expect(rendered).not_to have_link('CI / CD', href: project_settings_ci_cd_path(project))
expect(rendered).not_to have_link('CI/CD', href: project_settings_ci_cd_path(project))
end
end
@ -214,7 +214,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it 'shows the ci/cd settings tab' do
render
expect(rendered).to have_link('CI / CD', href: project_settings_ci_cd_path(project))
expect(rendered).to have_link('CI/CD', href: project_settings_ci_cd_path(project))
end
end
end

View file

@ -11412,10 +11412,10 @@ svg-tags@^1.0.0:
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
swagger-ui-dist@^3.43.0:
version "3.43.0"
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.43.0.tgz#b064a2cec1d27776f9a124bc70423cfa0bbc0d3f"
integrity sha512-PtE+g23bNbYv8qqAVoPBqNQth8hU5Sl5ZsQ7gHXlO5jlCt31dVTiKI9ArHIT1b23ZzUYTnKsFgPYYFoiWyNCAw==
swagger-ui-dist@^3.44.1:
version "3.44.1"
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.44.1.tgz#757385a79698b8ef7045287be585671db4e4a252"
integrity sha512-N0u+aN55bp53RRwi/wFbEbkQxcHqZ445ShZR/Ct1Jg+XCMxYtocrsGavh7kdNKw5+6Rs4QDD6GzUMiT28Z1u3Q==
symbol-observable@^1.0.2:
version "1.2.0"