Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-02-23 12:10:56 +00:00
parent cd40f83527
commit 6cbe9eaeb3
79 changed files with 590 additions and 256 deletions

View File

@ -29,6 +29,7 @@ cache-repo:
- '[ -z "$CI_REPO_CACHE_CREDENTIALS" ] || gcloud auth activate-service-account --key-file=$CI_REPO_CACHE_CREDENTIALS'
script:
# Enable shallow repo caching only if the $ENABLE_SHALLOW_REPO_CACHING variable exists
# The `git repack` call works around a Git bug with shallow clones: https://gitlab.com/gitlab-org/git/-/issues/86
- if [ -n "$ENABLE_SHALLOW_REPO_CACHING" ]; then
cd .. && rm -rf $CI_PROJECT_NAME;
today=$(date +%Y-%m-%d);
@ -38,6 +39,7 @@ cache-repo:
echo "Cloning $CI_REPOSITORY_URL into $CI_PROJECT_NAME with commits from $one_year_ago.";
time git clone --progress --no-checkout --shallow-since=$one_year_ago $CI_REPOSITORY_URL $CI_PROJECT_NAME;
cd $CI_PROJECT_NAME;
time git repack -d;
echo "Archiving $CI_PROJECT_NAME into /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
time tar cf /tmp/$SHALLOW_CLONE_TAR_FILENAME .;
echo "GZipping /tmp/$SHALLOW_CLONE_TAR_FILENAME.";

View File

@ -1 +1 @@
771df64aaf511cc3c64d7b55aee2d961941bfdab
4139a25fddd1f6b99cc80aa89bd0ebc6594f5f4a

View File

@ -122,7 +122,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
gem 'gitlab-fog-azure-rm', '~> 1.0', require: false
gem 'gitlab-fog-azure-rm', '~> 1.0.1', require: false
# for Google storage
gem 'google-api-client', '~> 0.33'

View File

@ -428,7 +428,7 @@ GEM
gitlab-experiment (0.4.12)
activesupport (>= 3.0)
scientist (~> 1.5, >= 1.5.0)
gitlab-fog-azure-rm (1.0.0)
gitlab-fog-azure-rm (1.0.1)
azure-storage-blob (~> 2.0)
azure-storage-common (~> 2.0)
fog-core (= 2.1.0)
@ -737,7 +737,7 @@ GEM
mustermann (>= 1.0.0)
nap (1.1.0)
nenv (0.3.0)
net-http-persistent (4.0.0)
net-http-persistent (4.0.1)
connection_pool (~> 2.2)
net-ldap (0.16.3)
net-ntp (2.1.3)
@ -1372,7 +1372,7 @@ DEPENDENCIES
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-experiment (~> 0.4.12)
gitlab-fog-azure-rm (~> 1.0)
gitlab-fog-azure-rm (~> 1.0.1)
gitlab-labkit (= 0.14.0)
gitlab-license (~> 1.3)
gitlab-mail_room (~> 0.0.8)

View File

@ -1,2 +0,0 @@
// EE-specific feature. Find the implementation in the `ee/`-folder
export default () => {};

View File

@ -20,7 +20,7 @@ export default {
},
data() {
return {
searchTerm: this.value || '',
searchTerm: '',
};
},
computed: {
@ -38,11 +38,6 @@ export default {
);
},
},
watch: {
value(newVal) {
this.searchTerm = newVal;
},
},
methods: {
selectEnvironment(selected) {
this.$emit('selectEnvironment', selected);
@ -55,11 +50,14 @@ export default {
isSelected(env) {
return this.value === env;
},
clearSearch() {
this.searchTerm = '';
},
},
};
</script>
<template>
<gl-dropdown :text="value">
<gl-dropdown :text="value" @show="clearSearch">
<gl-search-box-by-type v-model.trim="searchTerm" data-testid="ci-environment-search" />
<gl-dropdown-item
v-for="environment in filteredResults"

View File

@ -1,5 +1,3 @@
import initDevopAdoption from 'ee_else_ce/admin/dev_ops_report/devops_adoption';
import initDevOpsScoreEmptyState from '~/admin/dev_ops_report/devops_score_empty_state';
import initDevOpsScoreEmptyState from '~/analytics/devops_report/devops_score_empty_state';
initDevOpsScoreEmptyState();
initDevopAdoption();

View File

@ -54,7 +54,7 @@ module Types
field :target_branch, GraphQL::STRING_TYPE, null: false,
description: 'Target branch of the merge request.'
field :work_in_progress, GraphQL::BOOLEAN_TYPE, method: :work_in_progress?, null: false,
description: 'Indicates if the merge request is a work in progress (WIP).'
description: 'Indicates if the merge request is a draft.'
field :merge_when_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).'
field :diff_head_sha, GraphQL::STRING_TYPE, null: true,

View File

@ -47,7 +47,7 @@ class UnifyCircuitService < ChatNotificationService
def notify(message, opts)
response = Gitlab::HTTP.post(webhook, body: {
subject: message.project_name,
text: message.pretext,
text: message.summary,
markdown: true
}.to_json)

View File

@ -46,7 +46,7 @@ class WebexTeamsService < ChatNotificationService
def notify(message, opts)
header = { 'Content-Type' => 'application/json' }
response = Gitlab::HTTP.post(webhook, headers: header, body: { markdown: message.pretext }.to_json)
response = Gitlab::HTTP.post(webhook, headers: header, body: { markdown: message.summary }.to_json)
response if response.success?
end

View File

@ -45,7 +45,7 @@ class Snippet < ApplicationRecord
has_many :notes, as: :noteable, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :user_mentions, class_name: "SnippetUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_one :snippet_repository, inverse_of: :snippet
has_many :repository_storage_moves, class_name: 'SnippetRepositoryStorageMove', inverse_of: :container
has_many :repository_storage_moves, class_name: 'Snippets::RepositoryStorageMove', inverse_of: :container
# We need to add the `dependent` in order to call the after_destroy callback
has_one :statistics, class_name: 'SnippetStatistics', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent

View File

