Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c8a7e4ada1
commit
6a0a4a80f7
27 changed files with 337 additions and 55 deletions
|
@ -1 +1 @@
|
|||
6ecbf56693083f1a872a53ad6accfc7d0d806718
|
||||
d950585cb9763c6014ae2c9b7c4f4923d90c9f81
|
||||
|
|
|
@ -1 +1 @@
|
|||
13.19.1
|
||||
13.21.0
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
/* eslint-disable @gitlab/vue-require-i18n-strings */
|
||||
import { GlTooltipDirective, GlIcon, GlLink } from '@gitlab/ui';
|
||||
import { GlTooltipDirective, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
|
@ -32,6 +31,7 @@ export default {
|
|||
ExternalUrlComponent,
|
||||
GlIcon,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
MonitoringButtonComponent,
|
||||
PinComponent,
|
||||
DeleteComponent,
|
||||
|
@ -647,14 +647,17 @@ export default {
|
|||
</span>
|
||||
|
||||
<span v-if="!isFolder && deploymentHasUser" class="text-break-word">
|
||||
by
|
||||
<user-avatar-link
|
||||
:link-href="deploymentUser.web_url"
|
||||
:img-src="deploymentUser.avatar_url"
|
||||
:img-alt="userImageAltDescription"
|
||||
:tooltip-text="deploymentUser.username"
|
||||
class="js-deploy-user-container float-none"
|
||||
/>
|
||||
<gl-sprintf :message="s__('Environments|by %{avatar}')">
|
||||
<template #avatar>
|
||||
<user-avatar-link
|
||||
:link-href="deploymentUser.web_url"
|
||||
:img-src="deploymentUser.avatar_url"
|
||||
:img-alt="userImageAltDescription"
|
||||
:tooltip-text="deploymentUser.username"
|
||||
class="js-deploy-user-container float-none"
|
||||
/>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
|
||||
<div v-if="showNoDeployments" class="commit-title table-mobile-content">
|
||||
|
@ -743,13 +746,16 @@ export default {
|
|||
</div>
|
||||
<div class="gl-display-flex">
|
||||
<span v-if="upcomingDeployment.user" class="text-break-word">
|
||||
by
|
||||
<user-avatar-link
|
||||
:link-href="upcomingDeployment.user.web_url"
|
||||
:img-src="upcomingDeployment.user.avatar_url"
|
||||
:img-alt="upcomingDeploymentUserImageAltDescription"
|
||||
:tooltip-text="upcomingDeployment.user.username"
|
||||
/>
|
||||
<gl-sprintf :message="s__('Environments|by %{avatar}')">
|
||||
<template #avatar>
|
||||
<user-avatar-link
|
||||
:link-href="upcomingDeployment.user.web_url"
|
||||
:img-src="upcomingDeployment.user.avatar_url"
|
||||
:img-alt="upcomingDeploymentUserImageAltDescription"
|
||||
:tooltip-text="upcomingDeployment.user.username"
|
||||
/>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@ import Group from '~/group';
|
|||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import NewGroupCreationApp from './components/app.vue';
|
||||
import GroupPathValidator from './group_path_validator';
|
||||
import initToggleInviteMembers from './toggle_invite_members';
|
||||
|
||||
new GroupPathValidator(); // eslint-disable-line no-new
|
||||
|
||||
|
@ -31,3 +32,5 @@ function initNewGroupCreation(el) {
|
|||
const el = document.querySelector('.js-new-group-creation');
|
||||
|
||||
initNewGroupCreation(el);
|
||||
|
||||
initToggleInviteMembers();
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
|
||||
export default function initToggleInviteMembers() {
|
||||
const inviteMembersSection = document.querySelector('.js-invite-members-section');
|
||||
const setupForCompanyRadios = document.querySelectorAll('input[name="group[setup_for_company]"]');
|
||||
|
||||
if (inviteMembersSection && setupForCompanyRadios.length) {
|
||||
setupForCompanyRadios.forEach((el) => {
|
||||
el.addEventListener('change', (event) => {
|
||||
inviteMembersSection.classList.toggle('hidden', !parseBoolean(event.target.value));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -64,6 +64,7 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
def new
|
||||
@group = Group.new(params.permit(:parent_id))
|
||||
@group.build_namespace_settings
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -269,7 +270,9 @@ class GroupsController < Groups::ApplicationController
|
|||
:default_branch_name,
|
||||
:allow_mfa_for_subgroups,
|
||||
:resource_access_token_creation_allowed,
|
||||
:prevent_sharing_groups_outside_hierarchy
|
||||
:prevent_sharing_groups_outside_hierarchy,
|
||||
:setup_for_company,
|
||||
:jobs_to_be_done
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -342,7 +345,15 @@ class GroupsController < Groups::ApplicationController
|
|||
render action: 'new'
|
||||
end
|
||||
|
||||
def successful_creation_hooks; end
|
||||
def successful_creation_hooks
|
||||
update_user_role_and_setup_for_company
|
||||
end
|
||||
|
||||
def update_user_role_and_setup_for_company
|
||||
user_params = params.fetch(:user, {}).permit(:role)
|
||||
user_params[:setup_for_company] = @group.setup_for_company if !@group.setup_for_company.nil? && current_user.setup_for_company.nil?
|
||||
Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute if user_params.present?
|
||||
end
|
||||
|
||||
def groups
|
||||
if @group.supports_events?
|
||||
|
|
|
@ -219,6 +219,18 @@ module GroupsHelper
|
|||
def group_url_error_message
|
||||
s_('GroupSettings|Please choose a group URL with no special characters or spaces.')
|
||||
end
|
||||
|
||||
# Maps `jobs_to_be_done` values to option texts
|
||||
def localized_jobs_to_be_done_choices
|
||||
{
|
||||
basics: _('I want to learn the basics of Git'),
|
||||
move_repository: _('I want to move my repository to GitLab from somewhere else'),
|
||||
code_storage: _('I want to store my code'),
|
||||
exploring: _('I want to explore GitLab to see if it’s worth switching to'),
|
||||
ci: _('I want to use GitLab CI with my existing repository'),
|
||||
other: _('A different reason')
|
||||
}.with_indifferent_access.freeze
|
||||
end
|
||||
end
|
||||
|
||||
GroupsHelper.prepend_mod_with('GroupsHelper')
|
||||
|
|
|
@ -81,7 +81,7 @@ class Group < Namespace
|
|||
# debian_distributions and associated component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
|
||||
has_many :debian_distributions, class_name: 'Packages::Debian::GroupDistribution', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
||||
|
||||
delegate :prevent_sharing_groups_outside_hierarchy, :new_user_signups_cap, to: :namespace_settings
|
||||
delegate :prevent_sharing_groups_outside_hierarchy, :new_user_signups_cap, :setup_for_company, :jobs_to_be_done, to: :namespace_settings
|
||||
|
||||
accepts_nested_attributes_for :variables, allow_destroy: true
|
||||
|
||||
|
|
|
@ -16,9 +16,12 @@ class NamespaceSetting < ApplicationRecord
|
|||
|
||||
before_validation :normalize_default_branch_name
|
||||
|
||||
enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true
|
||||
|
||||
NAMESPACE_SETTINGS_PARAMS = [:default_branch_name, :delayed_project_removal,
|
||||
:lock_delayed_project_removal, :resource_access_token_creation_allowed,
|
||||
:prevent_sharing_groups_outside_hierarchy, :new_user_signups_cap].freeze
|
||||
:prevent_sharing_groups_outside_hierarchy, :new_user_signups_cap,
|
||||
:setup_for_company, :jobs_to_be_done].freeze
|
||||
|
||||
self.primary_key = :namespace_id
|
||||
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
- if Gitlab.config.mattermost.enabled
|
||||
.row
|
||||
= render 'create_chat_team', f: f
|
||||
.row
|
||||
|
||||
= render 'personalize', f: f
|
||||
|
||||
.row.js-invite-members-section
|
||||
.col-sm-4
|
||||
= render_if_exists 'shared/groups/invite_members'
|
||||
|
||||
|
|
27
app/views/groups/_personalize.html.haml
Normal file
27
app/views/groups/_personalize.html.haml
Normal file
|
@ -0,0 +1,27 @@
|
|||
.row
|
||||
.form-group.col-sm-12.gl-mb-0
|
||||
%label.label-bold
|
||||
= _('Now, personalize your GitLab experience')
|
||||
%p
|
||||
= _("We'll use this to help surface the right features and information to you.")
|
||||
|
||||
.row
|
||||
.form-group.col-sm-4
|
||||
= label :user, :role, _('Role')
|
||||
= select :user, :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { selected: @current_user.role }, class: 'form-control'
|
||||
|
||||
.row
|
||||
.form-group.col-sm-4
|
||||
= f.label :setup_for_company, _('Who will be using this group?')
|
||||
.gl-display-flex.gl-flex-direction-column.gl-lg-flex-direction-row
|
||||
.gl-flex-grow-1.gl-display-flex.gl-align-items-center
|
||||
= f.radio_button :setup_for_company, true, checked: true
|
||||
= f.label :setup_for_company, _('My company or team'), class: 'gl-font-weight-normal gl-mb-0 gl-ml-2', value: 'true'
|
||||
.gl-flex-grow-1.gl-display-flex.gl-align-items-center
|
||||
= f.radio_button :setup_for_company, false
|
||||
= f.label :setup_for_company, _('Just me'), class: 'gl-font-weight-normal gl-mb-0 gl-ml-2', value: 'false'
|
||||
|
||||
.row
|
||||
.form-group.col-sm-4
|
||||
= f.label :jobs_to_be_done, _("What will you use this group for?")
|
||||
= f.select :jobs_to_be_done, ::NamespaceSetting.jobs_to_be_dones.keys.map { |job_to_be_done| [localized_jobs_to_be_done_choices[job_to_be_done], job_to_be_done] }, { include_blank: true }, class: 'form-control'
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
%fieldset
|
||||
%h5= _('Permissions')
|
||||
.form-group
|
||||
= render 'shared/allow_request_access', form: f
|
||||
- unless ::Feature.enabled?(:saas_user_caps)
|
||||
.form-group
|
||||
= render 'shared/allow_request_access', form: f
|
||||
|
||||
- if @group.root?
|
||||
.form-group.gl-mb-3
|
||||
|
@ -43,5 +44,6 @@
|
|||
= render_if_exists 'groups/settings/prevent_forking', f: f, group: @group
|
||||
= render 'groups/settings/two_factor_auth', f: f, group: @group
|
||||
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
|
||||
= render_if_exists 'groups/settings/membership', f: f
|
||||
= render_if_exists 'groups/member_lock_setting', f: f, group: @group
|
||||
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm gl-mt-3 js-dirty-submit', data: { qa_selector: 'save_permissions_changes_button' }
|
||||
|
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332963
|
|||
milestone: '14.0'
|
||||
type: development
|
||||
group: group::pipeline authoring
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddColumnsToNamespaceSettings < ActiveRecord::Migration[6.1]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
add_column :namespace_settings, :setup_for_company, :boolean
|
||||
add_column :namespace_settings, :jobs_to_be_done, :smallint
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_column :namespace_settings, :setup_for_company
|
||||
remove_column :namespace_settings, :jobs_to_be_done
|
||||
end
|
||||
end
|
||||
end
|
1
db/schema_migrations/20210819162047
Normal file
1
db/schema_migrations/20210819162047
Normal file
|
@ -0,0 +1 @@
|
|||
5a02c5a24bb4c7cb63da2e5cc53ff89461f328d0092bb4bb6589223dc4bdae8c
|
|
@ -15344,6 +15344,8 @@ CREATE TABLE namespace_settings (
|
|||
lock_delayed_project_removal boolean DEFAULT false NOT NULL,
|
||||
prevent_sharing_groups_outside_hierarchy boolean DEFAULT false NOT NULL,
|
||||
new_user_signups_cap integer,
|
||||
setup_for_company boolean,
|
||||
jobs_to_be_done smallint,
|
||||
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
|
||||
);
|
||||
|
||||
|
|
|
@ -4472,7 +4472,6 @@ Input type: `VulnerabilityCreateInput`
|
|||
| <a id="mutationvulnerabilitycreateproject"></a>`project` | [`ProjectID!`](#projectid) | ID of the project to attach the vulnerability to. |
|
||||
| <a id="mutationvulnerabilitycreateresolvedat"></a>`resolvedAt` | [`Time`](#time) | Timestamp of when the vulnerability state changed to resolved (defaults to creation time if status is `resolved`). |
|
||||
| <a id="mutationvulnerabilitycreatescannername"></a>`scannerName` | [`String!`](#string) | Name of the security scanner used to discover the vulnerability. |
|
||||
| <a id="mutationvulnerabilitycreatescannertype"></a>`scannerType` | [`SecurityScannerType!`](#securityscannertype) | Type of the security scanner used to discover the vulnerability. |
|
||||
| <a id="mutationvulnerabilitycreateseverity"></a>`severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the vulnerability (defaults to `unknown`). |
|
||||
| <a id="mutationvulnerabilitycreatesolution"></a>`solution` | [`String`](#string) | How to fix this vulnerability. |
|
||||
| <a id="mutationvulnerabilitycreatestate"></a>`state` | [`VulnerabilityState`](#vulnerabilitystate) | State of the vulnerability (defaults to `detected`). |
|
||||
|
|
|
@ -82,6 +82,10 @@ To create a group:
|
|||
- Underscores
|
||||
- Dashes and dots (it cannot start with dashes or end in a dot)
|
||||
1. Choose the [visibility level](../../public_access/public_access.md).
|
||||
1. Personalize your GitLab experience by answering the following questions:
|
||||
- What is your role?
|
||||
- Who will be using this group?
|
||||
- What will you use this group for?
|
||||
1. Invite GitLab members or other users to join the group.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
|
|
|
@ -13,18 +13,13 @@ module API
|
|||
post '/lint' do
|
||||
unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil?
|
||||
|
||||
result = Gitlab::Ci::YamlProcessor.new(params[:content], user: current_user).execute
|
||||
result = Gitlab::Ci::Lint.new(project: nil, current_user: current_user)
|
||||
.validate(params[:content], dry_run: false)
|
||||
|
||||
status 200
|
||||
|
||||
response = if result.errors.empty?
|
||||
{ status: 'valid', errors: [], warnings: result.warnings }
|
||||
else
|
||||
{ status: 'invalid', errors: result.errors, warnings: result.warnings }
|
||||
end
|
||||
|
||||
response.tap do |response|
|
||||
response[:merged_yaml] = result.merged_yaml if params[:include_merged_yaml]
|
||||
Entities::Ci::Lint::Result.represent(result, current_user: current_user).serializable_hash.tap do |presented_result|
|
||||
presented_result[:status] = presented_result[:valid] ? 'valid' : 'invalid'
|
||||
presented_result.delete(:merged_yaml) unless params[:include_merged_yaml]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,5 +30,3 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Checks::BaseSingleChecker.prepend_mod_with('Gitlab::Checks::BaseSingleChecker')
|
||||
|
|
|
@ -76,23 +76,33 @@ module Gitlab
|
|||
result
|
||||
end
|
||||
|
||||
def single_change_accesses
|
||||
@single_changes_accesses ||=
|
||||
changes.map do |change|
|
||||
commits =
|
||||
if change[:newrev].blank? || Gitlab::Git.blank_ref?(change[:newrev])
|
||||
[]
|
||||
else
|
||||
Gitlab::Lazy.new { commits_for(change[:newrev]) }
|
||||
end
|
||||
|
||||
Checks::SingleChangeAccess.new(
|
||||
change,
|
||||
user_access: user_access,
|
||||
project: project,
|
||||
protocol: protocol,
|
||||
logger: logger,
|
||||
commits: commits
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def single_access_checks!
|
||||
# Iterate over all changes to find if user allowed all of them to be applied
|
||||
changes.each do |change|
|
||||
commits = Gitlab::Lazy.new { commits_for(change[:newrev]) }
|
||||
|
||||
# If user does not have access to make at least one change, cancel all
|
||||
# push by allowing the exception to bubble up
|
||||
Checks::SingleChangeAccess.new(
|
||||
change,
|
||||
user_access: user_access,
|
||||
project: project,
|
||||
protocol: protocol,
|
||||
logger: logger,
|
||||
commits: commits
|
||||
).validate!
|
||||
single_change_accesses.each do |single_change_access|
|
||||
single_change_access.validate!
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -102,3 +112,5 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Checks::ChangesAccess.prepend_mod_with('Gitlab::Checks::ChangesAccess')
|
||||
|
|
|
@ -21,7 +21,7 @@ module Gitlab
|
|||
def initialize(project:, current_user:, sha: nil)
|
||||
@project = project
|
||||
@current_user = current_user
|
||||
@sha = sha || project.repository.commit&.sha
|
||||
@sha = sha || project&.repository&.commit&.sha
|
||||
end
|
||||
|
||||
def validate(content, dry_run: false)
|
||||
|
|
|
@ -12911,6 +12911,9 @@ msgstr ""
|
|||
msgid "Environments|Your feedback helps GitLab make environments better for you and other users. Participate and enter a sweepstake to win a USD 30 gift card."
|
||||
msgstr ""
|
||||
|
||||
msgid "Environments|by %{avatar}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Environments|protected"
|
||||
msgstr ""
|
||||
|
||||
|
@ -20808,6 +20811,9 @@ msgstr ""
|
|||
msgid "Members of a group may only view projects they have permission to access"
|
||||
msgstr ""
|
||||
|
||||
msgid "Membership"
|
||||
msgstr ""
|
||||
|
||||
msgid "Members|%{time} by %{user}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -23071,6 +23077,9 @@ msgstr ""
|
|||
msgid "Novice"
|
||||
msgstr ""
|
||||
|
||||
msgid "Now, personalize your GitLab experience"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
|
||||
msgstr ""
|
||||
|
||||
|
@ -37346,6 +37355,9 @@ msgstr ""
|
|||
msgid "We'll continuously validate your pipeline configuration. The validation results will appear here."
|
||||
msgstr ""
|
||||
|
||||
msgid "We'll use this to help surface the right features and information to you."
|
||||
msgstr ""
|
||||
|
||||
msgid "We've found no vulnerabilities"
|
||||
msgstr ""
|
||||
|
||||
|
@ -37601,6 +37613,9 @@ msgstr ""
|
|||
msgid "What is your job title? (optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "What will you use this group for?"
|
||||
msgstr ""
|
||||
|
||||
msgid "What's new"
|
||||
msgstr ""
|
||||
|
||||
|
@ -37660,6 +37675,9 @@ msgstr ""
|
|||
msgid "Who will be using this GitLab trial?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who will be using this group?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Why are you signing up? (Optional)"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -370,6 +370,57 @@ RSpec.describe GroupsController, factory_default: :keep do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when creating a group with the `role` attribute present' do
|
||||
it 'changes the users role' do
|
||||
sign_in(user)
|
||||
|
||||
expect do
|
||||
post :create, params: { group: { name: 'new_group', path: 'new_group' }, user: { role: 'devops_engineer' } }
|
||||
end.to change { user.reload.role }.to('devops_engineer')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when creating a group with the `setup_for_company` attribute present' do
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
subject do
|
||||
post :create, params: { group: { name: 'new_group', path: 'new_group', setup_for_company: 'false' } }
|
||||
end
|
||||
|
||||
it 'sets the groups `setup_for_company` value' do
|
||||
subject
|
||||
expect(Group.last.setup_for_company).to be(false)
|
||||
end
|
||||
|
||||
context 'when the user already has a value for `setup_for_company`' do
|
||||
before do
|
||||
user.update_attribute(:setup_for_company, true)
|
||||
end
|
||||
|
||||
it 'does not change the users `setup_for_company` value' do
|
||||
expect(Users::UpdateService).not_to receive(:new)
|
||||
expect { subject }.not_to change { user.reload.setup_for_company }.from(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user has no value for `setup_for_company`' do
|
||||
it 'changes the users `setup_for_company` value' do
|
||||
expect(Users::UpdateService).to receive(:new).and_call_original
|
||||
expect { subject }.to change { user.reload.setup_for_company }.to(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when creating a group with the `jobs_to_be_done` attribute present' do
|
||||
it 'sets the groups `jobs_to_be_done` value' do
|
||||
sign_in(user)
|
||||
post :create, params: { group: { name: 'new_group', path: 'new_group', jobs_to_be_done: 'other' } }
|
||||
expect(Group.last.jobs_to_be_done).to eq('other')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
|
|
|
@ -486,4 +486,10 @@ RSpec.describe GroupsHelper do
|
|||
expect(helper.can_admin_group_member?(group)).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#localized_jobs_to_be_done_choices' do
|
||||
it 'has a translation for all `jobs_to_be_done` values' do
|
||||
expect(localized_jobs_to_be_done_choices.keys).to match_array(NamespaceSetting.jobs_to_be_dones.keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -174,6 +174,101 @@ RSpec.describe Gitlab::Checks::ChangesAccess do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#single_change_accesses' do
|
||||
let(:commits_for) { {} }
|
||||
let(:expected_accesses) { [] }
|
||||
|
||||
shared_examples '#single_change_access' do
|
||||
before do
|
||||
commits_for.each do |id, commits|
|
||||
expect(subject)
|
||||
.to receive(:commits_for)
|
||||
.with(id)
|
||||
.and_return(commits)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns an array of SingleChangeAccess' do
|
||||
# Commits are wrapped in a Gitlab::Lazy and thus need to be resolved
|
||||
# first such that we can directly compare types.
|
||||
actual_accesses = subject.single_change_accesses
|
||||
.each { |access| access.instance_variable_set(:@commits, access.commits.to_a) }
|
||||
|
||||
expect(actual_accesses).to match_array(expected_accesses)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no changes' do
|
||||
let(:changes) { [] }
|
||||
|
||||
it_behaves_like '#single_change_access'
|
||||
end
|
||||
|
||||
context 'with a single change and no new commits' do
|
||||
let(:commits_for) { { 'new' => [] } }
|
||||
let(:changes) do
|
||||
[
|
||||
{ oldrev: 'old', newrev: 'new', ref: 'refs/heads/branch' }
|
||||
]
|
||||
end
|
||||
|
||||
let(:expected_accesses) do
|
||||
[
|
||||
have_attributes(oldrev: 'old', newrev: 'new', ref: 'refs/heads/branch', commits: [])
|
||||
]
|
||||
end
|
||||
|
||||
it_behaves_like '#single_change_access'
|
||||
end
|
||||
|
||||
context 'with a single change and new commits' do
|
||||
let(:commits_for) { { 'new' => [create_commit('new', [])] } }
|
||||
let(:changes) do
|
||||
[
|
||||
{ oldrev: 'old', newrev: 'new', ref: 'refs/heads/branch' }
|
||||
]
|
||||
end
|
||||
|
||||
let(:expected_accesses) do
|
||||
[
|
||||
have_attributes(oldrev: 'old', newrev: 'new', ref: 'refs/heads/branch', commits: [create_commit('new', [])])
|
||||
]
|
||||
end
|
||||
|
||||
it_behaves_like '#single_change_access'
|
||||
end
|
||||
|
||||
context 'with multiple changes' do
|
||||
let(:commits_for) do
|
||||
{
|
||||
'a' => [create_commit('a', [])],
|
||||
'c' => [create_commit('c', [])],
|
||||
'd' => []
|
||||
}
|
||||
end
|
||||
|
||||
let(:changes) do
|
||||
[
|
||||
{ newrev: 'a', ref: 'refs/heads/a' },
|
||||
{ oldrev: 'b', ref: 'refs/heads/b' },
|
||||
{ oldrev: 'a', newrev: 'c', ref: 'refs/heads/c' },
|
||||
{ newrev: 'd', ref: 'refs/heads/d' }
|
||||
]
|
||||
end
|
||||
|
||||
let(:expected_accesses) do
|
||||
[
|
||||
have_attributes(newrev: 'a', ref: 'refs/heads/a', commits: [create_commit('a', [])]),
|
||||
have_attributes(oldrev: 'b', ref: 'refs/heads/b', commits: []),
|
||||
have_attributes(oldrev: 'a', newrev: 'c', ref: 'refs/heads/c', commits: [create_commit('c', [])]),
|
||||
have_attributes(newrev: 'd', ref: 'refs/heads/d', commits: [])
|
||||
]
|
||||
end
|
||||
|
||||
it_behaves_like '#single_change_access'
|
||||
end
|
||||
end
|
||||
|
||||
def create_commit(id, parent_ids)
|
||||
Gitlab::Git::Commit.new(project.repository, {
|
||||
id: id,
|
||||
|
|
|
@ -113,7 +113,6 @@ RSpec.describe API::Lint do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['status']).to eq('valid')
|
||||
expect(json_response['warnings']).not_to be_empty
|
||||
expect(json_response['status']).to eq('valid')
|
||||
expect(json_response['errors']).to eq([])
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue