Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-26 09:08:59 +00:00
parent f88f72df02
commit 52fd2a9921
40 changed files with 146 additions and 505 deletions

View File

@ -23,9 +23,6 @@ import ForkSuggestion from './fork_suggestion.vue';
import { loadViewer } from './blob_viewers';
export default {
i18n: {
pipelineEditor: __('Pipeline Editor'),
},
components: {
BlobHeader,
BlobButtonGroup,

View File

@ -14,6 +14,7 @@ import CiIcon from '~/vue_shared/components/ci_icon.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
@ -27,6 +28,7 @@ export default {
GlButtonGroup,
GlLink,
GlLoadingIcon,
UserAvatarImage,
},
directives: {
GlTooltip: GlTooltipDirective,
@ -111,24 +113,24 @@ export default {
</script>
<template>
<div class="well-segment commit gl-p-5 gl-w-full">
<div class="well-segment commit gl-p-5 gl-w-full gl-display-flex">
<gl-loading-icon v-if="isLoading" size="md" color="dark" class="m-auto" />
<template v-else-if="commit">
<user-avatar-link
v-if="commit.author"
:link-href="commit.author.webPath"
:img-src="commit.author.avatarUrl"
:img-size="40"
class="avatar-cell"
:img-size="32"
:img-css-classes="'gl-mr-0!' /* NOTE: this is needed only while we migrate user-avatar-image to GlAvatar (7731 epics) */"
class="gl-my-2 gl-mr-4"
/>
<user-avatar-image
v-else
class="gl-my-2 gl-mr-4"
:img-src="commit.authorGravatar || $options.defaultAvatarUrl"
:css-classes="'gl-mr-0!' /* NOTE: this is needed only while we migrate user-avatar-image to GlAvatar (7731 epics) */"
:size="32"
/>
<span v-else class="avatar-cell user-avatar-link">
<img
:src="commit.authorGravatar || $options.defaultAvatarUrl"
width="40"
height="40"
class="avatar s40"
/>
</span>
<div class="commit-detail flex-list">
<div class="commit-content qa-commit-content">
<gl-link
@ -168,7 +170,10 @@ export default {
class="commit-row-description gl-mb-3"
></pre>
</div>
<div class="commit-actions flex-row">
<div class="gl-flex-grow-1"></div>
<div
class="commit-actions gl-display-flex gl-flex-align gl-align-items-center gl-flex-direction-row"
>
<div
v-if="commit.signatureHtml"
v-html="commit.signatureHtml /* eslint-disable-line vue/no-v-html */"

View File

@ -84,6 +84,7 @@ export default {
</runner-detail>
<runner-detail :label="s__('Runners|Version')" :value="runner.version" />
<runner-detail :label="s__('Runners|IP Address')" :value="runner.ipAddress" />
<runner-detail :label="s__('Runners|Executor')" :value="runner.executorName" />
<runner-detail :label="s__('Runners|Configuration')">
<template #value>
<gl-intersperse v-if="configTextProtected || configTextUntagged">

View File

@ -7,6 +7,7 @@ fragment RunnerDetailsShared on CiRunner {
runUntagged
locked
ipAddress
executorName
description
maximumTimeout
jobCount

View File

@ -20,6 +20,14 @@ table {
@include gl-text-gray-500;
}
&.table {
.thead-white {
th {
background-color: $white;
}
}
}
.md &:not(.code),
&.table:not(.gl-table) {
margin-bottom: $gl-padding;
@ -61,7 +69,6 @@ table {
.thead-white {
th {
background-color: $white;
color: $gl-text-color-secondary;
border-top: 0;
}

View File

@ -7,7 +7,7 @@ module Groups
before_action :authorize_admin_dependency_proxy!, only: :update
before_action :verify_dependency_proxy_enabled!
feature_category :package_registry
feature_category :dependency_proxy
private

View File

@ -8,7 +8,7 @@ module Groups
before_action :verify_container_registry_enabled!
before_action :authorize_read_container_image!
feature_category :package_registry
feature_category :container_registry
def index
respond_to do |format|

View File

@ -289,7 +289,7 @@ module Ci
def assign_to(project, current_user = nil)
if instance_type?
self.runner_type = :project_type
raise ArgumentError, 'Transitioning an instance runner to a project runner is not supported'
elsif group_type?
raise ArgumentError, 'Transitioning a group runner to a project runner is not supported'
end

View File

@ -1,72 +0,0 @@
# frozen_string_literal: true
module AuthorizedProjectUpdate
class ProjectGroupLinkCreateService < BaseService
include Gitlab::Utils::StrongMemoize
BATCH_SIZE = 1000
def initialize(project, group, group_access = nil)
@project = project
@group = group
@group_access = group_access
end
def execute
group.members_from_self_and_ancestors_with_effective_access_level
.each_batch(of: BATCH_SIZE, column: :user_id) do |members|
existing_authorizations = existing_project_authorizations(members)
authorizations_to_create = []
user_ids_to_delete = []
members.each do |member|
new_access_level = access_level(member.access_level)
existing_access_level = existing_authorizations[member.user_id]
if existing_access_level
# User might already have access to the project unrelated to the
# current project share
next if existing_access_level >= new_access_level
user_ids_to_delete << member.user_id
end
authorizations_to_create << { user_id: member.user_id,
project_id: project.id,
access_level: new_access_level }
end
update_authorizations(user_ids_to_delete, authorizations_to_create)
end
ServiceResponse.success
end
private
attr_reader :project, :group, :group_access
def access_level(membership_access_level)
return membership_access_level unless group_access
# access level (role) must not be higher than the max access level (role) set when
# creating the project share
[membership_access_level, group_access].min
end
def existing_project_authorizations(members)
user_ids = members.map(&:user_id)
ProjectAuthorization.where(project_id: project.id, user_id: user_ids) # rubocop: disable CodeReuse/ActiveRecord
.select(:user_id, :access_level)
.each_with_object({}) do |authorization, hash|
hash[authorization.user_id] = authorization.access_level
end
end
def update_authorizations(user_ids_to_delete, authorizations_to_create)
project.remove_project_authorizations(user_ids_to_delete) if user_ids_to_delete.any?
ProjectAuthorization.insert_all_in_batches(authorizations_to_create) if authorizations_to_create.any?
end
end
end

View File

@ -16,29 +16,30 @@
= f.label :default_group_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_group_visibility, form: f, selected_level: @application_setting.default_group_visibility, form_model: Group.new)
.form-group
= f.label :restricted_visibility_levels, class: 'label-bold'
= f.label :restricted_visibility_levels, class: 'label-bold gl-mb-0'
%span.form-text.gl-mt-0.gl-mb-3#restricted-visibility-help
= _('Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users.')
= hidden_field_tag 'application_setting[restricted_visibility_levels][]'
- restricted_level_checkboxes(f).each do |level|
= level
%span.form-text.text-muted#restricted-visibility-help
= _('Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users.')
.form-group
= f.label :import_sources, class: 'label-bold'
= hidden_field_tag 'application_setting[import_sources][]'
- import_sources_checkboxes(f).each do |source|
= source
%span.form-text.text-muted#import-sources-help
= f.label :import_sources, s_('AdminSettings|Import sources'), class: 'label-bold gl-mb-0'
%span.form-text.gl-mt-0.gl-mb-3#import-sources-help
= _('Enabled sources for code import during project creation. OmniAuth must be configured for GitHub')
= link_to sprite_icon('question-o'), help_page_path("integration/github")
, Bitbucket
= link_to sprite_icon('question-o'), help_page_path("integration/bitbucket")
and GitLab.com
= link_to sprite_icon('question-o'), help_page_path("integration/gitlab")
= hidden_field_tag 'application_setting[import_sources][]'
- import_sources_checkboxes(f).each do |source|
= source
= render_if_exists 'admin/application_settings/ldap_access_setting', form: f
.form-group
= f.gitlab_ui_checkbox_component :project_export_enabled, s_('AdminSettings|Project export enabled')
= f.label :project_export, s_('AdminSettings|Project export'), class: 'label-bold'
= f.gitlab_ui_checkbox_component :project_export_enabled, s_('AdminSettings|Enabled')
.form-group
%label.label-bold= _('Enabled Git access protocols')

View File

@ -10,47 +10,48 @@
#js-admin-runner-edit{ data: {runner_id: @runner.id, runner_url: admin_runner_path(@runner) } }
.gl-overflow-auto
%h4.gl-font-lg.gl-my-5= _('Restrict projects for this runner')
- if @runner.project_type?
.gl-overflow-auto
%h4.gl-font-lg.gl-my-5= _('Restrict projects for this runner')
- if @runner.runner_projects.any?
%table.table{ data: { testid: 'assigned-projects' } }
- if @runner.runner_projects.any?
%table.table{ data: { testid: 'assigned-projects' } }
%thead
%tr
%th= _('Assigned projects')
- @runner.runner_projects.each do |runner_project|
- project = runner_project.project
- if project
%tr
%td
= render Pajamas::AlertComponent.new(variant: :danger,
dismissible: false,
title: project.full_name) do
.gl-alert-actions
= link_to _('Disable'), admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, class: 'btn gl-alert-action btn-confirm btn-md gl-button'
%table.table{ data: { testid: 'unassigned-projects' } }
%thead
%tr
%th= _('Assigned projects')
- @runner.runner_projects.each do |runner_project|
- project = runner_project.project
- if project
%tr
%td
= render Pajamas::AlertComponent.new(variant: :danger,
dismissible: false,
title: project.full_name) do
.gl-alert-actions
= link_to _('Disable'), admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, class: 'btn gl-alert-action btn-confirm btn-md gl-button'
%th= s_('Runners|Select projects to assign to this runner')
%th
%table.table{ data: { testid: 'unassigned-projects' } }
%thead
%tr
%th= s_('Runners|Select projects to assign to this runner')
%th
%tr
%td
= form_tag edit_admin_runner_path(@runner), id: 'runner-projects-search', class: 'form-inline', method: :get do
.input-group
= search_field_tag :search, params[:search], class: 'form-control gl-form-input', spellcheck: false
.input-group-append
= submit_tag _('Search'), class: 'gl-button btn btn-default'
%td
- @projects.each do |project|
%tr
%td
= project.full_name
= form_tag edit_admin_runner_path(@runner), id: 'runner-projects-search', class: 'form-inline', method: :get do
.input-group
= search_field_tag :search, params[:search], class: 'form-control gl-form-input', spellcheck: false
.input-group-append
= submit_tag _('Search'), class: 'gl-button btn btn-default'
%td
.float-right
= form_for project.runner_projects.new, url: admin_namespace_project_runner_projects_path(project.namespace, project), method: :post do |f|
= f.hidden_field :runner_id, value: @runner.id
= f.submit _('Enable'), aria: { label: s_('Runners|Change to project runner') }, class: 'gl-button btn btn-sm', data: { confirm: (s_('Runners|You are about to change this instance runner to a project runner. This operation is not reversible. Are you sure you want to continue?') if @runner.instance_type?), confirm_btn_variant: 'danger' }
= paginate_without_count @projects
- @projects.each do |project|
%tr
%td
= project.full_name
%td
.float-right
= form_for project.runner_projects.new, url: admin_namespace_project_runner_projects_path(project.namespace, project), method: :post do |f|
= f.hidden_field :runner_id, value: @runner.id
= f.submit _('Enable'), class: 'gl-button btn btn-sm'
= paginate_without_count @projects

View File

@ -12,15 +12,6 @@
:weight: 1
:idempotent: true
:tags: []
- :name: authorized_project_update:authorized_project_update_project_group_link_create
:worker_name: AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker
:feature_category: :authentication_and_authorization
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: authorized_project_update:authorized_project_update_project_recalculate
:worker_name: AuthorizedProjectUpdate::ProjectRecalculateWorker
:feature_category: :authentication_and_authorization

View File

@ -1,26 +0,0 @@
# frozen_string_literal: true
module AuthorizedProjectUpdate
class ProjectGroupLinkCreateWorker
include ApplicationWorker
data_consistency :always
sidekiq_options retry: 3
feature_category :authentication_and_authorization
urgency :low
queue_namespace :authorized_project_update
idempotent!
def perform(project_id, group_id, group_access = nil)
project = Project.find(project_id)
group = Group.find(group_id)
AuthorizedProjectUpdate::ProjectGroupLinkCreateService
.new(project, group, group_access)
.execute
end
end
end

View File

@ -524,7 +524,7 @@ module Gitlab
# app/assets/stylesheets/example.scss
#
# The jh/ version will be preferred.
initializer :prefer_specialized_assets, after: :append_assets_path do |app|
initializer :prefer_specialized_assets, after: :append_assets_path, before: :build_middleware_stack do |app|
Gitlab.extensions.each do |extension|
%w[images javascripts stylesheets].each do |path|
app.config.assets.paths.unshift("#{config.root}/#{extension}/app/assets/#{path}")

View File

@ -1,11 +1,15 @@
- name: "Converting an instance (shared) runner to a project (specific) runner"
- name: "Changing an instance (shared) runner to a project (specific) runner"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true
body: | # Do not modify this line, instead modify the lines below.
In GitLab 15.0, we will remove the feature that enables you to convert an instance (shared) runner to a project (specific) runner. Users who need to add a runner to only a particular project can register a runner to the project directly.
In GitLab 15.0, you can no longer change an instance (shared) runner to a project (specific) runner.
Users often accidentally change instance runners to project runners, and they're unable to change them back. GitLab does not allow you to change a project runner to a shared runner because of the security implications. A runner meant for one project could be set to run jobs for an entire instance.
Administrators who need to add runners for multiple projects can register a runner for one project, then go to the Admin view and choose additional projects.
stage: Verify
tiers: [Core, Premium, Ultimate]

View File

@ -168,7 +168,7 @@ To add or update variables in the project settings:
- **Type**: [`File` or `Variable`](#cicd-variable-types).
- **Environment scope**: Optional. `All`, or specific [environments](../environments/index.md).
- **Protect variable** Optional. If selected, the variable is only available
in pipelines that run on protected branches or tags.
in pipelines that run on [protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md).
- **Mask variable** Optional. If selected, the variable's **Value** is masked
in job logs. The variable fails to save if the value does not meet the
[masking requirements](#mask-a-cicd-variable).

View File

@ -1262,7 +1262,7 @@ If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you wi
## 14.5
### Converting an instance (shared) runner to a project (specific) runner
### Changing an instance (shared) runner to a project (specific) runner
WARNING:
This feature will be changed or removed in 15.0
@ -1270,7 +1270,11 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
In GitLab 15.0, we will remove the feature that enables you to convert an instance (shared) runner to a project (specific) runner. Users who need to add a runner to only a particular project can register a runner to the project directly.
In GitLab 15.0, you can no longer change an instance (shared) runner to a project (specific) runner.
Users often accidentally change instance runners to project runners, and they're unable to change them back. GitLab does not allow you to change a project runner to a shared runner because of the security implications. A runner meant for one project could be set to run jobs for an entire instance.
Administrators who need to add runners for multiple projects can register a runner for one project, then go to the Admin view and choose additional projects.
**Planned removal milestone: 15.0 (2022-05-22)**

View File

@ -82,6 +82,7 @@ The following items are **not** exported:
- Merge Request Approvers and [the number of required approvals](https://gitlab.com/gitlab-org/gitlab/-/issues/221088)
- Repository size limits
- Deploy keys allowed to push to protected branches
- Secure Files
These content rules also apply to creating projects from templates on the
[group](../../group/custom_project_templates.md)

View File

@ -4,7 +4,7 @@ module API
class ContainerRegistryEvent < ::API::Base
DOCKER_DISTRIBUTION_EVENTS_V1_JSON = 'application/vnd.docker.distribution.events.v1+json'
feature_category :package_registry
feature_category :container_registry
before { authenticate_registry_notification! }

View File

@ -9,7 +9,7 @@ module API
before { authorize_read_group_container_images! }
feature_category :package_registry
feature_category :container_registry
REPOSITORY_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
tag_name: API::NO_SLASH_URL_PART_REGEX)

View File

@ -2651,6 +2651,9 @@ msgstr ""
msgid "AdminSettings|Enable smartcn custom analyzer: Search"
msgstr ""
msgid "AdminSettings|Enabled"
msgstr ""
msgid "AdminSettings|Feed token"
msgstr ""
@ -2663,6 +2666,9 @@ msgstr ""
msgid "AdminSettings|If there isn't any existing index, GitLab creates one."
msgstr ""
msgid "AdminSettings|Import sources"
msgstr ""
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@ -2714,7 +2720,7 @@ msgstr ""
msgid "AdminSettings|Preview payload"
msgstr ""
msgid "AdminSettings|Project export enabled"
msgid "AdminSettings|Project export"
msgstr ""
msgid "AdminSettings|Protect CI/CD variables by default"
@ -27556,9 +27562,6 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
msgid "Pipeline Editor"
msgstr ""
msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
msgstr ""
@ -32556,9 +32559,6 @@ msgstr ""
msgid "Runners|Capacity of 1 enables warm HA through Auto Scaling group re-spawn. Capacity of 2 enables hot HA because the service is available even when a node is lost. Capacity of 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
msgid "Runners|Change to project runner"
msgstr ""
msgid "Runners|Checkbox"
msgstr ""
@ -32615,6 +32615,9 @@ msgstr ""
msgid "Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project."
msgstr ""
msgid "Runners|Executor"
msgstr ""
msgid "Runners|Group"
msgstr ""
@ -32893,9 +32896,6 @@ msgstr ""
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot."
msgstr ""
msgid "Runners|You are about to change this instance runner to a project runner. This operation is not reversible. Are you sure you want to continue?"
msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""

View File

@ -57,7 +57,7 @@
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "2.10.0",
"@gitlab/ui": "39.0.0",
"@gitlab/ui": "39.2.1",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-7",
"@rails/ujs": "6.1.4-7",

View File

@ -486,7 +486,7 @@ RSpec.describe "Admin Runners" do
end
describe "Runner edit page" do
let(:runner) { create(:ci_runner) }
let(:runner) { create(:ci_runner, :project) }
before do
@project1 = create(:project)
@ -507,7 +507,7 @@ RSpec.describe "Admin Runners" do
describe 'runner header', :js do
it 'contains the runner status, type and id' do
expect(page).to have_content("never contacted shared Runner ##{runner.id} created")
expect(page).to have_content("never contacted specific Runner ##{runner.id} created")
end
end
@ -564,17 +564,6 @@ RSpec.describe "Admin Runners" do
it_behaves_like 'assignable runner'
end
context 'with shared runner' do
let(:runner) { create(:ci_runner, :instance) }
before do
@project1.destroy!
visit edit_admin_runner_path(runner)
end
it_behaves_like 'assignable runner'
end
end
describe 'disable/destroy' do

View File

@ -71,7 +71,7 @@ RSpec.describe 'Admin updates settings' do
it 'change Visibility and Access Controls' do
page.within('.as-visibility-access') do
uncheck 'Project export enabled'
uncheck 'Enabled'
click_button 'Save changes'
end

View File

@ -81,7 +81,7 @@ RSpec.describe 'Projects tree', :js do
wait_for_requests
page.within('.project-last-commit') do
expect(page).to have_selector('.user-avatar-link')
expect(page).to have_selector('.gl-avatar')
expect(page).to have_content('Merge branch')
end
end

View File

@ -16,6 +16,7 @@ exports[`Design management index page designs renders error 1`] = `
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
showicon="true"
title=""
variant="danger"
>

View File

@ -180,6 +180,7 @@ exports[`Design management design index page with error GlAlert is rendered in c
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
showicon="true"
title=""
variant="danger"
>

View File

@ -17,6 +17,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
showicon="true"
title="Feature deprecation"
variant="warning"
>

View File

@ -49,6 +49,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
showicon="true"
title=""
variant="danger"
>

View File

@ -43,6 +43,7 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
showicon="true"
title=""
variant="danger"
>

View File

@ -2,13 +2,13 @@
exports[`Repository last commit component renders commit widget 1`] = `
<div
class="well-segment commit gl-p-5 gl-w-full"
class="well-segment commit gl-p-5 gl-w-full gl-display-flex"
>
<user-avatar-link-stub
class="avatar-cell"
class="gl-my-2 gl-mr-4"
imgalt=""
imgcssclasses=""
imgsize="40"
imgcssclasses="gl-mr-0!"
imgsize="32"
imgsrc="https://test.com"
linkhref="/test"
tooltipplacement="top"
@ -55,7 +55,11 @@ exports[`Repository last commit component renders commit widget 1`] = `
</div>
<div
class="commit-actions flex-row"
class="gl-flex-grow-1"
/>
<div
class="commit-actions gl-display-flex gl-flex-align gl-align-items-center gl-flex-direction-row"
>
<!---->

View File

@ -82,6 +82,7 @@ describe('AdminRunnerShowApp', () => {
Last contact Never contacted
Version 1.0.0
IP Address 127.0.0.1
Executor None
Configuration Runs untagged jobs
Maximum job timeout None
Tags None`.replace(/\s+/g, ' ');

View File

@ -77,6 +77,7 @@ describe('RunnerDetails', () => {
${'Last contact'} | ${{ contactedAt: null }} | ${'Never contacted'}
${'Version'} | ${{ version: '12.3' }} | ${'12.3'}
${'Version'} | ${{ version: null }} | ${'None'}
${'Executor'} | ${{ executorName: 'shell' }} | ${'shell'}
${'IP Address'} | ${{ ipAddress: '127.0.0.1' }} | ${'127.0.0.1'}
${'IP Address'} | ${{ ipAddress: null }} | ${'None'}
${'Configuration'} | ${{ accessLevel: ACCESS_LEVEL_REF_PROTECTED, runUntagged: true }} | ${'Protected, Runs untagged jobs'}

View File

@ -123,6 +123,7 @@ describe('RunnerUpdateForm', () => {
const {
__typename,
ipAddress,
executorName,
runnerType,
createdAt,
status,

View File

@ -412,12 +412,9 @@ RSpec.describe Ci::Runner do
context 'with shared_runner' do
let(:runner) { create(:ci_runner, :instance) }
it 'transitions shared runner to project runner and assigns project' do
expect(subject).to be_truthy
expect(runner).to be_project_type
expect(runner.runner_projects.pluck(:project_id)).to match_array([project.id])
expect(runner.only_for?(project)).to be_truthy
it 'raises an error' do
expect { subject }
.to raise_error(ArgumentError, 'Transitioning an instance runner to a project runner is not supported')
end
end
@ -430,6 +427,18 @@ RSpec.describe Ci::Runner do
.to raise_error(ArgumentError, 'Transitioning a group runner to a project runner is not supported')
end
end
context 'with project runner' do
let(:other_project) { create(:project) }
let(:runner) { create(:ci_runner, :project, projects: [other_project]) }
it 'assigns runner to project' do
expect(subject).to be_truthy
expect(runner).to be_project_type
expect(runner.runner_projects.pluck(:project_id)).to contain_exactly(project.id, other_project.id)
end
end
end
describe '.recent' do

View File

@ -1216,15 +1216,6 @@ RSpec.describe API::Ci::Runners do
end
end
end
it 'enables a instance type runner' do
expect do
post api("/projects/#{project.id}/runners", admin), params: { runner_id: shared_runner.id }
end.to change { project.runners.count }.by(1)
expect(shared_runner.reload).not_to be_instance_type
expect(response).to have_gitlab_http_status(:created)
end
end
it 'raises an error when no runner_id param is provided' do

View File

@ -1,222 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AuthorizedProjectUpdate::ProjectGroupLinkCreateService do
let_it_be(:group_parent) { create(:group, :private) }
let_it_be(:group) { create(:group, :private, parent: group_parent) }
let_it_be(:group_child) { create(:group, :private, parent: group) }
let_it_be(:parent_group_user) { create(:user) }
let_it_be(:group_user) { create(:user) }
let_it_be(:project) { create(:project, :private, group: create(:group, :private)) }
let(:access_level) { Gitlab::Access::MAINTAINER }
let(:group_access) { nil }
subject(:service) { described_class.new(project, group, group_access) }
describe '#perform' do
context 'direct group members' do
before do
create(:group_member, access_level: access_level, group: group, user: group_user)
ProjectAuthorization.delete_all
end
it 'creates project authorization' do
expect { service.execute }.to(
change { ProjectAuthorization.count }.from(0).to(1))
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: group_user.id,
access_level: access_level)
expect(project_authorization).to exist
end
end
context 'inherited group members' do
before do
create(:group_member, access_level: access_level, group: group_parent, user: parent_group_user)
ProjectAuthorization.delete_all
end
it 'creates project authorization' do
expect { service.execute }.to(
change { ProjectAuthorization.count }.from(0).to(1))
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: parent_group_user.id,
access_level: access_level)
expect(project_authorization).to exist
end
end
context 'with group_access' do
let(:group_access) { Gitlab::Access::REPORTER }
before do
create(:group_member, access_level: access_level, group: group_parent, user: parent_group_user)
ProjectAuthorization.delete_all
end
it 'creates project authorization' do
expect { service.execute }.to(
change { ProjectAuthorization.count }.from(0).to(1))
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: parent_group_user.id,
access_level: group_access)
expect(project_authorization).to exist
end
end
context 'membership overrides' do
before do
create(:group_member, access_level: Gitlab::Access::REPORTER, group: group_parent, user: group_user)
create(:group_member, access_level: Gitlab::Access::DEVELOPER, group: group, user: group_user)
ProjectAuthorization.delete_all
end
it 'creates project authorization' do
expect { service.execute }.to(
change { ProjectAuthorization.count }.from(0).to(1))
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: group_user.id,
access_level: Gitlab::Access::DEVELOPER)
expect(project_authorization).to exist
end
end
context 'no group member' do
it 'does not create project authorization' do
expect { service.execute }.not_to(
change { ProjectAuthorization.count }.from(0))
end
end
context 'unapproved access requests' do
before do
create(:group_member, :guest, :access_request, user: group_user, group: group)
end
it 'does not create project authorization' do
expect { service.execute }.not_to(
change { ProjectAuthorization.count }.from(0))
end
end
context 'minimal access member' do
before do
create(:group_member, :minimal_access, user: group_user, source: group)
end
it 'does not create project authorization' do
expect { service.execute }.not_to(
change { ProjectAuthorization.count }.from(0))
end
end
context 'project has more users than BATCH_SIZE' do
let(:batch_size) { 2 }
let(:users) { create_list(:user, batch_size + 1 ) }
before do
stub_const("#{described_class.name}::BATCH_SIZE", batch_size)
users.each do |user|
create(:group_member, access_level: access_level, group: group_parent, user: user)
end
ProjectAuthorization.delete_all
end
it 'bulk creates project authorizations in batches' do
users.each_slice(batch_size) do |batch|
attributes = batch.map do |user|
{ user_id: user.id, project_id: project.id, access_level: access_level }
end
expect(ProjectAuthorization).to(
receive(:insert_all).with(array_including(attributes)).and_call_original)
end
expect { service.execute }.to(
change { ProjectAuthorization.count }.from(0).to(batch_size + 1))
end
end
context 'users have existing project authorizations' do
before do
create(:group_member, access_level: access_level, group: group, user: group_user)
ProjectAuthorization.delete_all
create(:project_authorization, user_id: group_user.id,
project_id: project.id,
access_level: existing_access_level)
end
context 'when access level is the same' do
let(:existing_access_level) { access_level }
it 'does not create project authorization' do
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: group_user.id,
access_level: existing_access_level)
expect(ProjectAuthorization).not_to receive(:insert_all)
expect { service.execute }.not_to(
change { project_authorization.reload.exists? }.from(true))
end
end
context 'when existing access level is lower' do
let(:existing_access_level) { Gitlab::Access::DEVELOPER }
it 'creates new project authorization' do
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: group_user.id,
access_level: access_level)
expect { service.execute }.to(
change { project_authorization.reload.exists? }.from(false).to(true))
end
it 'deletes previous project authorization' do
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: group_user.id,
access_level: existing_access_level)
expect { service.execute }.to(
change { project_authorization.reload.exists? }.from(true).to(false))
end
end
context 'when existing access level is higher' do
let(:existing_access_level) { Gitlab::Access::OWNER }
it 'does not create project authorization' do
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: group_user.id,
access_level: existing_access_level)
expect(ProjectAuthorization).not_to receive(:insert_all)
expect { service.execute }.not_to(
change { project_authorization.reload.exists? }.from(true))
end
end
end
end
end

View File

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker do
let_it_be(:group) { create(:group, :private) }
let_it_be(:group_project) { create(:project, group: group) }
let_it_be(:shared_with_group) { create(:group, :private) }
let_it_be(:user) { create(:user) }
let(:access_level) { Gitlab::Access::MAINTAINER }
subject(:worker) { described_class.new }
it 'calls AuthorizedProjectUpdate::ProjectCreateService' do
expect_next_instance_of(AuthorizedProjectUpdate::ProjectGroupLinkCreateService) do |service|
expect(service).to(receive(:execute))
end
worker.perform(group_project.id, shared_with_group.id)
end
it 'returns ServiceResponse.success' do
result = worker.perform(group_project.id, shared_with_group.id)
expect(result.success?).to be_truthy
end
context 'idempotence' do
before do
create(:group_member, group: shared_with_group, user: user, access_level: access_level)
create(:project_group_link, project: group_project, group: shared_with_group)
ProjectAuthorization.delete_all
end
include_examples 'an idempotent worker' do
let(:job_args) { [group_project.id, shared_with_group.id] }
it 'creates project authorization' do
subject
project_authorization = ProjectAuthorization.where(
project_id: group_project.id,
user_id: user.id,
access_level: access_level)
expect(project_authorization).to exist
expect(ProjectAuthorization.count).to eq(1)
end
end
end
end

View File

@ -127,7 +127,6 @@ RSpec.describe 'Every Sidekiq worker' do
'ArchiveTraceWorker' => 3,
'AuthorizedKeysWorker' => 3,
'AuthorizedProjectUpdate::ProjectCreateWorker' => 3,
'AuthorizedProjectUpdate::ProjectGroupLinkCreateWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker' => 3,
'AuthorizedProjectUpdate::UserRefreshFromReplicaWorker' => 3,

View File

@ -974,10 +974,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.10.0.tgz#223d3ab592b06aff330a05aa2e7b590624ab8a08"
integrity sha512-XohQ/abgalEHNaNR/HCTS761GUSzlLAMSyO/37eaSykjMqeX8v2iEwUm+0JtmI70N/7mp/tFZv5gzGIDt5oWgQ==
"@gitlab/ui@39.0.0":
version "39.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-39.0.0.tgz#12e658fe84e94b494fec926d824989cbf1334e5c"
integrity sha512-QsD8Os3eXgIq4xlxIvhxmhKPDWYyqCAlDGMw4afo2ynQriIg73KoV6Me3QRwGhaNfzO77Sk9reRxdHLG3L+iNA==
"@gitlab/ui@39.2.1":
version "39.2.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-39.2.1.tgz#e1930ccfd85ff3b378f2d4b4e769df6022d778f8"
integrity sha512-CwArf5CLS9VhnpGJMPtROzLEtUHudaXVSo2HusKQS6rMUWDsc0SFF5nC07uIlp0oI8iS3zt3O9Ma9uAJBlxLgA==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1"