@ -1,28 +1,13 @@
# frozen_string_literal: true
# SnippetRepositoryStorageMove are details of repository storage moves for a
# snippet. For example, moving a snippet to another gitaly node to help
# balance storage capacity.
class SnippetRepositoryStorageMove < ApplicationRecord
extend ::Gitlab::Utils::Override
include RepositoryStorageMovable
belongs_to :container, class_name: 'Snippet', inverse_of: :repository_storage_moves, foreign_key: :snippet_id
alias_attribute :snippet, :container
override :schedule_repository_storage_update_worker
def schedule_repository_storage_update_worker
SnippetUpdateRepositoryStorageWorker.perform_async(
snippet_id,
destination_storage_name,
id
)
end
private
override :error_key
def error_key
:snippet
end
# This is a compatibility class to avoid calling a non-existent
# class from sidekiq during deployment.
#
# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
# we cannot remove this class entirely because there can be jobs
# referencing it.
#
# We can get rid of this class in 14.0
# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
class SnippetRepositoryStorageMove < Snippets::RepositoryStorageMove
end

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
# Snippets::RepositoryStorageMove are details of repository storage moves for a
# snippet. For example, moving a snippet to another gitaly node to help
# balance storage capacity.
module Snippets
class RepositoryStorageMove < ApplicationRecord
extend ::Gitlab::Utils::Override
include RepositoryStorageMovable
self.table_name = 'snippet_repository_storage_moves'
belongs_to :container, class_name: 'Snippet', inverse_of: :repository_storage_moves, foreign_key: :snippet_id
alias_attribute :snippet, :container
override :schedule_repository_storage_update_worker
def schedule_repository_storage_update_worker
Snippets::UpdateRepositoryStorageWorker.perform_async(
snippet_id,
destination_storage_name,
id
)
end
private
override :error_key
def error_key
:snippet
end
end
end

View File

@ -25,7 +25,7 @@ module Snippets
override :schedule_bulk_worker_klass
def self.schedule_bulk_worker_klass
::SnippetScheduleBulkRepositoryShardMovesWorker
::Snippets::ScheduleBulkRepositoryShardMovesWorker
end
end
end

View File

@ -2204,6 +2204,22 @@
:weight: 1
:idempotent: true
:tags: []
- :name: snippets_schedule_bulk_repository_shard_moves
:feature_category: :gitaly
:has_external_dependencies:
:urgency: :throttled
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: snippets_update_repository_storage
:feature_category: :gitaly
:has_external_dependencies:
:urgency: :throttled
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: system_hook_push
:feature_category: :source_code_management
:has_external_dependencies:

View File

@ -1,13 +1,16 @@
# frozen_string_literal: true
class SnippetScheduleBulkRepositoryShardMovesWorker
include ApplicationWorker
# This is a compatibility class to avoid calling a non-existent
# class from sidekiq during deployment.
#
# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
# we cannot remove this class entirely because there can be jobs
# referencing it.
#
# We can get rid of this class in 14.0
# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
class SnippetScheduleBulkRepositoryShardMovesWorker < Snippets::ScheduleBulkRepositoryShardMovesWorker
idempotent!
feature_category :gitaly
urgency :throttled
def perform(source_storage_name, destination_storage_name = nil)
Snippets::ScheduleBulkRepositoryShardMovesService.new.execute(source_storage_name, destination_storage_name)
end
end

View File

@ -1,23 +1,15 @@
# frozen_string_literal: true
class SnippetUpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
extend ::Gitlab::Utils::Override
include UpdateRepositoryStorageWorker
private
override :find_repository_storage_move
def find_repository_storage_move(repository_storage_move_id)
SnippetRepositoryStorageMove.find(repository_storage_move_id)
end
override :find_container
def find_container(container_id)
Snippet.find(container_id)
end
override :update_repository_storage
def update_repository_storage(repository_storage_move)
::Snippets::UpdateRepositoryStorageService.new(repository_storage_move).execute
end
# This is a compatibility class to avoid calling a non-existent
# class from sidekiq during deployment.
#
# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
# we cannot remove this class entirely because there can be jobs
# referencing it.
#
# We can get rid of this class in 14.0
# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
class SnippetUpdateRepositoryStorageWorker < Snippets::UpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
idempotent!
urgency :throttled
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module Snippets
class ScheduleBulkRepositoryShardMovesWorker
include ApplicationWorker
idempotent!
feature_category :gitaly
urgency :throttled
def perform(source_storage_name, destination_storage_name = nil)
Snippets::ScheduleBulkRepositoryShardMovesService.new.execute(source_storage_name, destination_storage_name)
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Snippets
class UpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
extend ::Gitlab::Utils::Override
include ::UpdateRepositoryStorageWorker
private
override :find_repository_storage_move
def find_repository_storage_move(repository_storage_move_id)
Snippets::RepositoryStorageMove.find(repository_storage_move_id)
end
override :find_container
def find_container(container_id)
Snippet.find(container_id)
end
override :update_repository_storage
def update_repository_storage(repository_storage_move)
::Snippets::UpdateRepositoryStorageService.new(repository_storage_move).execute
end
end
end

View File

@ -0,0 +1,5 @@
---
title: Fix pipeline notifications for Webex Teams / Unify Circuit integrations
merge_request: 54852
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix setting default cadences migration
merge_request: 54598
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Clear Environment Search in CI/CD Variables
merge_request: 54626
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Fix UTF-8 characters not working with Azure Blob storage
merge_request: 54875
author:
type: fixed

View File

@ -1,8 +0,0 @@
---
name: ci_rules_variables
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48752
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289803
milestone: '13.7'
type: development
group: group::pipeline authoring
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: security_on_demand_scans_site_validation
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40685
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241815
milestone: '13.4'
type: development
group: group::dynamic analysis
default_enabled: true

View File

@ -50,6 +50,7 @@ Rails.application.routes.draw do
resource :welcome, only: [:show, :update], controller: 'welcome' do
Gitlab.ee do
get :trial_getting_started, on: :collection
get :trial_onboarding_board, on: :collection
end
end

View File

@ -346,6 +346,10 @@
- 1
- - snippet_update_repository_storage
- 1
- - snippets_schedule_bulk_repository_shard_moves
- 1
- - snippets_update_repository_storage
- 1
- - status_page_publish
- 1
- - sync_seat_link_request

View File

@ -17,11 +17,7 @@ class ScheduleSetDefaultIterationCadences < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
def up
Iteration.select(:group_id).distinct.each_batch(of: BATCH_SIZE, column: :group_id) do |batch, index|
group_ids = batch.pluck(:group_id)
migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, group_ids)
end
# Do nothing, rescheduling migration: 20210219102900_reschedule_set_default_iteration_cadences.rb
end
def down

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
class RescheduleSetDefaultIterationCadences < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
BATCH_SIZE = 1_000
DELAY_INTERVAL = 2.minutes.to_i
MIGRATION_CLASS = 'SetDefaultIterationCadences'
class Iteration < ActiveRecord::Base # rubocop:disable Style/Documentation
include EachBatch
self.table_name = 'sprints'
end
disable_ddl_transaction!
def up
Iteration.select(:group_id).distinct.each_batch(of: BATCH_SIZE, column: :group_id) do |batch, index|
group_ids = batch.pluck(:group_id)
migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, group_ids)
end
end
def down
# Not needed
end
end

View File

@ -0,0 +1 @@
42e06332b279aaac7044243df0a8bd5525025db7d8c22bc474c0874e85f525f5

View File

@ -9398,8 +9398,8 @@ CREATE TABLE application_settings (
keep_latest_artifact boolean DEFAULT true NOT NULL,
notes_create_limit integer DEFAULT 300 NOT NULL,
notes_create_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
in_product_marketing_emails_enabled boolean DEFAULT true NOT NULL,
kroki_formats jsonb DEFAULT '{}'::jsonb NOT NULL,
in_product_marketing_emails_enabled boolean DEFAULT true NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),

View File

@ -2675,7 +2675,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `userNotesCount` | Int | User notes count of the merge request. |
| `userPermissions` | MergeRequestPermissions! | Permissions for the current user on the resource |
| `webUrl` | String | Web URL of the merge request. |
| `workInProgress` | Boolean! | Indicates if the merge request is a work in progress (WIP). |
| `workInProgress` | Boolean! | Indicates if the merge request is a draft. |
### MergeRequestCreatePayload
@ -3227,7 +3227,7 @@ Represents vulnerability finding of a security report on the pipeline.
| `dastScannerProfiles` | DastScannerProfileConnection | The DAST scanner profiles associated with the project. |
| `dastSiteProfile` | DastSiteProfile | DAST Site Profile associated with the project. |
| `dastSiteProfiles` | DastSiteProfileConnection | DAST Site Profiles associated with the project. |
| `dastSiteValidations` | DastSiteValidationConnection | DAST Site Validations associated with the project. Always returns no nodes if `security_on_demand_scans_site_validation` is disabled. |
| `dastSiteValidations` | DastSiteValidationConnection | DAST Site Validations associated with the project. |
| `description` | String | Short description of the project. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `environment` | Environment | A single environment of the project. |

View File

@ -101,7 +101,7 @@ Parameters:
| `target_branch` | string | no | Return merge requests with the given target branch. |
| `search` | string | no | Search merge requests against their `title` and `description`. |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description`. |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests. |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* draft merge requests, `no` to return *non-draft* merge requests. |
| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. |
| `environment` | string | no | Returns merge requests deployed to the given environment. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `deployed_before` | datetime | no | Return merge requests deployed before the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
@ -287,7 +287,7 @@ Parameters:
| `source_branch` | string | no | Return merge requests with the given source branch. |
| `target_branch` | string | no | Return merge requests with the given target branch. |
| `search` | string | no | Search merge requests against their `title` and `description`. |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests. |
| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* draft merge requests, `no` to return *non-draft* merge requests. |
| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. |
```json

View File

@ -1436,14 +1436,7 @@ In this example, if the first rule matches, then the job has `when: manual` and
#### `rules:variables`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209864) in GitLab 13.7.
> - It was [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/289803) on GitLab 13.8.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-rulesvariables). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289803) in GitLab 13.10.
You can use [`variables`](#variables) in `rules:` to define variables for specific conditions.
@ -1465,25 +1458,6 @@ job:
- echo "Run another script if $IS_A_FEATURE exists"
```
##### Enable or disable rules:variables **(FREE SELF)**
rules:variables is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can opt to disable it.
To enable it:
```ruby
Feature.enable(:ci_rules_variables)
```
To disable it:
```ruby
Feature.disable(:ci_rules_variables)
```
#### Complex rule clauses
To conjoin `if`, `changes`, and `exists` clauses with an `AND`, use them in the

View File

@ -146,7 +146,7 @@ One way to generate the initial list is to run the `todo` auto generation,
with `exclude limit` set to a high number.
```shell
bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit=10000
bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit=100000
```
You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively

View File

@ -340,3 +340,7 @@ bundle exec rake gitlab:graphql:schema:dump
```
This uses GraphQL Ruby's built-in Rake tasks to generate files in both [IDL](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51) and JSON formats.
### Update documentation and schema definitions
The following command combines the intent of [Update GraphQL documentation and schema definitions](#update-graphql-documentation-and-schema-definitions) and [Update machine-readable schema files](#update-machine-readable-schema-files):

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
module API
module Entities
module Snippets
class RepositoryStorageMove < BasicRepositoryStorageMove
expose :snippet, using: Entities::BasicSnippet
end
end
end
end

View File

@ -11,28 +11,28 @@ module API
resource :snippet_repository_storage_moves do
desc 'Get a list of all snippet repository storage moves' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
success Entities::Snippets::RepositoryStorageMove
end
params do
use :pagination
end
get do
storage_moves = SnippetRepositoryStorageMove.order_created_at_desc
storage_moves = ::Snippets::RepositoryStorageMove.order_created_at_desc
present paginate(storage_moves), with: Entities::SnippetRepositoryStorageMove, current_user: current_user
present paginate(storage_moves), with: Entities::Snippets::RepositoryStorageMove, current_user: current_user
end
desc 'Get a snippet repository storage move' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
success Entities::Snippets::RepositoryStorageMove
end
params do
requires :repository_storage_move_id, type: Integer, desc: 'The ID of a snippet repository storage move'
end
get ':repository_storage_move_id' do
storage_move = SnippetRepositoryStorageMove.find(params[:repository_storage_move_id])
storage_move = ::Snippets::RepositoryStorageMove.find(params[:repository_storage_move_id])
present storage_move, with: Entities::SnippetRepositoryStorageMove, current_user: current_user
present storage_move, with: Entities::Snippets::RepositoryStorageMove, current_user: current_user
end
desc 'Schedule bulk snippet repository storage moves' do
@ -68,7 +68,7 @@ module API
desc 'Get a list of all snippets repository storage moves' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
success Entities::Snippets::RepositoryStorageMove
end
params do
use :pagination
@ -76,12 +76,12 @@ module API
get ':id/repository_storage_moves' do
storage_moves = user_snippet.repository_storage_moves.order_created_at_desc
present paginate(storage_moves), with: Entities::SnippetRepositoryStorageMove, current_user: current_user
present paginate(storage_moves), with: Entities::Snippets::RepositoryStorageMove, current_user: current_user
end
desc 'Get a snippet repository storage move' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
success Entities::Snippets::RepositoryStorageMove
end
params do
requires :repository_storage_move_id, type: Integer, desc: 'The ID of a snippet repository storage move'
@ -89,12 +89,12 @@ module API
get ':id/repository_storage_moves/:repository_storage_move_id' do
storage_move = user_snippet.repository_storage_moves.find(params[:repository_storage_move_id])
present storage_move, with: Entities::SnippetRepositoryStorageMove, current_user: current_user
present storage_move, with: Entities::Snippets::RepositoryStorageMove, current_user: current_user
end
desc 'Schedule a snippet repository storage move' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
success Entities::Snippets::RepositoryStorageMove
end
params do
optional :destination_storage_name, type: String, desc: 'The destination storage shard'
@ -105,7 +105,7 @@ module API
)
if storage_move.schedule
present storage_move, with: Entities::SnippetRepositoryStorageMove, current_user: current_user
present storage_move, with: Entities::Snippets::RepositoryStorageMove, current_user: current_user
else
render_validation_error!(storage_move)
end

View File

@ -12,8 +12,8 @@ module Banzai
def customize_allowlist(allowlist)
# Allow table alignment; we allow specific text-align values in a
# transformer below
allowlist[:attributes]['th'] = %w(style)
allowlist[:attributes]['td'] = %w(style)
allowlist[:attributes]['th'] = %w[style]
allowlist[:attributes]['td'] = %w[style]
allowlist[:css] = { properties: ['text-align'] }
# Allow the 'data-sourcepos' from CommonMark on all elements
@ -25,7 +25,7 @@ module Banzai
# Allow `id` in a and li elements for footnotes
# and remove any `id` properties not matching for footnotes
allowlist[:attributes]['a'].push('id')
allowlist[:attributes]['li'] = %w(id)
allowlist[:attributes]['li'] = %w[id]
allowlist[:transformers].push(self.class.remove_non_footnote_ids)
allowlist

View File

@ -16,6 +16,8 @@ module Gitlab
class Group < ApplicationRecord
self.table_name = 'namespaces'
self.inheritance_column = :_type_disabled
end
def perform(*group_ids)
@ -27,6 +29,7 @@ module Gitlab
def create_iterations_cadences(group_ids)
groups_with_cadence = IterationCadence.select(:group_id)
new_cadences = Group.where(id: group_ids).where.not(id: groups_with_cadence).map do |group|
last_iteration = Iteration.where(group_id: group.id).order(:start_date)&.last
@ -44,7 +47,7 @@ module Gitlab
)
end
IterationCadence.bulk_insert!(new_cadences.compact)
IterationCadence.bulk_insert!(new_cadences.compact, skip_duplicates: true)
end
def assign_iterations_cadences(group_ids)

