Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
bb5c4817e5
commit
3b9468e8b9
52 changed files with 553 additions and 133 deletions
|
@ -1289,7 +1289,7 @@
|
|||
rules:
|
||||
- if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/'
|
||||
when: never
|
||||
- <<: *if-default-branch-schedule-nightly
|
||||
- <<: *if-dot-com-ee-nightly-schedule
|
||||
allow_failure: true
|
||||
|
||||
.reports:rules:package_hunter-yarn:
|
||||
|
|
|
@ -826,5 +826,7 @@ Individual Cool Widget replication and verification data should now be available
|
|||
feature_flag: :geo_cool_widget_replication # REMOVE THIS LINE
|
||||
```
|
||||
|
||||
- [ ] Run `bundle exec rake gitlab:graphql:compile_docs` after the step above to regenerate the GraphQL docs.
|
||||
|
||||
- [ ] Add a row for Cool Widgets to the `Data types` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#data-types)
|
||||
- [ ] Add a row for Cool Widgets to the `Limitations on replication/verification` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#limitations-on-replicationverification). If the row already exists, then update it to show that Replication and Verification is released in the current version.
|
||||
|
|
|
@ -794,5 +794,7 @@ Individual Cool Widget replication and verification data should now be available
|
|||
feature_flag: :geo_cool_widget_replication # REMOVE THIS LINE
|
||||
```
|
||||
|
||||
- [ ] Run `bundle exec rake gitlab:graphql:compile_docs` after the step above to regenerate the GraphQL docs.
|
||||
|
||||
- [ ] Add a row for Cool Widgets to the `Data types` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#data-types)
|
||||
- [ ] Add a row for Cool Widgets to the `Limitations on replication/verification` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#limitations-on-replicationverification). If the row already exists, then update it to show that Replication and Verification is released in the current version.
|
||||
|
|
|
@ -1 +1 @@
|
|||
14.3.1
|
||||
14.3.2
|
||||
|
|
|
@ -315,7 +315,7 @@ export default {
|
|||
<span
|
||||
v-if="isJiraIssue"
|
||||
v-safe-html="jiraLogo"
|
||||
class="svg-container jira-logo-container"
|
||||
class="svg-container logo-container"
|
||||
data-testid="jira-logo"
|
||||
></span>
|
||||
{{ referencePath }}
|
||||
|
|
|
@ -18,7 +18,10 @@ class Admin::ApplicationsController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@application = Doorkeeper::Application.new
|
||||
# Default access tokens to expire. This preserves backward compatibility
|
||||
# with existing applications. This will be removed in 15.0.
|
||||
# Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848
|
||||
@application = Doorkeeper::Application.new(expire_access_tokens: true)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -55,10 +58,13 @@ class Admin::ApplicationsController < Admin::ApplicationController
|
|||
@application = ApplicationsFinder.new(id: params[:id]).execute
|
||||
end
|
||||
|
||||
# Only allow a trusted parameter "white list" through.
|
||||
def permitted_params
|
||||
super << :trusted
|
||||
end
|
||||
|
||||
def application_params
|
||||
params
|
||||
.require(:doorkeeper_application)
|
||||
.permit(:name, :redirect_uri, :trusted, :scopes, :confidential)
|
||||
super.tap do |params|
|
||||
params[:owner] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ class Admin::RunnerProjectsController < Admin::ApplicationController
|
|||
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
|
||||
|
||||
if @runner.assign_to(@project, current_user)
|
||||
redirect_to admin_runner_path(@runner)
|
||||
redirect_to admin_runner_path(@runner), notice: s_('Runners|Runner assigned to project.')
|
||||
else
|
||||
redirect_to admin_runner_path(@runner), alert: 'Failed adding runner to project'
|
||||
end
|
||||
|
@ -20,7 +20,7 @@ class Admin::RunnerProjectsController < Admin::ApplicationController
|
|||
runner = rp.runner
|
||||
rp.destroy
|
||||
|
||||
redirect_to admin_runner_path(runner), status: :found
|
||||
redirect_to admin_runner_path(runner), status: :found, notice: s_('Runners|Runner unassigned from project.')
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -18,4 +18,14 @@ module OauthApplications
|
|||
def load_scopes
|
||||
@scopes ||= Doorkeeper.configuration.scopes
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
%i{name redirect_uri scopes confidential expire_access_tokens}
|
||||
end
|
||||
|
||||
def application_params
|
||||
params
|
||||
.require(:doorkeeper_application)
|
||||
.permit(*permitted_params)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -54,8 +54,10 @@ module Groups
|
|||
# https://gitlab.com/gitlab-org/gitlab/-/issues/324187
|
||||
@applications = @group.oauth_applications.limit(100)
|
||||
|
||||
# Don't overwrite a value possibly set by `create`
|
||||
@application ||= Doorkeeper::Application.new
|
||||
# Default access tokens to expire. This preserves backward compatibility
|
||||
# with existing applications. This will be removed in 15.0.
|
||||
# Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848
|
||||
@application ||= Doorkeeper::Application.new(expire_access_tokens: true)
|
||||
end
|
||||
|
||||
def set_application
|
||||
|
@ -63,12 +65,9 @@ module Groups
|
|||
end
|
||||
|
||||
def application_params
|
||||
params
|
||||
.require(:doorkeeper_application)
|
||||
.permit(:name, :redirect_uri, :scopes, :confidential)
|
||||
.tap do |params|
|
||||
params[:owner] = @group
|
||||
end
|
||||
super.tap do |params|
|
||||
params[:owner] = @group
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,7 +25,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
|||
end
|
||||
|
||||
def create
|
||||
@application = Applications::CreateService.new(current_user, create_application_params).execute(request)
|
||||
@application = Applications::CreateService.new(current_user, application_params).execute(request)
|
||||
|
||||
if @application.persisted?
|
||||
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
|
||||
|
@ -51,8 +51,10 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
|||
@authorized_anonymous_tokens = @authorized_tokens.reject(&:application)
|
||||
@authorized_apps = @authorized_tokens.map(&:application).uniq.reject(&:nil?)
|
||||
|
||||
# Don't overwrite a value possibly set by `create`
|
||||
@application ||= Doorkeeper::Application.new
|
||||
# Default access tokens to expire. This preserves backward compatibility
|
||||
# with existing applications. This will be removed in 15.0.
|
||||
# Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848
|
||||
@application ||= Doorkeeper::Application.new(expire_access_tokens: true)
|
||||
end
|
||||
|
||||
# Override Doorkeeper to scope to the current user
|
||||
|
@ -64,8 +66,8 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
|||
render "errors/not_found", layout: "errors", status: :not_found
|
||||
end
|
||||
|
||||
def create_application_params
|
||||
application_params.tap do |params|
|
||||
def application_params
|
||||
super.tap do |params|
|
||||
params[:owner] = current_user
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
|
|||
path = project_runners_path(project)
|
||||
|
||||
if @runner.assign_to(project, current_user)
|
||||
redirect_to path
|
||||
redirect_to path, notice: s_('Runners|Runner assigned to project.')
|
||||
else
|
||||
assign_to_messages = @runner.errors.messages[:assign_to]
|
||||
alert = assign_to_messages&.join(',') || 'Failed adding runner to project'
|
||||
|
@ -28,6 +28,6 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
|
|||
runner_project = project.runner_projects.find(params[:id])
|
||||
runner_project.destroy
|
||||
|
||||
redirect_to project_runners_path(project), status: :found
|
||||
redirect_to project_runners_path(project), status: :found, notice: s_('Runners|Runner unassigned from project.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,7 @@ module Enums
|
|||
pipeline_loop_detected: 17,
|
||||
no_matching_runner: 18, # not used anymore, but cannot be deleted because of old data
|
||||
trace_size_exceeded: 19,
|
||||
builds_disabled: 20,
|
||||
insufficient_bridge_permissions: 1_001,
|
||||
downstream_bridge_project_not_found: 1_002,
|
||||
invalid_bridge_trigger: 1_003,
|
||||
|
|
|
@ -27,7 +27,8 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
|
|||
user_blocked: 'The user who created this job is blocked',
|
||||
ci_quota_exceeded: 'No more CI minutes available',
|
||||
no_matching_runner: 'No matching runner available',
|
||||
trace_size_exceeded: 'The job log size limit was reached'
|
||||
trace_size_exceeded: 'The job log size limit was reached',
|
||||
builds_disabled: 'The CI/CD is disabled for this project'
|
||||
}.freeze
|
||||
|
||||
private_constant :CALLOUT_FAILURE_MESSAGES
|
||||
|
|
|
@ -271,6 +271,15 @@ module Ci
|
|||
missing_dependency_failure: -> (build, _) { !build.has_valid_build_dependencies? },
|
||||
runner_unsupported: -> (build, params) { !build.supported_runner?(params.dig(:info, :features)) },
|
||||
archived_failure: -> (build, _) { build.archived? }
|
||||
}.merge(builds_enabled_checks)
|
||||
end
|
||||
|
||||
def builds_enabled_checks
|
||||
return {} unless ::Feature.enabled?(:ci_queueing_builds_enabled_checks, runner, default_enabled: :yaml)
|
||||
|
||||
{
|
||||
project_deleted: -> (build, _) { build.project.pending_delete? },
|
||||
builds_disabled: -> (build, _) { !build.project.builds_enabled? }
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,18 +12,19 @@ module Packages
|
|||
if @tag_name.present?
|
||||
@tag_name.delete_prefix('v')
|
||||
elsif @branch_name.present?
|
||||
branch_sufix_or_prefix(@branch_name.match(Gitlab::Regex.composer_package_version_regex))
|
||||
branch_suffix_or_prefix(@branch_name.match(Gitlab::Regex.composer_package_version_regex))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def branch_sufix_or_prefix(match)
|
||||
def branch_suffix_or_prefix(match)
|
||||
if match
|
||||
if match.captures[1] == '.x'
|
||||
match.captures[0] + '-dev'
|
||||
captures = match.captures.reject(&:blank?)
|
||||
if captures[-1] == '.x'
|
||||
captures[0] + '-dev'
|
||||
else
|
||||
match.captures[0] + '.x-dev'
|
||||
captures[0] + '.x-dev'
|
||||
end
|
||||
else
|
||||
"dev-#{@branch_name}"
|
||||
|
|
|
@ -33,6 +33,14 @@
|
|||
%span.form-text.text-muted
|
||||
= _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
|
||||
|
||||
= content_tag :div, class: 'form-group row' do
|
||||
.col-sm-2.col-form-label.pt-0
|
||||
= f.label :expire_access_tokens
|
||||
.col-sm-10
|
||||
= f.check_box :expire_access_tokens
|
||||
%span.form-text.text-muted
|
||||
= _('Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility.')
|
||||
|
||||
.form-group.row
|
||||
.col-sm-2.col-form-label.pt-0
|
||||
= f.label :scopes
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
%span.form-text.text-muted
|
||||
= _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
|
||||
|
||||
.form-group.form-check
|
||||
= f.check_box :expire_access_tokens, class: 'form-check-input'
|
||||
= f.label :expire_access_tokens, class: 'label-bold form-check-label'
|
||||
%span.form-text.text-muted
|
||||
= _('Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility.')
|
||||
|
||||
.form-group
|
||||
= f.label :scopes, class: 'label-bold'
|
||||
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: @application, scopes: @scopes
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: ci_queueing_builds_enabled_checks
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70581
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341131
|
||||
milestone: '14.4'
|
||||
type: development
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
|
@ -38,8 +38,11 @@ Doorkeeper.configure do
|
|||
# authorization_code_expires_in 10.minutes
|
||||
|
||||
# Access token expiration time (default 2 hours).
|
||||
# If you want to disable expiration, set this to nil.
|
||||
access_token_expires_in nil
|
||||
# Until 15.0, applications can opt-out of expiring tokens.
|
||||
# Removal issue: https://gitlab.com/gitlab-org/gitlab/-/issues/340848
|
||||
custom_access_token_expires_in do |context|
|
||||
context.client&.expire_access_tokens ? 2.hours : Float::INFINITY
|
||||
end
|
||||
|
||||
# Reuse access token for the same resource owner within an application (disabled by default)
|
||||
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
||||
|
|
23
config/metrics/counts_28d/20210916080405_promoted_issues.yml
Normal file
23
config/metrics/counts_28d/20210916080405_promoted_issues.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
key_path: counts_monthly.promoted_issues
|
||||
name: count_promoted_issues
|
||||
description: Count of issues promoted to epics
|
||||
product_section: growth
|
||||
product_stage: growth
|
||||
product_group: group::product intelligence
|
||||
product_category: collection
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "14.3"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70485
|
||||
time_frame: 28d
|
||||
data_source: database
|
||||
data_category: optional
|
||||
performance_indicator_type: []
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIterationCadenceIdToIssueBoards < Gitlab::Database::Migration[1.0]
|
||||
enable_lock_retries!
|
||||
|
||||
def change
|
||||
add_column :boards, :iteration_cadence_id, :bigint
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddExpireAccessTokensToDoorkeeperApplication < Gitlab::Database::Migration[1.0]
|
||||
def change
|
||||
add_column :oauth_applications, :expire_access_tokens, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddFkToIterationCadenceIdOnBoards < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_boards_on_iteration_cadence_id'
|
||||
|
||||
def up
|
||||
add_concurrent_index :boards, :iteration_cadence_id, name: INDEX_NAME
|
||||
add_concurrent_foreign_key :boards, :iterations_cadences, column: :iteration_cadence_id
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :boards, column: :iteration_cadence_id
|
||||
end
|
||||
remove_concurrent_index_by_name :boards, INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class BackfillCadenceIdForBoardsScopedToIteration < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
BATCH_SIZE = 1000
|
||||
DELAY = 2.minutes.to_i
|
||||
MIGRATION = 'BackfillIterationCadenceIdForBoards'
|
||||
|
||||
class MigrationBoard < ApplicationRecord
|
||||
include EachBatch
|
||||
|
||||
self.table_name = 'boards'
|
||||
end
|
||||
|
||||
def up
|
||||
schedule_backfill_group_boards
|
||||
schedule_backfill_project_boards
|
||||
end
|
||||
|
||||
def down
|
||||
MigrationBoard.where.not(iteration_cadence_id: nil).each_batch(of: BATCH_SIZE) do |batch, index|
|
||||
range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
|
||||
delay = index * DELAY
|
||||
|
||||
migrate_in(delay, MIGRATION, ['none', 'down', *range])
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def schedule_backfill_project_boards
|
||||
MigrationBoard.where(iteration_id: -4).where.not(project_id: nil).where(iteration_cadence_id: nil).each_batch(of: BATCH_SIZE) do |batch, index|
|
||||
range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
|
||||
delay = index * DELAY
|
||||
|
||||
migrate_in(delay, MIGRATION, ['project', 'up', *range])
|
||||
end
|
||||
end
|
||||
|
||||
def schedule_backfill_group_boards
|
||||
MigrationBoard.where(iteration_id: -4).where.not(group_id: nil).where(iteration_cadence_id: nil).each_batch(of: BATCH_SIZE) do |batch, index|
|
||||
range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
|
||||
delay = index * DELAY
|
||||
|
||||
migrate_in(delay, MIGRATION, ['group', 'up', *range])
|
||||
end
|
||||
end
|
||||
end
|
1
db/schema_migrations/20210825193448
Normal file
1
db/schema_migrations/20210825193448
Normal file
|
@ -0,0 +1 @@
|
|||
d9c7cc7721b28cbd442bf40255ecfbd20d0abf4cd31631c150ebdc05c76062be
|
1
db/schema_migrations/20210825193548
Normal file
1
db/schema_migrations/20210825193548
Normal file
|
@ -0,0 +1 @@
|
|||
b97b77aef61db2e51106ac090f5511a67fa85be8f3741f618fe03c8c03ecd88c
|
1
db/schema_migrations/20210825193652
Normal file
1
db/schema_migrations/20210825193652
Normal file
|
@ -0,0 +1 @@
|
|||
fd7aef11635bc4c5d6b9346dbed90f6c114da7b7a33744083e8610f3850e4736
|
1
db/schema_migrations/20210902184334
Normal file
1
db/schema_migrations/20210902184334
Normal file
|
@ -0,0 +1 @@
|
|||
508b8d4608d28b2a12cf429262c3dd336e130013a41e51ff6c95027ece1540e5
|
|
@ -10894,7 +10894,8 @@ CREATE TABLE boards (
|
|||
weight integer,
|
||||
hide_backlog_list boolean DEFAULT false NOT NULL,
|
||||
hide_closed_list boolean DEFAULT false NOT NULL,
|
||||
iteration_id bigint
|
||||
iteration_id bigint,
|
||||
iteration_cadence_id bigint
|
||||
);
|
||||
|
||||
CREATE TABLE boards_epic_board_labels (
|
||||
|
@ -16385,7 +16386,8 @@ CREATE TABLE oauth_applications (
|
|||
owner_id integer,
|
||||
owner_type character varying,
|
||||
trusted boolean DEFAULT false NOT NULL,
|
||||
confidential boolean DEFAULT true NOT NULL
|
||||
confidential boolean DEFAULT true NOT NULL,
|
||||
expire_access_tokens boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE oauth_applications_id_seq
|
||||
|
@ -24405,6 +24407,8 @@ CREATE INDEX index_boards_epic_user_preferences_on_user_id ON boards_epic_user_p
|
|||
|
||||
CREATE INDEX index_boards_on_group_id ON boards USING btree (group_id);
|
||||
|
||||
CREATE INDEX index_boards_on_iteration_cadence_id ON boards USING btree (iteration_cadence_id);
|
||||
|
||||
CREATE INDEX index_boards_on_iteration_id ON boards USING btree (iteration_id);
|
||||
|
||||
CREATE INDEX index_boards_on_milestone_id ON boards USING btree (milestone_id);
|
||||
|
@ -27911,6 +27915,9 @@ ALTER TABLE ONLY alert_management_alerts
|
|||
ALTER TABLE ONLY identities
|
||||
ADD CONSTRAINT fk_aade90f0fc FOREIGN KEY (saml_provider_id) REFERENCES saml_providers(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY boards
|
||||
ADD CONSTRAINT fk_ab0a250ff6 FOREIGN KEY (iteration_cadence_id) REFERENCES iterations_cadences(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY dep_ci_build_trace_sections
|
||||
ADD CONSTRAINT fk_ab7c104e26 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -1075,6 +1075,7 @@ Input type: `CreateBoardInput`
|
|||
| <a id="mutationcreateboardgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
|
||||
| <a id="mutationcreateboardhidebackloglist"></a>`hideBacklogList` | [`Boolean`](#boolean) | Whether or not backlog list is hidden. |
|
||||
| <a id="mutationcreateboardhideclosedlist"></a>`hideClosedList` | [`Boolean`](#boolean) | Whether or not closed list is hidden. |
|
||||
| <a id="mutationcreateboarditerationcadenceid"></a>`iterationCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | ID of iteration cadence to be assigned to the board. |
|
||||
| <a id="mutationcreateboarditerationid"></a>`iterationId` | [`IterationID`](#iterationid) | ID of iteration to be assigned to the board. |
|
||||
| <a id="mutationcreateboardlabelids"></a>`labelIds` | [`[LabelID!]`](#labelid) | IDs of labels to be added to the board. |
|
||||
| <a id="mutationcreateboardlabels"></a>`labels` | [`[String!]`](#string) | Labels of the issue. |
|
||||
|
@ -4122,6 +4123,7 @@ Input type: `UpdateBoardInput`
|
|||
| <a id="mutationupdateboardhidebackloglist"></a>`hideBacklogList` | [`Boolean`](#boolean) | Whether or not backlog list is hidden. |
|
||||
| <a id="mutationupdateboardhideclosedlist"></a>`hideClosedList` | [`Boolean`](#boolean) | Whether or not closed list is hidden. |
|
||||
| <a id="mutationupdateboardid"></a>`id` | [`BoardID!`](#boardid) | Board global ID. |
|
||||
| <a id="mutationupdateboarditerationcadenceid"></a>`iterationCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | ID of iteration cadence to be assigned to the board. |
|
||||
| <a id="mutationupdateboarditerationid"></a>`iterationId` | [`IterationID`](#iterationid) | ID of iteration to be assigned to the board. |
|
||||
| <a id="mutationupdateboardlabelids"></a>`labelIds` | [`[LabelID!]`](#labelid) | IDs of labels to be added to the board. |
|
||||
| <a id="mutationupdateboardlabels"></a>`labels` | [`[String!]`](#string) | Labels of the issue. |
|
||||
|
@ -7897,6 +7899,7 @@ Represents a project or group issue board.
|
|||
| <a id="boardhideclosedlist"></a>`hideClosedList` | [`Boolean`](#boolean) | Whether or not closed list is hidden. |
|
||||
| <a id="boardid"></a>`id` | [`ID!`](#id) | ID (global ID) of the board. |
|
||||
| <a id="boarditeration"></a>`iteration` | [`Iteration`](#iteration) | Board iteration. |
|
||||
| <a id="boarditerationcadence"></a>`iterationCadence` | [`IterationCadence`](#iterationcadence) | Board iteration cadence. |
|
||||
| <a id="boardlabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels of the board. (see [Connections](#connections)) |
|
||||
| <a id="boardmilestone"></a>`milestone` | [`Milestone`](#milestone) | Board milestone. |
|
||||
| <a id="boardname"></a>`name` | [`String`](#string) | Name of the board. |
|
||||
|
|
|
@ -223,7 +223,7 @@ the contribution acceptance criteria below:
|
|||
|
||||
## Definition of done
|
||||
|
||||
If you contribute to GitLab please know that changes involve more than just
|
||||
If you contribute to GitLab, please know that changes involve more than just
|
||||
code. We use the following [definition of done](https://www.agilealliance.org/glossary/definition-of-done).
|
||||
To reach the definition of done, the merge request must create no regressions and meet all these criteria:
|
||||
|
||||
|
@ -231,7 +231,7 @@ To reach the definition of done, the merge request must create no regressions an
|
|||
- Verified as working for self-managed instances.
|
||||
|
||||
If a regression occurs, we prefer you revert the change. We break the definition of done into two phases: [MR Merge](#mr-merge) and [Production use](#production-use).
|
||||
Your contribution is not *done* until you have made sure it meets all of these
|
||||
Your contribution is *incomplete* until you have made sure it meets all of these
|
||||
requirements.
|
||||
|
||||
### MR Merge
|
||||
|
@ -246,18 +246,24 @@ requirements.
|
|||
1. [Secure coding guidelines](https://gitlab.com/gitlab-com/gl-security/security-guidelines) have been followed.
|
||||
1. [Documented](../documentation/index.md) in the `/doc` directory.
|
||||
1. [Changelog entry added](../changelog.md), if necessary.
|
||||
1. Reviewed by relevant reviewers and all concerns are addressed for Availability, Regressions, Security. Documentation reviews should take place as soon as possible, but they should not block a merge request.
|
||||
1. Reviewed by relevant reviewers, and all concerns are addressed for Availability, Regressions, and Security. Documentation reviews should take place as soon as possible, but they should not block a merge request.
|
||||
1. The [MR acceptance checklist](../code_review.md#acceptance-checklist) has been checked as confirmed in the MR.
|
||||
1. Create an issue in the [infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues) to inform the Infrastructure department when your contribution is changing default settings or introduces a new setting, if relevant.
|
||||
1. [Black-box tests/end-to-end tests](../testing_guide/testing_levels.md#black-box-tests-at-the-system-level-aka-end-to-end-tests)
|
||||
added if required. Please contact [the quality team](https://about.gitlab.com/handbook/engineering/quality/#teams)
|
||||
with any questions.
|
||||
1. The change is tested in a review app where possible and if appropriate.
|
||||
1. The new feature does not degrade the user experience of the product.
|
||||
1. An agreed upon rollout plan.
|
||||
1. The change is evaluated to [limit the impact of far-reaching work](https://about.gitlab.com/handbook/engineering/development/#reducing-the-impact-of-far-reaching-work).
|
||||
1. An agreed-upon rollout plan.
|
||||
1. Merged by a project maintainer.
|
||||
|
||||
### Production use
|
||||
|
||||
1. Confirmed to be working in staging before implementing the change in production, where possible.
|
||||
1. Confirmed to be working in the production with no new [Sentry](https://about.gitlab.com/handbook/engineering/#sentry) errors after the contribution is deployed.
|
||||
1. Confirmed that the rollout plan has been completed.
|
||||
1. If there is a performance risk in the change, I have analyzed the performance of the system before and after the change.
|
||||
1. *If the merge request uses feature flags, per-project or per-group enablement, and a staged rollout:*
|
||||
- Confirmed to be working on GitLab projects.
|
||||
- Confirmed to be working at each stage for all projects added.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# rubocop: disable Style/Documentation
|
||||
class BackfillIterationCadenceIdForBoards
|
||||
def perform(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::BackgroundMigration::BackfillIterationCadenceIdForBoards.prepend_mod_with('Gitlab::BackgroundMigration::BackfillIterationCadenceIdForBoards')
|
|
@ -32,7 +32,8 @@ module Gitlab
|
|||
user_blocked: 'pipeline user was blocked',
|
||||
ci_quota_exceeded: 'no more CI minutes available',
|
||||
no_matching_runner: 'no matching runner available',
|
||||
trace_size_exceeded: 'log size limit exceeded'
|
||||
trace_size_exceeded: 'log size limit exceeded',
|
||||
builds_disabled: 'project builds are disabled'
|
||||
}.freeze
|
||||
|
||||
private_constant :REASONS
|
||||
|
|
|
@ -70,7 +70,9 @@ module Gitlab
|
|||
# If the lock was not acquired within the retry period, a last attempt is made without using +lock_timeout+.
|
||||
#
|
||||
# In order to retry the block, the method wraps the block into a transaction.
|
||||
# Note it cannot be used inside an already open transaction and will raise an error in that case.
|
||||
#
|
||||
# When called inside an open transaction it will execute the block directly if lock retries are enabled
|
||||
# with `enable_lock_retries!` at migration level, otherwise it will raise an error.
|
||||
#
|
||||
# ==== Examples
|
||||
# # Invoking without parameters
|
||||
|
@ -101,14 +103,19 @@ module Gitlab
|
|||
# * +env+ - [Hash] custom environment hash, see the example with `DISABLE_LOCK_RETRIES`
|
||||
def with_lock_retries(*args, **kwargs, &block)
|
||||
if transaction_open?
|
||||
raise <<~EOF
|
||||
if enable_lock_retries?
|
||||
Gitlab::AppLogger.warn 'Lock retries already enabled, executing the block directly'
|
||||
yield
|
||||
else
|
||||
raise <<~EOF
|
||||
#{__callee__} can not be run inside an already open transaction
|
||||
|
||||
Use migration-level lock retries instead, see https://docs.gitlab.com/ee/development/migration_style_guide.html#retry-mechanism-when-acquiring-database-locks
|
||||
EOF
|
||||
EOF
|
||||
end
|
||||
else
|
||||
super(*args, **kwargs.merge(allow_savepoints: false), &block)
|
||||
end
|
||||
|
||||
super(*args, **kwargs.merge(allow_savepoints: false), &block)
|
||||
end
|
||||
|
||||
# Renames a column without requiring downtime.
|
||||
|
|
|
@ -400,6 +400,7 @@ excluded_attributes:
|
|||
boards:
|
||||
- :milestone_id
|
||||
- :iteration_id
|
||||
- :iteration_cadence_id
|
||||
lists:
|
||||
- :board_id
|
||||
- :label_id
|
||||
|
|
|
@ -82,9 +82,21 @@ module Gitlab
|
|||
end
|
||||
|
||||
def self.configure_throttles(rack_attack)
|
||||
throttle_or_track(rack_attack, 'throttle_unauthenticated_api', Gitlab::Throttle.unauthenticated_api_options) do |req|
|
||||
if req.throttle_unauthenticated_api?
|
||||
req.ip
|
||||
# Each of these settings follows the same pattern of specifying separate
|
||||
# authenticated and unauthenticated rates via settings
|
||||
Gitlab::Throttle::REGULAR_THROTTLES.each do |throttle|
|
||||
unauthenticated_options = Gitlab::Throttle.options(throttle, authenticated: false)
|
||||
throttle_or_track(rack_attack, "throttle_unauthenticated_#{throttle}", unauthenticated_options) do |req|
|
||||
if req.throttle?(throttle, authenticated: false)
|
||||
req.ip
|
||||
end
|
||||
end
|
||||
|
||||
authenticated_options = Gitlab::Throttle.options(throttle, authenticated: true)
|
||||
throttle_or_track(rack_attack, "throttle_authenticated_#{throttle}", authenticated_options) do |req|
|
||||
if req.throttle?(throttle, authenticated: true)
|
||||
req.throttled_user_id([:api])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -94,12 +106,6 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
throttle_or_track(rack_attack, 'throttle_authenticated_api', Gitlab::Throttle.authenticated_api_options) do |req|
|
||||
if req.throttle_authenticated_api?
|
||||
req.throttled_user_id([:api])
|
||||
end
|
||||
end
|
||||
|
||||
# Product analytics feature is in experimental stage.
|
||||
# At this point we want to limit amount of events registered
|
||||
# per application (aid stands for application id).
|
||||
|
@ -133,36 +139,12 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
throttle_or_track(rack_attack, 'throttle_unauthenticated_packages_api', Gitlab::Throttle.unauthenticated_packages_api_options) do |req|
|
||||
if req.throttle_unauthenticated_packages_api?
|
||||
req.ip
|
||||
end
|
||||
end
|
||||
|
||||
throttle_or_track(rack_attack, 'throttle_authenticated_packages_api', Gitlab::Throttle.authenticated_packages_api_options) do |req|
|
||||
if req.throttle_authenticated_packages_api?
|
||||
req.throttled_user_id([:api])
|
||||
end
|
||||
end
|
||||
|
||||
throttle_or_track(rack_attack, 'throttle_authenticated_git_lfs', Gitlab::Throttle.throttle_authenticated_git_lfs_options) do |req|
|
||||
if req.throttle_authenticated_git_lfs?
|
||||
req.throttled_user_id([:api])
|
||||
end
|
||||
end
|
||||
|
||||
throttle_or_track(rack_attack, 'throttle_unauthenticated_files_api', Gitlab::Throttle.unauthenticated_files_api_options) do |req|
|
||||
if req.throttle_unauthenticated_files_api?
|
||||
req.ip
|
||||
end
|
||||
end
|
||||
|
||||
throttle_or_track(rack_attack, 'throttle_authenticated_files_api', Gitlab::Throttle.authenticated_files_api_options) do |req|
|
||||
if req.throttle_authenticated_files_api?
|
||||
req.throttled_user_id([:api])
|
||||
end
|
||||
end
|
||||
|
||||
rack_attack.safelist('throttle_bypass_header') do |req|
|
||||
Gitlab::Throttle.bypass_header.present? &&
|
||||
req.get_header(Gitlab::Throttle.bypass_header) == '1'
|
||||
|
|
|
@ -60,6 +60,12 @@ module Gitlab
|
|||
path =~ protected_paths_regex
|
||||
end
|
||||
|
||||
def throttle?(throttle, authenticated:)
|
||||
fragment = Gitlab::Throttle.throttle_fragment!(throttle, authenticated: authenticated)
|
||||
|
||||
__send__("#{fragment}?") # rubocop:disable GitlabSecurity/PublicSend
|
||||
end
|
||||
|
||||
def throttle_unauthenticated_api?
|
||||
api_request? &&
|
||||
!should_be_skipped? &&
|
||||
|
|
|
@ -21,7 +21,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def composer_package_version_regex
|
||||
@composer_package_version_regex ||= %r{^v?(\d+(\.(\d+|x))*(-.+)?)}.freeze
|
||||
# see https://github.com/composer/semver/blob/31f3ea725711245195f62e54ffa402d8ef2fdba9/src/VersionParser.php#L215
|
||||
@composer_package_version_regex ||= %r{\Av?((\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?)?\z}.freeze
|
||||
end
|
||||
|
||||
def composer_dev_version_regex
|
||||
|
|
|
@ -4,6 +4,11 @@ module Gitlab
|
|||
class Throttle
|
||||
DEFAULT_RATE_LIMITING_RESPONSE_TEXT = 'Retry later'
|
||||
|
||||
# Each of these settings follows the same pattern of specifying separate
|
||||
# authenticated and unauthenticated rates via settings. New throttles should
|
||||
# ideally be regular as well.
|
||||
REGULAR_THROTTLES = [:api, :packages_api, :files_api].freeze
|
||||
|
||||
def self.settings
|
||||
Gitlab::CurrentSettings.current_application_settings
|
||||
end
|
||||
|
@ -24,28 +29,38 @@ module Gitlab
|
|||
"HTTP_#{env_value.upcase.tr('-', '_')}"
|
||||
end
|
||||
|
||||
def self.unauthenticated_api_options
|
||||
limit_proc = proc { |req| settings.throttle_unauthenticated_api_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_unauthenticated_api_period_in_seconds.seconds }
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
class << self
|
||||
def options(throttle, authenticated:)
|
||||
fragment = throttle_fragment!(throttle, authenticated: authenticated)
|
||||
|
||||
# rubocop:disable GitlabSecurity/PublicSend
|
||||
limit_proc = proc { |req| settings.public_send("#{fragment}_requests_per_period") }
|
||||
period_proc = proc { |req| settings.public_send("#{fragment}_period_in_seconds").seconds }
|
||||
# rubocop:enable GitlabSecurity/PublicSend
|
||||
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def throttle_fragment!(throttle, authenticated:)
|
||||
raise("Unknown throttle: #{throttle}") unless REGULAR_THROTTLES.include?(throttle)
|
||||
|
||||
"throttle_#{'un' unless authenticated}authenticated_#{throttle}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.unauthenticated_web_options
|
||||
# TODO: Columns will be renamed in https://gitlab.com/gitlab-org/gitlab/-/issues/340031
|
||||
# Once this is done, web can be made into a regular throttle
|
||||
limit_proc = proc { |req| settings.throttle_unauthenticated_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_unauthenticated_period_in_seconds.seconds }
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.authenticated_api_options
|
||||
limit_proc = proc { |req| settings.throttle_authenticated_api_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_authenticated_api_period_in_seconds.seconds }
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.authenticated_web_options
|
||||
limit_proc = proc { |req| settings.throttle_authenticated_web_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_authenticated_web_period_in_seconds.seconds }
|
||||
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
|
@ -56,20 +71,6 @@ module Gitlab
|
|||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.unauthenticated_packages_api_options
|
||||
limit_proc = proc { |req| settings.throttle_unauthenticated_packages_api_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_unauthenticated_packages_api_period_in_seconds.seconds }
|
||||
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.authenticated_packages_api_options
|
||||
limit_proc = proc { |req| settings.throttle_authenticated_packages_api_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_authenticated_packages_api_period_in_seconds.seconds }
|
||||
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.throttle_authenticated_git_lfs_options
|
||||
limit_proc = proc { |req| settings.throttle_authenticated_git_lfs_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_authenticated_git_lfs_period_in_seconds.seconds }
|
||||
|
@ -77,20 +78,6 @@ module Gitlab
|
|||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.unauthenticated_files_api_options
|
||||
limit_proc = proc { |req| settings.throttle_unauthenticated_files_api_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_unauthenticated_files_api_period_in_seconds.seconds }
|
||||
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.authenticated_files_api_options
|
||||
limit_proc = proc { |req| settings.throttle_authenticated_files_api_requests_per_period }
|
||||
period_proc = proc { |req| settings.throttle_authenticated_files_api_period_in_seconds.seconds }
|
||||
|
||||
{ limit: limit_proc, period: period_proc }
|
||||
end
|
||||
|
||||
def self.rate_limiting_response_text
|
||||
(settings.rate_limiting_response_text.presence || DEFAULT_RATE_LIMITING_RESPONSE_TEXT) + "\n"
|
||||
end
|
||||
|
|
|
@ -1741,6 +1741,9 @@ msgstr ""
|
|||
msgid "Access to '%{classification_label}' not allowed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility."
|
||||
msgstr ""
|
||||
|
||||
msgid "AccessDropdown|Deploy Keys"
|
||||
msgstr ""
|
||||
|
||||
|
@ -29142,6 +29145,9 @@ msgstr ""
|
|||
msgid "Runners|Runner #%{runner_id}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner assigned to project."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner is offline, last contact was %{runner_contact} ago"
|
||||
msgstr ""
|
||||
|
||||
|
@ -29154,6 +29160,9 @@ msgstr ""
|
|||
msgid "Runners|Runner registration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner unassigned from project."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runners"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ module QA
|
|||
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
|
||||
merge_request.project = project
|
||||
merge_request.title = merge_request_title
|
||||
merge_request.assignee = 'me'
|
||||
merge_request.description = merge_request_description
|
||||
end
|
||||
|
||||
|
|
|
@ -356,6 +356,7 @@ RSpec.describe "Admin Runners" do
|
|||
|
||||
assigned_project = page.find('[data-testid="assigned-projects"]')
|
||||
|
||||
expect(page).to have_content('Runner assigned to project.')
|
||||
expect(assigned_project).to have_content(@project2.path)
|
||||
end
|
||||
end
|
||||
|
@ -399,13 +400,14 @@ RSpec.describe "Admin Runners" do
|
|||
visit admin_runner_path(runner)
|
||||
end
|
||||
|
||||
it 'enables specific runner for project' do
|
||||
it 'removed specific runner from project' do
|
||||
within '[data-testid="assigned-projects"]' do
|
||||
click_on 'Disable'
|
||||
end
|
||||
|
||||
new_runner_project = page.find('[data-testid="unassigned-projects"]')
|
||||
|
||||
expect(page).to have_content('Runner unassigned from project.')
|
||||
expect(new_runner_project).to have_content(@project1.path)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -293,5 +293,33 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
|
|||
|
||||
model.with_lock_retries(env: env, logger: in_memory_logger) { }
|
||||
end
|
||||
|
||||
context 'when in transaction' do
|
||||
before do
|
||||
allow(model).to receive(:transaction_open?).and_return(true)
|
||||
end
|
||||
|
||||
context 'when lock retries are enabled' do
|
||||
before do
|
||||
allow(model).to receive(:enable_lock_retries?).and_return(true)
|
||||
end
|
||||
|
||||
it 'does not use Gitlab::Database::WithLockRetries and executes the provided block directly' do
|
||||
expect(Gitlab::Database::WithLockRetries).not_to receive(:new)
|
||||
|
||||
expect(model.with_lock_retries(env: env, logger: in_memory_logger) { :block_result }).to eq(:block_result)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when lock retries are not enabled' do
|
||||
before do
|
||||
allow(model).to receive(:enable_lock_retries?).and_return(false)
|
||||
end
|
||||
|
||||
it 'raises an error' do
|
||||
expect { model.with_lock_retries(env: env, logger: in_memory_logger) { } }.to raise_error /can not be run inside an already open transaction/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -683,6 +683,7 @@ boards:
|
|||
- destroyable_lists
|
||||
- milestone
|
||||
- iteration
|
||||
- iteration_cadence
|
||||
- board_labels
|
||||
- board_assignee
|
||||
- assignee
|
||||
|
|
|
@ -762,6 +762,7 @@ Board:
|
|||
- group_id
|
||||
- milestone_id
|
||||
- iteration_id
|
||||
- iteration_cadence_id
|
||||
- weight
|
||||
- name
|
||||
- hide_backlog_list
|
||||
|
|
|
@ -10,19 +10,19 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
|
|||
|
||||
let(:throttles) do
|
||||
{
|
||||
throttle_unauthenticated_api: Gitlab::Throttle.unauthenticated_api_options,
|
||||
throttle_unauthenticated_api: Gitlab::Throttle.options(:api, authenticated: false),
|
||||
throttle_authenticated_api: Gitlab::Throttle.options(:api, authenticated: true),
|
||||
throttle_unauthenticated_web: Gitlab::Throttle.unauthenticated_web_options,
|
||||
throttle_authenticated_api: Gitlab::Throttle.authenticated_api_options,
|
||||
throttle_product_analytics_collector: { limit: 100, period: 60 },
|
||||
throttle_authenticated_web: Gitlab::Throttle.authenticated_web_options,
|
||||
throttle_product_analytics_collector: { limit: 100, period: 60 },
|
||||
throttle_unauthenticated_protected_paths: Gitlab::Throttle.protected_paths_options,
|
||||
throttle_authenticated_protected_paths_api: Gitlab::Throttle.protected_paths_options,
|
||||
throttle_authenticated_protected_paths_web: Gitlab::Throttle.protected_paths_options,
|
||||
throttle_unauthenticated_packages_api: Gitlab::Throttle.unauthenticated_packages_api_options,
|
||||
throttle_authenticated_packages_api: Gitlab::Throttle.authenticated_packages_api_options,
|
||||
throttle_unauthenticated_packages_api: Gitlab::Throttle.options(:packages_api, authenticated: false),
|
||||
throttle_authenticated_packages_api: Gitlab::Throttle.options(:packages_api, authenticated: true),
|
||||
throttle_authenticated_git_lfs: Gitlab::Throttle.throttle_authenticated_git_lfs_options,
|
||||
throttle_unauthenticated_files_api: Gitlab::Throttle.unauthenticated_files_api_options,
|
||||
throttle_authenticated_files_api: Gitlab::Throttle.authenticated_files_api_options
|
||||
throttle_unauthenticated_files_api: Gitlab::Throttle.options(:files_api, authenticated: false),
|
||||
throttle_authenticated_files_api: Gitlab::Throttle.options(:files_api, authenticated: true)
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -924,4 +924,25 @@ RSpec.describe Gitlab::Regex do
|
|||
it { is_expected.not_to match('/api/v4/groups/1234/packages/debian/dists/stable/Release.gpg') }
|
||||
it { is_expected.not_to match('/api/v4/groups/1234/packages/debian/pool/compon/a/pkg/file.name') }
|
||||
end
|
||||
|
||||
describe '.composer_package_version_regex' do
|
||||
subject { described_class.composer_package_version_regex }
|
||||
|
||||
it { is_expected.to match('v1.2.3') }
|
||||
it { is_expected.to match('v1.2.x') }
|
||||
it { is_expected.to match('v1.2.X') }
|
||||
it { is_expected.to match('1.2.3') }
|
||||
it { is_expected.to match('1') }
|
||||
it { is_expected.to match('v1') }
|
||||
it { is_expected.to match('1.2') }
|
||||
it { is_expected.to match('v1.2') }
|
||||
it { is_expected.not_to match('1.2.3-beta') }
|
||||
it { is_expected.not_to match('1.2.x-beta') }
|
||||
it { is_expected.not_to match('1.2.X-beta') }
|
||||
it { is_expected.not_to match('1.2.3-alpha.3') }
|
||||
it { is_expected.not_to match('1./2.3') }
|
||||
it { is_expected.not_to match('v1./2.3') }
|
||||
it { is_expected.not_to match('../../../../../1.2.3') }
|
||||
it { is_expected.not_to match('%2e%2e%2f1.2.3') }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
# require Rails.root.join('db', 'post_migrate', '20210825193652_backfill_candence_id_for_boards_scoped_to_iteration.rb')
|
||||
|
||||
RSpec.describe BackfillCadenceIdForBoardsScopedToIteration, :migration do
|
||||
let(:projects) { table(:projects) }
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:iterations_cadences) { table(:iterations_cadences) }
|
||||
let(:boards) { table(:boards) }
|
||||
|
||||
let!(:group) { namespaces.create!(name: 'group1', path: 'group1', type: 'Group') }
|
||||
let!(:cadence) { iterations_cadences.create!(title: 'group cadence', group_id: group.id, start_date: Time.current) }
|
||||
let!(:project) { projects.create!(name: 'gitlab1', path: 'gitlab1', namespace_id: group.id, visibility_level: 0) }
|
||||
let!(:project_board1) { boards.create!(name: 'Project Dev1', project_id: project.id) }
|
||||
let!(:project_board2) { boards.create!(name: 'Project Dev2', project_id: project.id, iteration_id: -4) }
|
||||
let!(:project_board3) { boards.create!(name: 'Project Dev3', project_id: project.id, iteration_id: -4) }
|
||||
let!(:project_board4) { boards.create!(name: 'Project Dev4', project_id: project.id, iteration_id: -4) }
|
||||
|
||||
let!(:group_board1) { boards.create!(name: 'Group Dev1', group_id: group.id) }
|
||||
let!(:group_board2) { boards.create!(name: 'Group Dev2', group_id: group.id, iteration_id: -4) }
|
||||
let!(:group_board3) { boards.create!(name: 'Group Dev3', group_id: group.id, iteration_id: -4) }
|
||||
let!(:group_board4) { boards.create!(name: 'Group Dev4', group_id: group.id, iteration_id: -4) }
|
||||
|
||||
describe '#up' do
|
||||
it 'schedules background migrations' do
|
||||
Sidekiq::Testing.fake! do
|
||||
freeze_time do
|
||||
described_class.new.up
|
||||
|
||||
migration = described_class::MIGRATION
|
||||
|
||||
expect(migration).to be_scheduled_delayed_migration(2.minutes, 'group', 'up', group_board2.id, group_board4.id)
|
||||
expect(migration).to be_scheduled_delayed_migration(2.minutes, 'project', 'up', project_board2.id, project_board4.id)
|
||||
expect(BackgroundMigrationWorker.jobs.size).to eq 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in batches' do
|
||||
before do
|
||||
stub_const('BackfillCadenceIdForBoardsScopedToIteration::BATCH_SIZE', 2)
|
||||
end
|
||||
|
||||
it 'schedules background migrations' do
|
||||
Sidekiq::Testing.fake! do
|
||||
freeze_time do
|
||||
described_class.new.up
|
||||
|
||||
migration = described_class::MIGRATION
|
||||
|
||||
expect(migration).to be_scheduled_delayed_migration(2.minutes, 'group', 'up', group_board2.id, group_board3.id)
|
||||
expect(migration).to be_scheduled_delayed_migration(4.minutes, 'group', 'up', group_board4.id, group_board4.id)
|
||||
expect(migration).to be_scheduled_delayed_migration(2.minutes, 'project', 'up', project_board2.id, project_board3.id)
|
||||
expect(migration).to be_scheduled_delayed_migration(4.minutes, 'project', 'up', project_board4.id, project_board4.id)
|
||||
expect(BackgroundMigrationWorker.jobs.size).to eq 4
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#down' do
|
||||
let!(:project_board1) { boards.create!(name: 'Project Dev1', project_id: project.id) }
|
||||
let!(:project_board2) { boards.create!(name: 'Project Dev2', project_id: project.id, iteration_cadence_id: cadence.id) }
|
||||
let!(:project_board3) { boards.create!(name: 'Project Dev3', project_id: project.id, iteration_id: -4, iteration_cadence_id: cadence.id) }
|
||||
let!(:project_board4) { boards.create!(name: 'Project Dev4', project_id: project.id, iteration_id: -4, iteration_cadence_id: cadence.id) }
|
||||
|
||||
let!(:group_board1) { boards.create!(name: 'Group Dev1', group_id: group.id) }
|
||||
let!(:group_board2) { boards.create!(name: 'Group Dev2', group_id: group.id, iteration_cadence_id: cadence.id) }
|
||||
let!(:group_board3) { boards.create!(name: 'Group Dev3', group_id: group.id, iteration_id: -4, iteration_cadence_id: cadence.id) }
|
||||
let!(:group_board4) { boards.create!(name: 'Group Dev4', group_id: group.id, iteration_id: -4, iteration_cadence_id: cadence.id) }
|
||||
|
||||
it 'schedules background migrations' do
|
||||
Sidekiq::Testing.fake! do
|
||||
freeze_time do
|
||||
described_class.new.down
|
||||
|
||||
migration = described_class::MIGRATION
|
||||
|
||||
expect(migration).to be_scheduled_delayed_migration(2.minutes, 'none', 'down', project_board2.id, group_board4.id)
|
||||
expect(BackgroundMigrationWorker.jobs.size).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in batches' do
|
||||
before do
|
||||
stub_const('BackfillCadenceIdForBoardsScopedToIteration::BATCH_SIZE', 2)
|
||||
end
|
||||
|
||||
it 'schedules background migrations' do
|
||||
Sidekiq::Testing.fake! do
|
||||
freeze_time do
|
||||
described_class.new.down
|
||||
|
||||
migration = described_class::MIGRATION
|
||||
|
||||
expect(migration).to be_scheduled_delayed_migration(2.minutes, 'none', 'down', project_board2.id, project_board3.id)
|
||||
expect(migration).to be_scheduled_delayed_migration(4.minutes, 'none', 'down', project_board4.id, group_board2.id)
|
||||
expect(migration).to be_scheduled_delayed_migration(6.minutes, 'none', 'down', group_board3.id, group_board4.id)
|
||||
expect(BackgroundMigrationWorker.jobs.size).to eq 3
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -55,5 +55,29 @@ RSpec.describe 'OAuth Tokens requests' do
|
|||
|
||||
expect(json_response['access_token']).not_to be_nil
|
||||
end
|
||||
|
||||
context 'when the application is configured to use expiring tokens' do
|
||||
before do
|
||||
application.update!(expire_access_tokens: true)
|
||||
end
|
||||
|
||||
it 'generates an access token with an expiration' do
|
||||
request_access_token(user)
|
||||
|
||||
expect(json_response['expires_in']).not_to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the application is configured not to use expiring tokens' do
|
||||
before do
|
||||
application.update!(expire_access_tokens: false)
|
||||
end
|
||||
|
||||
it 'generates an access token without an expiration' do
|
||||
request_access_token(user)
|
||||
|
||||
expect(json_response.key?('expires_in')).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -87,12 +87,30 @@ module Ci
|
|||
end
|
||||
|
||||
context 'for specific runner' do
|
||||
before do
|
||||
stub_feature_flags(ci_pending_builds_project_runners_decoupling: false)
|
||||
context 'with FF disabled' do
|
||||
before do
|
||||
stub_feature_flags(
|
||||
ci_pending_builds_project_runners_decoupling: false,
|
||||
ci_queueing_builds_enabled_checks: false)
|
||||
end
|
||||
|
||||
it 'does not pick a build' do
|
||||
expect(execute(specific_runner)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not pick a build' do
|
||||
expect(execute(specific_runner)).to be_nil
|
||||
context 'with FF enabled' do
|
||||
before do
|
||||
stub_feature_flags(
|
||||
ci_pending_builds_project_runners_decoupling: true,
|
||||
ci_queueing_builds_enabled_checks: true)
|
||||
end
|
||||
|
||||
it 'does not pick a build' do
|
||||
expect(execute(specific_runner)).to be_nil
|
||||
expect(pending_job.reload).to be_failed
|
||||
expect(pending_job.queuing_entry).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -246,13 +264,31 @@ module Ci
|
|||
end
|
||||
|
||||
context 'and uses project runner' do
|
||||
before do
|
||||
stub_feature_flags(ci_pending_builds_project_runners_decoupling: false)
|
||||
end
|
||||
|
||||
let(:build) { execute(specific_runner) }
|
||||
|
||||
it { expect(build).to be_nil }
|
||||
context 'with FF disabled' do
|
||||
before do
|
||||
stub_feature_flags(
|
||||
ci_pending_builds_project_runners_decoupling: false,
|
||||
ci_queueing_builds_enabled_checks: false)
|
||||
end
|
||||
|
||||
it { expect(build).to be_nil }
|
||||
end
|
||||
|
||||
context 'with FF enabled' do
|
||||
before do
|
||||
stub_feature_flags(
|
||||
ci_pending_builds_project_runners_decoupling: true,
|
||||
ci_queueing_builds_enabled_checks: true)
|
||||
end
|
||||
|
||||
it 'does not pick a build' do
|
||||
expect(build).to be_nil
|
||||
expect(pending_job.reload).to be_failed
|
||||
expect(pending_job.queuing_entry).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ RSpec.describe Packages::Composer::VersionParserService do
|
|||
where(:tagname, :branchname, :expected_version) do
|
||||
nil | 'master' | 'dev-master'
|
||||
nil | 'my-feature' | 'dev-my-feature'
|
||||
nil | '12-feature' | 'dev-12-feature'
|
||||
nil | 'v1' | '1.x-dev'
|
||||
nil | 'v1.x' | '1.x-dev'
|
||||
nil | 'v1.7.x' | '1.7.x-dev'
|
||||
|
|
|
@ -9,9 +9,11 @@ RSpec.shared_examples 'manage applications' do
|
|||
visit new_application_path
|
||||
|
||||
expect(page).to have_content 'Add new application'
|
||||
expect(find('#doorkeeper_application_expire_access_tokens')).to be_checked
|
||||
|
||||
fill_in :doorkeeper_application_name, with: application_name
|
||||
fill_in :doorkeeper_application_redirect_uri, with: application_redirect_uri
|
||||
uncheck :doorkeeper_application_expire_access_tokens
|
||||
check :doorkeeper_application_scopes_read_user
|
||||
click_on 'Save application'
|
||||
|
||||
|
@ -22,6 +24,8 @@ RSpec.shared_examples 'manage applications' do
|
|||
|
||||
click_on 'Edit'
|
||||
|
||||
expect(find('#doorkeeper_application_expire_access_tokens')).not_to be_checked
|
||||
|
||||
application_name_changed = "#{application_name} changed"
|
||||
|
||||
fill_in :doorkeeper_application_name, with: application_name_changed
|
||||
|
|
Loading…
Reference in a new issue