Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-26 18:09:02 +00:00
parent 8cd1a72e8f
commit dd9af4e967
32 changed files with 296 additions and 135 deletions

View File

@ -1 +1 @@
10d5f9bbf09a1405185519e34756925e8cbcc19f
ccfab390f7c32dae9d5683662be62d27c80f768f

View File

@ -1,6 +1,7 @@
<script>
import { GlButton, GlButtonGroup, GlModal, GlModalDirective, GlSprintf } from '@gitlab/ui';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
import { redirectTo } from '~/lib/utils/url_utility';
import {
ACTIONS_DOWNLOAD_ARTIFACTS,
ACTIONS_START_NOW,
@ -108,11 +109,11 @@ export default {
},
},
methods: {
async postJobAction(name, mutation) {
async postJobAction(name, mutation, redirect = false) {
try {
const {
data: {
[name]: { errors },
[name]: { errors, job },
},
} = await this.$apollo.mutate({
mutation,
@ -121,6 +122,10 @@ export default {
if (errors.length > 0) {
reportMessageToSentry(this.$options.name, errors.join(', '), {});
this.showToastMessage();
} else if (redirect) {
// Retry and Play actions redirect to job detail view
// we don't need to refetch with jobActionPerformed event
redirectTo(job.detailedStatus.detailsPath);
} else {
eventHub.$emit('jobActionPerformed');
}
@ -147,12 +152,12 @@ export default {
retryJob() {
this.retryBtnDisabled = true;
this.postJobAction(this.$options.jobRetry, retryJobMutation);
this.postJobAction(this.$options.jobRetry, retryJobMutation, true);
},
playJob() {
this.playManualBtnDisabled = true;
this.postJobAction(this.$options.jobPlay, playJobMutation);
this.postJobAction(this.$options.jobPlay, playJobMutation, true);
},
unscheduleJob() {
this.unscheduleBtnDisabled = true;

View File

@ -1,3 +1,7 @@
fragment Job on CiJob {
id
detailedStatus {
id
detailsPath
}
}

View File

@ -713,22 +713,6 @@ pre.light-well {
margin-bottom: 10px;
}
.service-installation {
padding: 32px;
margin: 32px;
border-radius: 3px;
background-color: $white;
h3 {
margin-top: 0;
}
hr {
margin: 32px 0;
border-color: $border-color;
}
}
.project-badge {
opacity: 0.9;

View File

@ -5,6 +5,8 @@ module Types
class RunnerUpgradeStatusTypeEnum < BaseEnum
graphql_name 'CiRunnerUpgradeStatusType'
value 'UNKNOWN', description: 'Upgrade status is unknown.', value: :unknown
Gitlab::Ci::RunnerUpgradeCheck::STATUSES.each do |status, description|
value status.to_s.upcase, description: description, value: status
end

View File

@ -336,7 +336,7 @@ module Ci
scope :with_only_interruptible_builds, -> do
where('NOT EXISTS (?)',
Ci::Build.where('ci_builds.commit_id = ci_pipelines.id')
.with_status(:running, :success, :failed)
.with_status(STARTED_STATUSES)
.not_interruptible
)
end

View File

@ -7,16 +7,14 @@ module Ci
DEFAULT_STATUS = 'created'
BLOCKED_STATUS = %w[manual scheduled].freeze
AVAILABLE_STATUSES = %w[created waiting_for_resource preparing pending running success failed canceled skipped manual scheduled].freeze
# TODO: replace STARTED_STATUSES with data from BUILD_STARTED_RUNNING_STATUSES in https://gitlab.com/gitlab-org/gitlab/-/issues/273378
# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82149#note_865508501
BUILD_STARTED_RUNNING_STATUSES = %w[running success failed].freeze
STARTED_STATUSES = %w[running success failed skipped manual scheduled].freeze
STARTED_STATUSES = %w[running success failed].freeze
ACTIVE_STATUSES = %w[waiting_for_resource preparing pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
ORDERED_STATUSES = %w[failed preparing pending running waiting_for_resource manual scheduled canceled success skipped created].freeze
PASSED_WITH_WARNINGS_STATUSES = %w[failed canceled].to_set.freeze
EXCLUDE_IGNORED_STATUSES = %w[manual failed canceled].to_set.freeze
CANCELABLE_STATUSES = %w[running waiting_for_resource preparing pending created scheduled].freeze
ALIVE_STATUSES = (ACTIVE_STATUSES + ['created']).freeze
CANCELABLE_STATUSES = (ALIVE_STATUSES + ['scheduled']).freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
failed: 4, canceled: 5, skipped: 6, manual: 7,
scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze
@ -78,8 +76,8 @@ module Ci
scope :skipped, -> { with_status(:skipped) }
scope :manual, -> { with_status(:manual) }
scope :scheduled, -> { with_status(:scheduled) }
scope :alive, -> { with_status(:created, :waiting_for_resource, :preparing, :pending, :running) }
scope :alive_or_scheduled, -> { with_status(:created, :waiting_for_resource, :preparing, :pending, :running, :scheduled) }
scope :alive, -> { with_status(*ALIVE_STATUSES) }
scope :alive_or_scheduled, -> { with_status(*klass::CANCELABLE_STATUSES) }
scope :created_or_pending, -> { with_status(:created, :pending) }
scope :running_or_pending, -> { with_status(:running, :pending) }
scope :finished, -> { with_status(:success, :failed, :canceled) }
@ -98,7 +96,7 @@ module Ci
end
def started?
STARTED_STATUSES.include?(status) && started_at
STARTED_STATUSES.include?(status) && !!started_at
end
def active?

View File

@ -13,7 +13,6 @@ class Integration < ApplicationRecord
include IgnorableColumns
extend ::Gitlab::Utils::Override
ignore_column :template, remove_with: '15.0', remove_after: '2022-04-22'
ignore_column :type, remove_with: '15.0', remove_after: '2022-04-22'
ignore_column :properties, remove_with: '15.1', remove_after: '2022-05-22'

View File

@ -3,4 +3,5 @@
class AwardEmojiEntity < Grape::Entity
expose :name
expose :user, using: API::Entities::UserSafe
expose :url
end

View File

@ -1,9 +1,3 @@
- if @teams_error_message
= content_for :flash_message do
= render Pajamas::AlertComponent.new(variant: :danger) do
.gl-alert-body
= @teams_error_message
%p
You arent a member of any team on the Mattermost instance at
%strong= Gitlab.config.mattermost.host

View File

@ -1,10 +1,20 @@
- @body_class = 'card-content'
- add_to_breadcrumbs _('Integrations'), scoped_integrations_path(project: @project, group: @group)
- add_to_breadcrumbs @integration.title, scoped_edit_integration_path(@integration, project: @project, group: @group)
- breadcrumb_title _('New')
- page_title @integration.title, _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
.service-installation
.inline.float-right
- if @teams_error_message
= render Pajamas::AlertComponent.new(variant: :danger) do
.gl-alert-body
= @teams_error_message
%h3
Install Mattermost Command
.gl-float-right
= custom_icon('mattermost_logo', size: 48)
%h3 Install Mattermost Command
- if @teams.empty?
= render 'no_teams'
- else
= render 'team_selection'
- if @teams.empty?
= render 'no_teams'
- else
= render 'team_selection'

View File

@ -47,12 +47,12 @@ module BulkImports
end
if ndjson_pipeline?(pipeline_tracker)
status = ExportStatus.new(pipeline_tracker, pipeline_tracker.pipeline_class.relation)
export_status = ExportStatus.new(pipeline_tracker, pipeline_tracker.pipeline_class.relation)
raise(Pipeline::ExpiredError, 'Pipeline timeout') if job_timeout?(pipeline_tracker)
raise(Pipeline::FailedError, status.error) if status.failed?
raise(Pipeline::FailedError, export_status.error) if export_status.failed?
return reenqueue(pipeline_tracker) if status.started?
return reenqueue(pipeline_tracker) if export_status.started?
end
pipeline_tracker.update!(status_event: 'start', jid: jid)

View File

@ -0,0 +1,8 @@
---
name: container_registry_migration_phase2_capacity_5
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85908
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
milestone: '15.0'
type: development
group: group::package
default_enabled: false

View File

@ -3,7 +3,10 @@
class AddViewForPerTableAutovacuumStatus < Gitlab::Database::Migration[1.0]
def up
execute <<~SQL
CREATE OR REPLACE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS SETOF pg_catalog.pg_stat_activity AS
DROP VIEW IF EXISTS postgres_autovacuum_activity;
DROP FUNCTION IF EXISTS postgres_pg_stat_activity_autovacuum;
CREATE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS SETOF pg_catalog.pg_stat_activity AS
$$
SELECT *
FROM pg_stat_activity

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddMaxSeatsUsedChangedAtToGitlabSubscriptions < Gitlab::Database::Migration[2.0]
def change
add_column :gitlab_subscriptions, :max_seats_used_changed_at, :datetime_with_timezone
end
end

View File

@ -6,7 +6,7 @@ class FixViewForPerTableAutovacuumStatus < Gitlab::Database::Migration[2.0]
DROP VIEW IF EXISTS postgres_autovacuum_activity;
DROP FUNCTION IF EXISTS postgres_pg_stat_activity_autovacuum;
CREATE OR REPLACE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS TABLE(query text, query_start timestamptz) AS
CREATE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS TABLE(query text, query_start timestamptz) AS
$$
SELECT query, query_start
FROM pg_stat_activity
@ -41,7 +41,7 @@ class FixViewForPerTableAutovacuumStatus < Gitlab::Database::Migration[2.0]
DROP VIEW IF EXISTS postgres_autovacuum_activity;
DROP FUNCTION IF EXISTS postgres_pg_stat_activity_autovacuum;
CREATE OR REPLACE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS SETOF pg_catalog.pg_stat_activity AS
CREATE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS SETOF pg_catalog.pg_stat_activity AS
$$
SELECT *
FROM pg_stat_activity

View File

@ -0,0 +1 @@
41913029290e231d17f108fadf62e629b8919f5edf8854a4a7ae92e233329af3

View File

@ -15539,6 +15539,7 @@ CREATE TABLE gitlab_subscriptions (
seats_in_use integer DEFAULT 0 NOT NULL,
seats_owed integer DEFAULT 0 NOT NULL,
trial_extension_type smallint,
max_seats_used_changed_at timestamp with time zone,
CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL))
);

View File

@ -17907,10 +17907,11 @@ Values for sorting runners.
| Value | Description |
| ----- | ----------- |
| <a id="cirunnerupgradestatustypeavailable"></a>`AVAILABLE` | An update is available for the runner. |
| <a id="cirunnerupgradestatustypeinvalid"></a>`INVALID` | The runner version is invalid. |
| <a id="cirunnerupgradestatustypenot_available"></a>`NOT_AVAILABLE` | An update is not available for the runner. |
| <a id="cirunnerupgradestatustyperecommended"></a>`RECOMMENDED` | An update is available and recommended for the runner. |
| <a id="cirunnerupgradestatustypeavailable"></a>`AVAILABLE` | Upgrade is available for the runner. |
| <a id="cirunnerupgradestatustypeinvalid"></a>`INVALID` | Runner version is not valid. |
| <a id="cirunnerupgradestatustypenot_available"></a>`NOT_AVAILABLE` | Upgrade is not available for the runner. |
| <a id="cirunnerupgradestatustyperecommended"></a>`RECOMMENDED` | Upgrade is available and recommended for the runner. |
| <a id="cirunnerupgradestatustypeunknown"></a>`UNKNOWN` | Upgrade status is unknown. |
### `CodeQualityDegradationSeverity`

View File

@ -302,6 +302,9 @@ globally or for individual jobs:
You can also use variables to configure how many times a runner
[attempts certain stages of job execution](#job-stages-attempts).
When using the Kubernetes executor, you can use variables to
[override Kubernetes CPU and memory allocations for requests and limits](https://docs.gitlab.com/runner/executors/kubernetes.html#overwriting-container-resources).
### Git strategy
> - Introduced in GitLab 8.9 as an experimental feature.

View File

@ -1,6 +1,6 @@
---
stage: Monitor
group: Respond
group: Observability
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---

View File

@ -52,6 +52,7 @@ module ContainerRegistry
#
return 25 if Feature.enabled?(:container_registry_migration_phase2_capacity_25)
return 10 if Feature.enabled?(:container_registry_migration_phase2_capacity_10)
return 5 if Feature.enabled?(:container_registry_migration_phase2_capacity_5)
return 2 if Feature.enabled?(:container_registry_migration_phase2_capacity_2)
return 1 if Feature.enabled?(:container_registry_migration_phase2_capacity_1)

View File

@ -6,10 +6,10 @@ module Gitlab
include Singleton
STATUSES = {
invalid: 'The runner version is invalid.',
not_available: 'An update is not available for the runner.',
available: 'An update is available for the runner.',
recommended: 'An update is available and recommended for the runner.'
invalid: 'Runner version is not valid.',
not_available: 'Upgrade is not available for the runner.',
available: 'Upgrade is available for the runner.',
recommended: 'Upgrade is available and recommended for the runner.'
}.freeze
def initialize

View File

@ -1,8 +1,12 @@
import { GlModal } from '@gitlab/ui';
import { nextTick } from 'vue';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { redirectTo } from '~/lib/utils/url_utility';
import ActionsCell from '~/jobs/components/table/cells/actions_cell.vue';
import eventHub from '~/jobs/components/table/event_hub';
import JobPlayMutation from '~/jobs/components/table/graphql/mutations/job_play.mutation.graphql';
import JobRetryMutation from '~/jobs/components/table/graphql/mutations/job_retry.mutation.graphql';
import JobUnscheduleMutation from '~/jobs/components/table/graphql/mutations/job_unschedule.mutation.graphql';
@ -15,11 +19,18 @@ import {
cannotRetryJob,
cannotPlayJob,
cannotPlayScheduledJob,
retryMutationResponse,
playMutationResponse,
cancelMutationResponse,
unscheduleMutationResponse,
} from '../../../mock_data';
jest.mock('~/lib/utils/url_utility');
Vue.use(VueApollo);
describe('Job actions cell', () => {
let wrapper;
let mutate;
const findRetryButton = () => wrapper.findByTestId('retry');
const findPlayButton = () => wrapper.findByTestId('play');
@ -31,29 +42,27 @@ describe('Job actions cell', () => {
const findModal = () => wrapper.findComponent(GlModal);
const MUTATION_SUCCESS = { data: { JobRetryMutation: { jobId: retryableJob.id } } };
const MUTATION_SUCCESS_UNSCHEDULE = {
data: { JobUnscheduleMutation: { jobId: scheduledJob.id } },
};
const MUTATION_SUCCESS_PLAY = { data: { JobPlayMutation: { jobId: playableJob.id } } };
const MUTATION_SUCCESS_CANCEL = { data: { JobCancelMutation: { jobId: cancelableJob.id } } };
const playMutationHandler = jest.fn().mockResolvedValue(playMutationResponse);
const retryMutationHandler = jest.fn().mockResolvedValue(retryMutationResponse);
const unscheduleMutationHandler = jest.fn().mockResolvedValue(unscheduleMutationResponse);
const cancelMutationHandler = jest.fn().mockResolvedValue(cancelMutationResponse);
const $toast = {
show: jest.fn(),
};
const createComponent = (jobType, mutationType = MUTATION_SUCCESS, props = {}) => {
mutate = jest.fn().mockResolvedValue(mutationType);
const createMockApolloProvider = (requestHandlers) => {
return createMockApollo(requestHandlers);
};
const createComponent = (jobType, requestHandlers, props = {}) => {
wrapper = shallowMountExtended(ActionsCell, {
propsData: {
job: jobType,
...props,
},
apolloProvider: createMockApolloProvider(requestHandlers),
mocks: {
$apollo: {
mutate,
},
$toast,
},
});
@ -101,23 +110,58 @@ describe('Job actions cell', () => {
});
it.each`
button | mutationResult | action | jobType | mutationFile
${findPlayButton} | ${MUTATION_SUCCESS_PLAY} | ${'play'} | ${playableJob} | ${JobPlayMutation}
${findRetryButton} | ${MUTATION_SUCCESS} | ${'retry'} | ${retryableJob} | ${JobRetryMutation}
${findCancelButton} | ${MUTATION_SUCCESS_CANCEL} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation}
`('performs the $action mutation', ({ button, mutationResult, jobType, mutationFile }) => {
createComponent(jobType, mutationResult);
button | action | jobType | mutationFile | handler | jobId
${findPlayButton} | ${'play'} | ${playableJob} | ${JobPlayMutation} | ${playMutationHandler} | ${playableJob.id}
${findRetryButton} | ${'retry'} | ${retryableJob} | ${JobRetryMutation} | ${retryMutationHandler} | ${retryableJob.id}
${findCancelButton} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation} | ${cancelMutationHandler} | ${cancelableJob.id}
`('performs the $action mutation', async ({ button, jobType, mutationFile, handler, jobId }) => {
createComponent(jobType, [[mutationFile, handler]]);
button().vm.$emit('click');
expect(mutate).toHaveBeenCalledWith({
mutation: mutationFile,
variables: {
id: jobType.id,
},
});
expect(handler).toHaveBeenCalledWith({ id: jobId });
});
it.each`
button | action | jobType | mutationFile | handler
${findUnscheduleButton} | ${'unschedule'} | ${scheduledJob} | ${JobUnscheduleMutation} | ${unscheduleMutationHandler}
${findCancelButton} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation} | ${cancelMutationHandler}
`(
'the mutation action $action emits the jobActionPerformed event',
async ({ button, jobType, mutationFile, handler }) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
createComponent(jobType, [[mutationFile, handler]]);
button().vm.$emit('click');
await waitForPromises();
expect(eventHub.$emit).toHaveBeenCalledWith('jobActionPerformed');
expect(redirectTo).not.toHaveBeenCalled();
},
);
it.each`
button | action | jobType | mutationFile | handler | redirectLink
${findPlayButton} | ${'play'} | ${playableJob} | ${JobPlayMutation} | ${playMutationHandler} | ${'/root/project/-/jobs/1986'}
${findRetryButton} | ${'retry'} | ${retryableJob} | ${JobRetryMutation} | ${retryMutationHandler} | ${'/root/project/-/jobs/1985'}
`(
'the mutation action $action redirects to the job',
async ({ button, jobType, mutationFile, handler, redirectLink }) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
createComponent(jobType, [[mutationFile, handler]]);
button().vm.$emit('click');
await waitForPromises();
expect(redirectTo).toHaveBeenCalledWith(redirectLink);
expect(eventHub.$emit).not.toHaveBeenCalled();
},
);
it.each`
button | action | jobType
${findPlayButton} | ${'play'} | ${playableJob}
@ -152,20 +196,17 @@ describe('Job actions cell', () => {
});
it('unschedules a job', () => {
createComponent(scheduledJob, MUTATION_SUCCESS_UNSCHEDULE);
createComponent(scheduledJob, [[JobUnscheduleMutation, unscheduleMutationHandler]]);
findUnscheduleButton().vm.$emit('click');
expect(mutate).toHaveBeenCalledWith({
mutation: JobUnscheduleMutation,
variables: {
id: scheduledJob.id,
},
expect(unscheduleMutationHandler).toHaveBeenCalledWith({
id: scheduledJob.id,
});
});
it('shows the play job confirmation modal', async () => {
createComponent(scheduledJob, MUTATION_SUCCESS);
createComponent(scheduledJob);
findPlayScheduledJobButton().vm.$emit('click');

View File

@ -1928,3 +1928,75 @@ export const CIJobConnectionExistingCache = {
};
export const mockFailedSearchToken = { type: 'status', value: { data: 'FAILED', operator: '=' } };
export const retryMutationResponse = {
data: {
jobRetry: {
job: {
__typename: 'CiJob',
id: '"gid://gitlab/Ci::Build/1985"',
detailedStatus: {
detailsPath: '/root/project/-/jobs/1985',
id: 'pending-1985-1985',
__typename: 'DetailedStatus',
},
},
errors: [],
__typename: 'JobRetryPayload',
},
},
};
export const playMutationResponse = {
data: {
jobPlay: {
job: {
__typename: 'CiJob',
id: '"gid://gitlab/Ci::Build/1986"',
detailedStatus: {
detailsPath: '/root/project/-/jobs/1986',
id: 'pending-1986-1986',
__typename: 'DetailedStatus',
},
},
errors: [],
__typename: 'JobRetryPayload',
},
},
};
export const cancelMutationResponse = {
data: {
jobCancel: {
job: {
__typename: 'CiJob',
id: '"gid://gitlab/Ci::Build/1987"',
detailedStatus: {
detailsPath: '/root/project/-/jobs/1987',
id: 'pending-1987-1987',
__typename: 'DetailedStatus',
},
},
errors: [],
__typename: 'JobRetryPayload',
},
},
};
export const unscheduleMutationResponse = {
data: {
jobUnschedule: {
job: {
__typename: 'CiJob',
id: '"gid://gitlab/Ci::Build/1988"',
detailedStatus: {
detailsPath: '/root/project/-/jobs/1988',
id: 'pending-1988-1988',
__typename: 'DetailedStatus',
},
},
errors: [],
__typename: 'JobRetryPayload',
},
},
};

View File

@ -7,7 +7,7 @@ RSpec.describe Types::Ci::RunnerUpgradeStatusTypeEnum do
it 'exposes all upgrade status values' do
expect(described_class.values.keys).to eq(
::Gitlab::Ci::RunnerUpgradeCheck::STATUSES.map { |sym, _| sym.to_s.upcase }
['UNKNOWN'] + ::Gitlab::Ci::RunnerUpgradeCheck::STATUSES.map { |sym, _| sym.to_s.upcase }
)
end
end

View File

@ -58,23 +58,17 @@ RSpec.describe ContainerRegistry::Migration do
describe '.capacity' do
subject { described_class.capacity }
where(:ff_1_enabled, :ff_2_enabled, :ff_10_enabled, :ff_25_enabled, :expected_result) do
false | false | false | false | 0
true | false | false | false | 1
false | true | false | false | 2
true | true | false | false | 2
false | true | true | false | 10
false | true | true | true | 25
false | true | false | true | 25
true | true | false | true | 25
true | true | true | true | 25
true | true | true | false | 10
true | false | true | false | 10
true | false | true | true | 25
false | false | true | false | 10
false | false | true | true | 25
false | false | false | true | 25
true | false | false | true | 25
where(:ff_1_enabled, :ff_2_enabled, :ff_5_enabled, :ff_10_enabled, :ff_25_enabled, :expected_result) do
false | false | false | false | false | 0
true | false | false | false | false | 1
false | true | false | false | false | 2
true | true | false | false | false | 2
false | false | true | false | false | 5
true | true | true | false | false | 5
false | false | false | true | false | 10
true | true | true | true | false | 10
false | false | false | false | true | 25
true | true | true | true | true | 25
end
with_them do
@ -82,6 +76,7 @@ RSpec.describe ContainerRegistry::Migration do
stub_feature_flags(
container_registry_migration_phase2_capacity_1: ff_1_enabled,
container_registry_migration_phase2_capacity_2: ff_2_enabled,
container_registry_migration_phase2_capacity_5: ff_5_enabled,
container_registry_migration_phase2_capacity_10: ff_10_enabled,
container_registry_migration_phase2_capacity_25: ff_25_enabled
)

View File

@ -106,7 +106,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines do
create(:ci_build, :interruptible, :running, pipeline: child_pipeline)
end
not_started_statuses = Ci::HasStatus::AVAILABLE_STATUSES - Ci::HasStatus::BUILD_STARTED_RUNNING_STATUSES
not_started_statuses = Ci::HasStatus::AVAILABLE_STATUSES - Ci::HasStatus::STARTED_STATUSES
context 'when the jobs are cancelable' do
cancelable_not_started_statuses = Set.new(not_started_statuses).intersection(Ci::HasStatus::CANCELABLE_STATUSES)
cancelable_not_started_statuses.each do |status|

View File

@ -142,6 +142,26 @@ RSpec.describe CommitStatus do
end
end
describe '.cancelable' do
subject { described_class.cancelable }
%i[running pending waiting_for_resource preparing created scheduled].each do |status|
context "when #{status} commit status" do
let!(:commit_status) { create(:commit_status, status, pipeline: pipeline) }
it { is_expected.to contain_exactly(commit_status) }
end
end
%i[failed success skipped canceled manual].each do |status|
context "when #{status} commit status" do
let!(:commit_status) { create(:commit_status, status, pipeline: pipeline) }
it { is_expected.to be_empty }
end
end
end
describe '#started?' do
subject { commit_status.started? }
@ -150,26 +170,28 @@ RSpec.describe CommitStatus do
commit_status.started_at = nil
end
it { is_expected.to be_falsey }
it { is_expected.to be(false) }
end
%w[running success failed].each do |status|
context "if commit status is #{status}" do
before do
commit_status.status = status
end
context 'with started_at' do
described_class::STARTED_STATUSES.each do |status|
context "if commit status is #{status}" do
before do
commit_status.status = status
end
it { is_expected.to be_truthy }
it { is_expected.to eq(true) }
end
end
end
%w[pending canceled].each do |status|
context "if commit status is #{status}" do
before do
commit_status.status = status
(described_class::AVAILABLE_STATUSES - described_class::STARTED_STATUSES).each do |status|
context "if commit status is #{status}" do
before do
commit_status.status = status
end
it { is_expected.to be(false) }
end
it { is_expected.to be_falsey }
end
end
end

View File

@ -27,10 +27,6 @@ RSpec.describe 'Query.runner(id)' do
let_it_be(:active_project_runner) { create(:ci_runner, :project) }
before do
allow(Gitlab::Ci::RunnerUpgradeCheck.instance).to receive(:check_runner_upgrade_status)
end
shared_examples 'runner details fetch' do
let(:query) do
wrap_fields(query_graphql_path(query_path, all_graphql_fields_for('CiRunner')))

View File

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::JobEntity do
let(:user) { create(:user) }
let(:job) { create(:ci_build) }
let(:job) { create(:ci_build, :running) }
let(:project) { job.project }
let(:request) { double('request') }
@ -21,6 +21,11 @@ RSpec.describe Ci::JobEntity do
subject { entity.as_json }
it 'contains started' do
expect(subject).to include(:started)
expect(subject[:started]).to eq(true)
end
it 'contains complete to indicate if a pipeline is completed' do
expect(subject).to include(:complete)
end

View File

@ -5,8 +5,11 @@ require 'spec_helper'
RSpec.describe DiscussionEntity do
include RepoHelpers
let(:user) { create(:user) }
let(:note) { create(:discussion_note_on_merge_request) }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let(:note) { create(:discussion_note_on_merge_request, project: project) }
let(:discussion) { note.discussion }
let(:request) { double('request', note_entity: ProjectNoteEntity) }
let(:controller) { double('controller') }
@ -50,10 +53,15 @@ RSpec.describe DiscussionEntity do
.to match_schema('entities/note_user_entity')
end
it 'exposes the url for custom award emoji' do
custom_emoji = create(:custom_emoji, group: group)
create(:award_emoji, awardable: note, name: custom_emoji.name)
expect(subject[:notes].last[:award_emoji].first.keys).to include(:url)
end
context 'when is LegacyDiffDiscussion' do
let(:project) { create(:project) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:discussion) { create(:legacy_diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion }
let(:discussion) { create(:legacy_diff_note_on_merge_request, noteable: note.noteable, project: project).to_discussion }
it 'exposes correct attributes' do
expect(subject.keys.sort).to include(