View File

@ -59,10 +59,6 @@ module Gitlab
::Feature.enabled?(:ci_pipeline_editor_page, project, default_enabled: :yaml)
end
def self.rules_variables_enabled?(project)
::Feature.enabled?(:ci_rules_variables, project, default_enabled: true)
end
def self.validate_build_dependencies?(project)
::Feature.enabled?(:ci_validate_build_dependencies, project, default_enabled: :yaml) &&
::Feature.disabled?(:ci_validate_build_dependencies_override, project)

View File

@ -169,15 +169,11 @@ module Gitlab
strong_memoize(:rules_attributes) do
next {} unless @using_rules
if ::Gitlab::Ci::Features.rules_variables_enabled?(@pipeline.project)
rules_variables_result = ::Gitlab::Ci::Variables::Helpers.merge_variables(
@seed_attributes[:yaml_variables], rules_result.variables
)
rules_variables_result = ::Gitlab::Ci::Variables::Helpers.merge_variables(
@seed_attributes[:yaml_variables], rules_result.variables
)
rules_result.build_attributes.merge(yaml_variables: rules_variables_result)
else
rules_result.build_attributes
end
rules_result.build_attributes.merge(yaml_variables: rules_variables_result)
end
end

View File

@ -130,6 +130,9 @@ namespace :gitlab do
abort
end
end
desc 'GitLab | GraphQL | Update GraphQL docs and schema'
task update_all: [:compile_docs, 'schema:dump']
end
end

View File

@ -4227,12 +4227,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
msgid "Attachment"
msgstr ""
msgid "Attachments"
msgstr ""
msgid "Audit Events"
msgstr ""

View File

@ -37,6 +37,14 @@ RUN wget -q "https://chromedriver.storage.googleapis.com/${CHROME_DRIVER_VERSION
RUN unzip chromedriver_linux64.zip -d /usr/local/bin
RUN rm -f chromedriver_linux64.zip
##
# Install root certificate
#
RUN mkdir -p /usr/share/ca-certificates/gitlab
ADD ./qa/tls_certificates/authority/ca.crt /usr/share/ca-certificates/gitlab/
RUN echo 'gitlab/ca.crt' >> /etc/ca-certificates.conf
RUN chmod -R 644 /usr/share/ca-certificates/gitlab && update-ca-certificates
##
# Install gcloud and kubectl CLI used in Auto DevOps test to create K8s
# clusters

View File

@ -5,6 +5,7 @@ module QA
describe 'Add project member' do
before do
Runtime::Feature.enable('vue_project_members_list')
Runtime::Feature.enable(:invite_members_group_modal)
end
after do
Runtime::Feature.disable('vue_project_members_list')
@ -19,8 +20,6 @@ module QA
project.name = 'add-member-project'
end
Runtime::Feature.enable(:invite_members_group_modal)
project.visit!
Page::Project::Menu.perform(&:click_members)

View File

@ -2,7 +2,8 @@
module QA
RSpec.describe 'Manage' do
describe 'Repository tags' do
# TODO: Remove :requires_admin meta when the `Runtime::Feature.enable` method call is removed
describe 'Repository tags', :requires_admin do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-for-tags'

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFizCCA3OgAwIBAgIUJBX+SiNuqUYjf33EuMObynTcKx0wDQYJKoZIhvcNAQEL
BQAwVTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xGTAXBgNVBAoMEEdpdExhYiBBdXRob3JpdHkwHhcNMjEw
MjExMDYyMTUzWhcNMzEwMjA5MDYyMTUzWjBVMQswCQYDVQQGEwJVUzETMBEGA1UE
CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQ
R2l0TGFiIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
ALxpL/dfJwhIWGYK93ovIVj+gqvJI58Sga7eWlp2LpuFQZETjJBA79R0gcwr42ph
ch1BuxoxkYizM8sqIyFa5aW8SCWmO+IQzedKWZv+UWZg6pG+Fzyp6GO1wmXZdeXw
xRiXp2qV+rqA8DaL2g1c2u6TB/mcfNTrfsSP3045yQW+4mdNx/g4wBf0dMpHe5DJ
5jIvowa2O0kesq1UQ1eM9IMNSwW8fMQenV+F41LWE1NO726ksglih9TQjAIrlX6I
XVmw0lgYegt2G+YQJ68nf2UmvK+C0KqzTZgqmzNMQnuSiJXMnlZvlgdLXTyTWCuq
tyxp3+Z2Wshk/Cghic2MCm2XwWBIqYGu+20qoPM61c3Rk5++2VOcajD1yCYxVtM2
akVP/e9arlCdi/CtJh3qvOlj9Uhs6a1UR/ZngpPLOa3r4JazZc04pK7q3ZynmoUL
oDPF9AKOikvhYKxTYsgZ65VhI3myTBjQFk9qX++z2HF9UImGblqUtckn3eIoI8n2
wd4pO/OFeFSXpR7jMywCwXTpC8yTTbuVzHEz8H83/qtsbjtw961g4kb8Vzh1zy73
PFiJNI7hZlP1I5dqNTOAv+GnwiSnF28i7xbdkIfmjYqwcwGhAO7rjifq8ygBH3sF
0I/6dnw4BvNlSgSJlJ1+2eH1uiaikpuOGtQAttz536dNAgMBAAGjUzBRMB0GA1Ud
DgQWBBQSNZ46Xu4rfGVIPIQJpduWHJ+AQjAfBgNVHSMEGDAWgBQSNZ46Xu4rfGVI
PIQJpduWHJ+AQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQC1
4REbDKF1tdYeCxpmQHXLHu7OkrgKIea6eKxf8mI+ZsJA4iNr3aiZYU5Wm+uAq3mK
x6mrQRaqoo6JNbie5Tw8fU2c71EO4t3vwB7YOsBtcV0YrMtg316UE0lk+6kL0TRD
tV7dAGCB3wXZVLPolC26/kecc258p6h4rCJ8Gi6FsIKGBisTFk3QOdLG3DQNulPF
2bZaJjs/6HqLL+QMdChUfJP3i71LdNxzwXNPbjJ3fm5f9RNeOcWo6oI2fkQArl2i
vcP/QtuqeOoJusbeL9zaF/EFlOggjkEtzFWCB05d6J7dMKYp5Lg4eMZQHPw6ycdk
Ek/XTupvBk+8UiXeHLvX6II9zww9+gm3uycPiO/CSPNw4yQBPPGW+30WznbedsuY
m79rxuq50KYvseJSPv7lw8v77ajQbRQzFi4frAFR+A1g8FArLxdpIptI9E+ekmaB
UMhCmi17mEuBtj8Hc3VrokTFtAJV6YNIk1X+Q/zLh4TaR5mm6C/82j/ZvkSm5OX7
TfaayRWDr7AfDKeG5Amt52BmYncsPUXnOofSz5UkqpeOWr0rKn+A7f2BeUP9R2nY
6DncxYA+yOgU7RpnMBscsW6SkVIMJKFrfeZ1SbvZGRJd4L1PwfeaU+3yEG6oAfMa
CFquw23nWhjvUlnCe9BaUiEtOJ2ruGjdu2sdvXPcnw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,83 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFizCCA3OgAwIBAgIUJBX+SiNuqUYjf33EuMObynTcKx0wDQYJKoZIhvcNAQEL
BQAwVTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xGTAXBgNVBAoMEEdpdExhYiBBdXRob3JpdHkwHhcNMjEw
MjExMDYyMTUzWhcNMzEwMjA5MDYyMTUzWjBVMQswCQYDVQQGEwJVUzETMBEGA1UE
CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQ
R2l0TGFiIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
ALxpL/dfJwhIWGYK93ovIVj+gqvJI58Sga7eWlp2LpuFQZETjJBA79R0gcwr42ph
ch1BuxoxkYizM8sqIyFa5aW8SCWmO+IQzedKWZv+UWZg6pG+Fzyp6GO1wmXZdeXw
xRiXp2qV+rqA8DaL2g1c2u6TB/mcfNTrfsSP3045yQW+4mdNx/g4wBf0dMpHe5DJ
5jIvowa2O0kesq1UQ1eM9IMNSwW8fMQenV+F41LWE1NO726ksglih9TQjAIrlX6I
XVmw0lgYegt2G+YQJ68nf2UmvK+C0KqzTZgqmzNMQnuSiJXMnlZvlgdLXTyTWCuq
tyxp3+Z2Wshk/Cghic2MCm2XwWBIqYGu+20qoPM61c3Rk5++2VOcajD1yCYxVtM2
akVP/e9arlCdi/CtJh3qvOlj9Uhs6a1UR/ZngpPLOa3r4JazZc04pK7q3ZynmoUL
oDPF9AKOikvhYKxTYsgZ65VhI3myTBjQFk9qX++z2HF9UImGblqUtckn3eIoI8n2
wd4pO/OFeFSXpR7jMywCwXTpC8yTTbuVzHEz8H83/qtsbjtw961g4kb8Vzh1zy73
PFiJNI7hZlP1I5dqNTOAv+GnwiSnF28i7xbdkIfmjYqwcwGhAO7rjifq8ygBH3sF
0I/6dnw4BvNlSgSJlJ1+2eH1uiaikpuOGtQAttz536dNAgMBAAGjUzBRMB0GA1Ud
DgQWBBQSNZ46Xu4rfGVIPIQJpduWHJ+AQjAfBgNVHSMEGDAWgBQSNZ46Xu4rfGVI
PIQJpduWHJ+AQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQC1
4REbDKF1tdYeCxpmQHXLHu7OkrgKIea6eKxf8mI+ZsJA4iNr3aiZYU5Wm+uAq3mK
x6mrQRaqoo6JNbie5Tw8fU2c71EO4t3vwB7YOsBtcV0YrMtg316UE0lk+6kL0TRD
tV7dAGCB3wXZVLPolC26/kecc258p6h4rCJ8Gi6FsIKGBisTFk3QOdLG3DQNulPF
2bZaJjs/6HqLL+QMdChUfJP3i71LdNxzwXNPbjJ3fm5f9RNeOcWo6oI2fkQArl2i
vcP/QtuqeOoJusbeL9zaF/EFlOggjkEtzFWCB05d6J7dMKYp5Lg4eMZQHPw6ycdk
Ek/XTupvBk+8UiXeHLvX6II9zww9+gm3uycPiO/CSPNw4yQBPPGW+30WznbedsuY
m79rxuq50KYvseJSPv7lw8v77ajQbRQzFi4frAFR+A1g8FArLxdpIptI9E+ekmaB
UMhCmi17mEuBtj8Hc3VrokTFtAJV6YNIk1X+Q/zLh4TaR5mm6C/82j/ZvkSm5OX7
TfaayRWDr7AfDKeG5Amt52BmYncsPUXnOofSz5UkqpeOWr0rKn+A7f2BeUP9R2nY
6DncxYA+yOgU7RpnMBscsW6SkVIMJKFrfeZ1SbvZGRJd4L1PwfeaU+3yEG6oAfMa
CFquw23nWhjvUlnCe9BaUiEtOJ2ruGjdu2sdvXPcnw==
-----END CERTIFICATE-----

View File

@ -1,29 +1,29 @@
# frozen_string_literal: true
FactoryBot.define do
factory :snippet_repository_storage_move, class: 'SnippetRepositoryStorageMove' do
factory :snippet_repository_storage_move, class: 'Snippets::RepositoryStorageMove' do
container { association(:snippet) }
source_storage_name { 'default' }
trait :scheduled do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:scheduled].value }
state { Snippets::RepositoryStorageMove.state_machines[:state].states[:scheduled].value }
end
trait :started do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:started].value }
state { Snippets::RepositoryStorageMove.state_machines[:state].states[:started].value }
end
trait :replicated do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:replicated].value }
state { Snippets::RepositoryStorageMove.state_machines[:state].states[:replicated].value }
end
trait :finished do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:finished].value }
state { Snippets::RepositoryStorageMove.state_machines[:state].states[:finished].value }
end
trait :failed do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:failed].value }
state { Snippets::RepositoryStorageMove.state_machines[:state].states[:failed].value }
end
end
end

View File

@ -89,6 +89,8 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j
before do
page.within '.mr-widget-body' do
page.click_link 'Resolve all threads in new issue', href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid)
wait_for_all_requests
end
end

View File

@ -24,7 +24,6 @@ RSpec.describe 'Project variables', :js do
find('[data-qa-selector="ci_variable_key_field"] input').set('akey')
find('#ci-variable-value').set('akey_value')
find('[data-testid="environment-scope"]').click
find_button('clear').click
find('[data-testid="ci-environment-search"]').set('review/*')
find('[data-testid="create-wildcard-button"]').click

View File

@ -1,4 +1,4 @@
import { GlDropdownItem, GlIcon } from '@gitlab/ui';
import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
@ -10,6 +10,9 @@ describe('Ci environments dropdown', () => {
let wrapper;
let store;
const enterSearchTerm = (value) =>
wrapper.find('[data-testid="ci-environment-search"]').setValue(value);
const createComponent = (term) => {
store = new Vuex.Store({
getters: {
@ -24,11 +27,12 @@ describe('Ci environments dropdown', () => {
value: term,
},
});
enterSearchTerm(term);
};
const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
const findDropdownItemByIndex = (index) => wrapper.findAll(GlDropdownItem).at(index);
const findActiveIconByIndex = (index) => findDropdownItemByIndex(index).find(GlIcon);
const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
const findActiveIconByIndex = (index) => findDropdownItemByIndex(index).findComponent(GlIcon);
afterEach(() => {
wrapper.destroy();
@ -68,8 +72,9 @@ describe('Ci environments dropdown', () => {
});
describe('Environments found', () => {
beforeEach(() => {
beforeEach(async () => {
createComponent('prod');
await wrapper.vm.$nextTick();
});
it('renders only the environment searched for', () => {
@ -84,21 +89,29 @@ describe('Ci environments dropdown', () => {
});
it('should not display empty results message', () => {
expect(wrapper.find({ ref: 'noMatchingResults' }).exists()).toBe(false);
expect(wrapper.findComponent({ ref: 'noMatchingResults' }).exists()).toBe(false);
});
it('should display active checkmark if active', () => {
expect(findActiveIconByIndex(0).classes('gl-visibility-hidden')).toBe(false);
});
it('should clear the search term when showing the dropdown', () => {
wrapper.findComponent(GlDropdown).trigger('click');
expect(wrapper.find('[data-testid="ci-environment-search"]').text()).toBe('');
});
describe('Custom events', () => {
it('should emit selectEnvironment if an environment is clicked', () => {
findDropdownItemByIndex(0).vm.$emit('click');
expect(wrapper.emitted('selectEnvironment')).toEqual([['prod']]);
});
it('should emit createClicked if an environment is clicked', () => {
it('should emit createClicked if an environment is clicked', async () => {
createComponent('newscope');
await wrapper.vm.$nextTick();
findDropdownItemByIndex(1).vm.$emit('click');
expect(wrapper.emitted('createClicked')).toEqual([['newscope']]);
});

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe API::Entities::SnippetRepositoryStorageMove do
RSpec.describe API::Entities::Snippets::RepositoryStorageMove do
describe '#as_json' do
subject { entity.as_json }

View File

@ -33,14 +33,14 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
end
it 'sanitizes `class` attribute from all elements' do
act = %q{<pre class="code highlight white c"><code>&lt;span class="k"&gt;def&lt;/span&gt;</code></pre>}
exp = %q{<pre><code>&lt;span class="k"&gt;def&lt;/span&gt;</code></pre>}
act = %q(<pre class="code highlight white c"><code>&lt;span class="k"&gt;def&lt;/span&gt;</code></pre>)
exp = %q(<pre><code>&lt;span class="k"&gt;def&lt;/span&gt;</code></pre>)
expect(filter(act).to_html).to eq exp
end
it 'sanitizes `class` attribute from non-highlight spans' do
act = %q{<span class="k">def</span>}
expect(filter(act).to_html).to eq %q{<span>def</span>}
act = %q(<span class="k">def</span>)
expect(filter(act).to_html).to eq %q(<span>def</span>)
end
it 'allows `text-align` property in `style` attribute on table elements' do
@ -82,12 +82,12 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
end
it 'allows `span` elements' do
exp = act = %q{<span>Hello</span>}
exp = act = %q(<span>Hello</span>)
expect(filter(act).to_html).to eq exp
end
it 'allows `abbr` elements' do
exp = act = %q{<abbr title="HyperText Markup Language">HTML</abbr>}
exp = act = %q(<abbr title="HyperText Markup Language">HTML</abbr>)
expect(filter(act).to_html).to eq exp
end
@ -132,7 +132,7 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
end
it 'allows the `data-sourcepos` attribute globally' do
exp = %q{<p data-sourcepos="1:1-1:10">foo/bar.md</p>}
exp = %q(<p data-sourcepos="1:1-1:10">foo/bar.md</p>)
act = filter(exp)
expect(act.to_html).to eq exp
@ -140,41 +140,41 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
describe 'footnotes' do
it 'allows correct footnote id property on links' do
exp = %q{<a href="#fn1" id="fnref1">foo/bar.md</a>}
exp = %q(<a href="#fn1" id="fnref1">foo/bar.md</a>)
act = filter(exp)
expect(act.to_html).to eq exp
end
it 'allows correct footnote id property on li element' do
exp = %q{<ol><li id="fn1">footnote</li></ol>}
exp = %q(<ol><li id="fn1">footnote</li></ol>)
act = filter(exp)
expect(act.to_html).to eq exp
end
it 'removes invalid id for footnote links' do
exp = %q{<a href="#fn1">link</a>}
exp = %q(<a href="#fn1">link</a>)
%w[fnrefx test xfnref1].each do |id|
act = filter(%Q{<a href="#fn1" id="#{id}">link</a>})
act = filter(%(<a href="#fn1" id="#{id}">link</a>))
expect(act.to_html).to eq exp
end
end
it 'removes invalid id for footnote li' do
exp = %q{<ol><li>footnote</li></ol>}
exp = %q(<ol><li>footnote</li></ol>)
%w[fnx test xfn1].each do |id|
act = filter(%Q{<ol><li id="#{id}">footnote</li></ol>})
act = filter(%(<ol><li id="#{id}">footnote</li></ol>))
expect(act.to_html).to eq exp
end
end
it 'allows footnotes numbered higher than 9' do
exp = %q{<a href="#fn15" id="fnref15">link</a><ol><li id="fn15">footnote</li></ol>}
exp = %q(<a href="#fn15" id="fnref15">link</a><ol><li id="fn15">footnote</li></ol>)
act = filter(exp)
expect(act.to_html).to eq exp

View File

@ -17,8 +17,10 @@ RSpec.describe Gitlab::BackgroundMigration::SetDefaultIterationCadences, schema:
let!(:iteration_2) { iterations.create!(group_id: group_3.id, iid: 1, title: 'Iteration 2', start_date: 10.days.ago, due_date: 8.days.ago) }
let!(:iteration_3) { iterations.create!(group_id: group_3.id, iid: 1, title: 'Iteration 3', start_date: 5.days.ago, due_date: 2.days.ago) }
subject { described_class.new.perform(group_1.id, group_2.id, group_3.id, namespaces.last.id + 1) }
before do
described_class.new.perform(group_1.id, group_2.id, group_3.id, namespaces.last.id + 1)
subject
end
it 'creates iterations_cadence records for the requested groups' do
@ -45,6 +47,12 @@ RSpec.describe Gitlab::BackgroundMigration::SetDefaultIterationCadences, schema:
expect(iteration_records.first.id).to eq(iteration_2.id)
expect(iteration_records.second.id).to eq(iteration_3.id)
end
it 'does not call Group class' do
expect(::Group).not_to receive(:where)
subject
end
end
context 'when an iteration cadence exists for a group' do

View File

@ -85,17 +85,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }])
end
context 'when FF ci_rules_variables is disabled' do
before do
stub_feature_flags(ci_rules_variables: false)
end
it do
is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true },
{ key: 'VAR2', value: 'var 2', public: true }])
end
end
end
context 'with cache:key' do

View File

@ -224,6 +224,17 @@ RSpec.describe ObjectStorage::DirectUpload do
expect(subject[:CustomPutHeaders]).to be_truthy
expect(subject[:PutHeaders]).to eq({})
end
context 'with an object with UTF-8 characters' do
let(:object_name) { 'tmp/uploads/テスト' }
it 'returns an escaped path' do
expect(subject[:GetURL]).to start_with(storage_url)
uri = Addressable::URI.parse(subject[:GetURL])
expect(uri.path).to include("tmp/uploads/#{CGI.escape("テスト")}")
end
end
end
shared_examples 'a valid upload with multipart data' do

View File

@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
RSpec.describe ScheduleSetDefaultIterationCadences do
RSpec.describe RescheduleSetDefaultIterationCadences do
let(:namespaces) { table(:namespaces) }
let(:iterations) { table(:sprints) }

View File

@ -6,7 +6,16 @@ RSpec.describe DiscordService do
it_behaves_like "chat service", "Discord notifications" do
let(:client) { Discordrb::Webhooks::Client }
let(:client_arguments) { { url: webhook_url } }
let(:content_key) { :content }
let(:payload) do
{
embeds: [
include(
author: include(name: be_present),
description: be_present
)
]
}
end
end
describe '#execute' do

View File

@ -6,6 +6,10 @@ RSpec.describe HangoutsChatService do
it_behaves_like "chat service", "Hangouts Chat" do
let(:client) { HangoutsChat::Sender }
let(:client_arguments) { webhook_url }
let(:content_key) { :text }
let(:payload) do
{
text: be_present
}
end
end
end

View File

@ -5,6 +5,12 @@ require "spec_helper"
RSpec.describe UnifyCircuitService do
it_behaves_like "chat service", "Unify Circuit" do
let(:client_arguments) { webhook_url }
let(:content_key) { :subject }
let(:payload) do
{
subject: project.full_name,
text: be_present,
markdown: true
}
end
end
end

View File

@ -5,6 +5,10 @@ require "spec_helper"
RSpec.describe WebexTeamsService do
it_behaves_like "chat service", "Webex Teams" do
let(:client_arguments) { webhook_url }
let(:content_key) { :markdown }
let(:payload) do
{
markdown: be_present
}
end
end
end

View File

@ -8,6 +8,6 @@ RSpec.describe SnippetRepositoryStorageMove, type: :model do
let(:repository_storage_factory_key) { :snippet_repository_storage_move }
let(:error_key) { :snippet }
let(:repository_storage_worker) { SnippetUpdateRepositoryStorageWorker }
let(:repository_storage_worker) { Snippets::UpdateRepositoryStorageWorker }
end
end

View File

@ -21,7 +21,7 @@ RSpec.describe Snippet do
it { is_expected.to have_many(:user_mentions).class_name("SnippetUserMention") }
it { is_expected.to have_one(:snippet_repository) }
it { is_expected.to have_one(:statistics).class_name('SnippetStatistics').dependent(:destroy) }
it { is_expected.to have_many(:repository_storage_moves).class_name('SnippetRepositoryStorageMove').inverse_of(:container) }
it { is_expected.to have_many(:repository_storage_moves).class_name('Snippets::RepositoryStorageMove').inverse_of(:container) }
end
describe 'validation' do

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Snippets::RepositoryStorageMove, type: :model do
it_behaves_like 'handles repository moves' do
let_it_be_with_refind(:container) { create(:snippet) }
let(:repository_storage_factory_key) { :snippet_repository_storage_move }
let(:error_key) { :snippet }
let(:repository_storage_worker) { Snippets::UpdateRepositoryStorageWorker }
end
end

View File

@ -7,6 +7,6 @@ RSpec.describe API::SnippetRepositoryStorageMoves do
let_it_be(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
let_it_be(:storage_move) { create(:snippet_repository_storage_move, :scheduled, container: container) }
let(:repository_storage_move_factory) { :snippet_repository_storage_move }
let(:bulk_worker_klass) { SnippetScheduleBulkRepositoryShardMovesWorker }
let(:bulk_worker_klass) { Snippets::ScheduleBulkRepositoryShardMovesWorker }
end
end

View File

@ -180,20 +180,6 @@ RSpec.describe Ci::CreatePipelineService do
expect(variables['VAR2']).to eq('my var 2')
expect(variables['VAR3']).to be_nil
end
context 'when FF ci_rules_variables is disabled' do
before do
stub_feature_flags(ci_rules_variables: false)
end
it 'does not affect variables' do
variables = job.scoped_variables_hash
expect(variables['VAR1']).to eq('my var 1')
expect(variables['VAR2']).to eq('my var 2')
expect(variables['VAR3']).to be_nil
end
end
end
context 'when matching to the second rule' do

View File

@ -3,12 +3,15 @@
require 'spec_helper'
RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
subject(:execute_service) { described_class.new(track, interval).execute }
subject(:execute_service) do
travel_to(frozen_time) { described_class.new(track, interval).execute }
end
let(:track) { :create }
let(:interval) { 1 }
let(:previous_action_completed_at) { 2.days.ago.middle_of_day }
let(:frozen_time) { Time.current }
let(:previous_action_completed_at) { frozen_time - 2.days }
let(:current_action_completed_at) { nil }
let(:experiment_enabled) { true }
let(:user_can_perform_current_track_action) { true }
@ -35,22 +38,22 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
end
end
context 'for each track and series with the right conditions', :quarantine do # https://gitlab.com/gitlab-org/gitlab/-/issues/322092
context 'for each track and series with the right conditions' do
using RSpec::Parameterized::TableSyntax
where(:track, :interval, :actions_completed) do
:create | 1 | { created_at: 2.days.ago.middle_of_day }
:create | 5 | { created_at: 6.days.ago.middle_of_day }
:create | 10 | { created_at: 11.days.ago.middle_of_day }
:verify | 1 | { created_at: 2.days.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day }
:verify | 5 | { created_at: 6.days.ago.middle_of_day, git_write_at: 6.days.ago.middle_of_day }
:verify | 10 | { created_at: 11.days.ago.middle_of_day, git_write_at: 11.days.ago.middle_of_day }
:trial | 1 | { created_at: 2.days.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day, pipeline_created_at: 2.days.ago.middle_of_day }
:trial | 5 | { created_at: 6.days.ago.middle_of_day, git_write_at: 6.days.ago.middle_of_day, pipeline_created_at: 6.days.ago.middle_of_day }
:trial | 10 | { created_at: 11.days.ago.middle_of_day, git_write_at: 11.days.ago.middle_of_day, pipeline_created_at: 11.days.ago.middle_of_day }
:team | 1 | { created_at: 2.days.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day, pipeline_created_at: 2.days.ago.middle_of_day, trial_started_at: 2.days.ago.middle_of_day }
:team | 5 | { created_at: 6.days.ago.middle_of_day, git_write_at: 6.days.ago.middle_of_day, pipeline_created_at: 6.days.ago.middle_of_day, trial_started_at: 6.days.ago.middle_of_day }
:team | 10 | { created_at: 11.days.ago.middle_of_day, git_write_at: 11.days.ago.middle_of_day, pipeline_created_at: 11.days.ago.middle_of_day, trial_started_at: 11.days.ago.middle_of_day }
:create | 1 | { created_at: frozen_time - 2.days }
:create | 5 | { created_at: frozen_time - 6.days }
:create | 10 | { created_at: frozen_time - 11.days }
:verify | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days }
:verify | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days }
:verify | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days }
:trial | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days }
:trial | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days }
:trial | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days }
:team | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days, trial_started_at: frozen_time - 2.days }
:team | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days, trial_started_at: frozen_time - 6.days }
:team | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days, trial_started_at: frozen_time - 11.days }
end
with_them do
@ -64,7 +67,7 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
it { is_expected.not_to send_in_product_marketing_email }
context 'when the previous track actions have been completed' do
let(:current_action_completed_at) { 2.days.ago.middle_of_day }
let(:current_action_completed_at) { frozen_time - 2.days }
it { is_expected.to send_in_product_marketing_email(user.id, group.id, :verify, 0) }
end
@ -76,7 +79,7 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
it { is_expected.not_to send_in_product_marketing_email }
context 'when the previous track action was completed within the intervals range' do
let(:previous_action_completed_at) { 6.days.ago.middle_of_day }
let(:previous_action_completed_at) { frozen_time - 6.days }
it { is_expected.to send_in_product_marketing_email(user.id, group.id, :create, 1) }
end
@ -113,13 +116,13 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
end
context 'when the previous track action is completed outside the intervals range' do
let(:previous_action_completed_at) { 3.days.ago }
let(:previous_action_completed_at) { frozen_time - 3.days }
it { is_expected.not_to send_in_product_marketing_email }
end
context 'when the current track action is completed' do
let(:current_action_completed_at) { Time.current }
let(:current_action_completed_at) { frozen_time }
it { is_expected.not_to send_in_product_marketing_email }
end

View File

@ -6,7 +6,7 @@ RSpec.describe Snippets::ScheduleBulkRepositoryShardMovesService do
it_behaves_like 'moves repository shard in bulk' do
let_it_be_with_reload(:container) { create(:snippet, :repository) }
let(:move_service_klass) { SnippetRepositoryStorageMove }
let(:bulk_worker_klass) { ::SnippetScheduleBulkRepositoryShardMovesWorker }
let(:move_service_klass) { Snippets::RepositoryStorageMove }
let(:bulk_worker_klass) { ::Snippets::ScheduleBulkRepositoryShardMovesWorker }
end
end

View File

@ -114,7 +114,7 @@ module StubObjectStorage
end
def stub_object_storage_multipart_init(endpoint, upload_id = "upload_id")
stub_request(:post, %r{\A#{endpoint}tmp/uploads/[a-z0-9-]*\?uploads\z})
stub_request(:post, %r{\A#{endpoint}tmp/uploads/[%A-Za-z0-9-]*\?uploads\z})
.to_return status: 200, body: <<-EOS.strip_heredoc
<?xml version="1.0" encoding="UTF-8"?>
<InitiateMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">

View File

@ -53,9 +53,13 @@ RSpec.shared_examples "chat service" do |service_name|
end
it "calls #{service_name} API" do
subject.execute(sample_data)
result = subject.execute(sample_data)
expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once
expect(result).to be(true)
expect(WebMock).to have_requested(:post, webhook_url).once.with { |req|
json_body = Gitlab::Json.parse(req.body).with_indifferent_access
expect(json_body).to include(payload)
}
end
end
@ -67,7 +71,8 @@ RSpec.shared_examples "chat service" do |service_name|
it "does not call #{service_name} API" do
result = subject.execute(sample_data)
expect(result).to be_falsy
expect(result).to be(false)
expect(WebMock).not_to have_requested(:post, webhook_url)
end
end

View File

@ -6,7 +6,7 @@ RSpec.describe SnippetScheduleBulkRepositoryShardMovesWorker do
it_behaves_like 'schedules bulk repository shard moves' do
let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
let(:move_service_klass) { SnippetRepositoryStorageMove }
let(:worker_klass) { SnippetUpdateRepositoryStorageWorker }
let(:move_service_klass) { Snippets::RepositoryStorageMove }
let(:worker_klass) { Snippets::UpdateRepositoryStorageWorker }
end
end

View File

@ -10,6 +10,6 @@ RSpec.describe SnippetUpdateRepositoryStorageWorker do
let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) }
let(:service_klass) { Snippets::UpdateRepositoryStorageService }
let(:repository_storage_move_klass) { SnippetRepositoryStorageMove }
let(:repository_storage_move_klass) { Snippets::RepositoryStorageMove }
end
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Snippets::ScheduleBulkRepositoryShardMovesWorker do
it_behaves_like 'schedules bulk repository shard moves' do
let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
let(:move_service_klass) { Snippets::RepositoryStorageMove }
let(:worker_klass) { Snippets::UpdateRepositoryStorageWorker }
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Snippets::UpdateRepositoryStorageWorker do
subject { described_class.new }
it_behaves_like 'an update storage move worker' do
let_it_be_with_refind(:container) { create(:snippet, :repository) }
let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) }
let(:service_klass) { Snippets::UpdateRepositoryStorageService }
let(:repository_storage_move_klass) { Snippets::RepositoryStorageMove }
end
end