Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5c93f783e8
commit
d1d62516aa
|
|
@ -37,4 +37,5 @@ If you have questions about the patch release process, please:
|
|||
[patch release runbook for engineers and maintainers]: https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/patch/engineers.md
|
||||
[`#releases`]: https://gitlab.slack.com/archives/C0XM5UU6B
|
||||
|
||||
/label ~backport
|
||||
/assign me
|
||||
|
|
|
|||
|
|
@ -16,27 +16,6 @@ RSpec/ChangeByZero:
|
|||
- 'ee/spec/requests/api/graphql/mutations/work_items/create_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/work_items/linked_items/add_spec.rb'
|
||||
- 'ee/spec/requests/api/merge_request_approvals_spec.rb'
|
||||
- 'ee/spec/services/app_sec/dast/profiles/create_service_spec.rb'
|
||||
- 'ee/spec/services/application_settings/update_service_spec.rb'
|
||||
- 'ee/spec/services/approval_rules/user_rules_destroy_service_spec.rb'
|
||||
- 'ee/spec/services/ci/delete_project_subscription_service_spec.rb'
|
||||
- 'ee/spec/services/ci/minutes/update_project_and_namespace_usage_service_spec.rb'
|
||||
- 'ee/spec/services/ee/ci/update_instance_variables_service_spec.rb'
|
||||
- 'ee/spec/services/ee/issues/create_service_spec.rb'
|
||||
- 'ee/spec/services/ee/members/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/geo/container_repository_registry_removal_service_spec.rb'
|
||||
- 'ee/spec/services/geo/file_registry_removal_service_spec.rb'
|
||||
- 'ee/spec/services/geo/metrics_update_service_spec.rb'
|
||||
- 'ee/spec/services/gitlab_subscriptions/add_on_purchases/gitlab_com/provision_service_spec.rb'
|
||||
- 'ee/spec/services/push_rules/create_or_update_service_spec.rb'
|
||||
- 'ee/spec/services/registrations/import_namespace_create_service_spec.rb'
|
||||
- 'ee/spec/services/registrations/standard_namespace_create_service_spec.rb'
|
||||
- 'ee/spec/services/sbom/ingestion/tasks/ingest_sources_spec.rb'
|
||||
- 'ee/spec/services/security/ingestion/tasks/ingest_cvs_security_scanners_spec.rb'
|
||||
- 'ee/spec/services/security/orchestration/create_bot_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/security_finding/create_merge_request_service_spec.rb'
|
||||
- 'ee/spec/services/work_items/legacy_epics/related_epic_links/create_service_spec.rb'
|
||||
- 'spec/controllers/admin/clusters_controller_spec.rb'
|
||||
- 'spec/controllers/groups/boards_controller_spec.rb'
|
||||
- 'spec/controllers/groups/clusters_controller_spec.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
55f4fb94e39f60e1d4c76deac5d6f20c6202c68f
|
||||
3292fb4882db9208602f3cd2cc61ba56bce8e6a9
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { GlPopover, GlFormInputGroup } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -9,13 +10,14 @@ export default {
|
|||
GlFormInputGroup,
|
||||
ClipboardButton,
|
||||
},
|
||||
inject: ['pushToCreateProjectCommand', 'projectHelpPath'],
|
||||
inject: ['pushToCreateProjectCommand'],
|
||||
props: {
|
||||
target: {
|
||||
type: [Function, HTMLElement],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
helpPath: helpPagePath('topics/git/project.md'),
|
||||
i18n: {
|
||||
clipboardButtonTitle: __('Copy command'),
|
||||
commandInputAriaLabel: __('Push project from command line'),
|
||||
|
|
@ -55,12 +57,9 @@ export default {
|
|||
</gl-form-input-group>
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
:href="`${projectHelpPath}#create-a-new-project-with-git-push`"
|
||||
class="gl-text-sm"
|
||||
target="_blank"
|
||||
>{{ $options.i18n.helpLinkText }}</a
|
||||
>
|
||||
<a :href="$options.helpPath" class="gl-text-sm" target="_blank">{{
|
||||
$options.i18n.helpLinkText
|
||||
}}</a>
|
||||
</p>
|
||||
</gl-popover>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ export function initNewProjectCreation() {
|
|||
|
||||
const {
|
||||
pushToCreateProjectCommand,
|
||||
projectHelpPath,
|
||||
newProjectGuidelines,
|
||||
hasErrors,
|
||||
isCiCdAvailable,
|
||||
|
|
@ -39,7 +38,6 @@ export function initNewProjectCreation() {
|
|||
};
|
||||
|
||||
const provide = {
|
||||
projectHelpPath,
|
||||
pushToCreateProjectCommand,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { GlFormGroup, GlLink, GlFormInputGroup } from '@gitlab/ui';
|
||||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -13,7 +14,8 @@ export default {
|
|||
directives: {
|
||||
SafeHtml,
|
||||
},
|
||||
inject: ['projectHelpPath', 'pushToCreateProjectCommand'],
|
||||
helpPath: helpPagePath('topics/git/project.md'),
|
||||
inject: ['pushToCreateProjectCommand'],
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -30,7 +32,7 @@ export default {
|
|||
data-testid="new-project-with-command"
|
||||
>
|
||||
<template #label-description>
|
||||
<gl-link :href="`${projectHelpPath}#create-a-new-project-with-git-push`" target="_blank">
|
||||
<gl-link :href="$options.helpPath" target="_blank">
|
||||
{{ s__('ProjectNew|What does this command do?') }}
|
||||
</gl-link>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ export function initNewProjectForm() {
|
|||
projectsUrl,
|
||||
parentGroupUrl,
|
||||
parentGroupName,
|
||||
projectHelpPath,
|
||||
isCiCdAvailable,
|
||||
canImportProjects,
|
||||
importSourcesEnabled,
|
||||
|
|
@ -64,7 +63,6 @@ export function initNewProjectForm() {
|
|||
projectsUrl,
|
||||
parentGroupUrl,
|
||||
parentGroupName,
|
||||
projectHelpPath,
|
||||
trackLabel,
|
||||
isCiCdAvailable: parseBoolean(isCiCdAvailable),
|
||||
importSourcesEnabled: parseBoolean(importSourcesEnabled),
|
||||
|
|
|
|||
|
|
@ -23,9 +23,7 @@ export const formatListBoxItems = ({ branches, tags, commits, selectedRef }) =>
|
|||
const addToFinalResult = (items, header, shouldFilter = true) => {
|
||||
if (!items) return;
|
||||
const filteredItems =
|
||||
shouldFilter && selectedRef
|
||||
? items.filter((item) => item.value !== selectedRef.value)
|
||||
: items; // Filter out the selected
|
||||
shouldFilter && selectedRef ? items.filter((item) => item.name !== selectedRef.name) : items; // Filter out the selected
|
||||
|
||||
if (!filteredItems?.length) return;
|
||||
listBoxItems.push({
|
||||
|
|
|
|||
|
|
@ -98,8 +98,7 @@ module Ci
|
|||
next unless result
|
||||
|
||||
if result.valid?
|
||||
@metrics.register_success(result.build_presented)
|
||||
@metrics.observe_queue_depth(:found, depth)
|
||||
track_success(result, depth)
|
||||
|
||||
return result # rubocop:disable Cop/AvoidReturnFromBlocks
|
||||
else
|
||||
|
|
@ -109,10 +108,7 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
@metrics.increment_queue_operation(:queue_conflict) unless valid
|
||||
@metrics.observe_queue_depth(:conflict, depth) unless valid
|
||||
@metrics.observe_queue_depth(:not_found, depth) if valid
|
||||
@metrics.register_failure
|
||||
track_conflict(depth, valid)
|
||||
|
||||
Result.new(nil, nil, nil, valid)
|
||||
end
|
||||
|
|
@ -308,14 +304,40 @@ module Ci
|
|||
track_exception_for_build(ex, build)
|
||||
end
|
||||
|
||||
def track_success(result, depth)
|
||||
@metrics.register_success(result.build_presented)
|
||||
@metrics.observe_queue_depth(:found, depth)
|
||||
rescue StandardError => ex
|
||||
# We should know about any errors during tracking but we don't want them to prevent
|
||||
# reporting a result to the runner
|
||||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
|
||||
ex, **build_tracking_data(result.build)
|
||||
)
|
||||
end
|
||||
|
||||
def track_conflict(depth, valid)
|
||||
@metrics.increment_queue_operation(:queue_conflict) unless valid
|
||||
@metrics.observe_queue_depth(:conflict, depth) unless valid
|
||||
@metrics.observe_queue_depth(:not_found, depth) if valid
|
||||
@metrics.register_failure
|
||||
rescue StandardError => ex
|
||||
# We should know about any errors during tracking but we don't want them to prevent
|
||||
# reporting a result to the runner
|
||||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(ex)
|
||||
end
|
||||
|
||||
def track_exception_for_build(ex, build)
|
||||
Gitlab::ErrorTracking.track_exception(ex,
|
||||
Gitlab::ErrorTracking.track_exception(ex, **build_tracking_data(build))
|
||||
end
|
||||
|
||||
def build_tracking_data(build)
|
||||
{
|
||||
build_id: build.id,
|
||||
build_name: build.name,
|
||||
build_stage: build.stage_name,
|
||||
pipeline_id: build.pipeline_id,
|
||||
project_id: build.project_id
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
def pre_assign_runner_checks
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
= content_for :meta_tags do
|
||||
%meta{ 'http-equiv': 'refresh', content: "3; url=#{@redirect_url}" }
|
||||
|
||||
.gl-text-center.gl-max-w-62.gl-mx-auto{ data: local_assigns.fetch(:data, {}) }
|
||||
.svg-content.svg-80
|
||||
= image_tag 'illustrations/success-sm.svg'
|
||||
%h2
|
||||
= s_('IdentityVerification|Verification successful')
|
||||
%p.gl-pt-2
|
||||
- redirect_url_start = '<a href="%{url}">'.html_safe % { url: @redirect_url }
|
||||
- redirect_url_end = '</a>'.html_safe
|
||||
= html_escape(s_("IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}.")) % { redirect_url_start: redirect_url_start, redirect_url_end: redirect_url_end }
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- @html_class = 'gl-dark'
|
||||
= content_for :meta_tags do
|
||||
%meta{ 'http-equiv': 'refresh', content: "3; url=#{@redirect_url}" }
|
||||
|
||||
.gl-text-center.gl-max-w-xl.gl-mx-auto.gl-bg-subtle.gl-rounded-lg.gl-py-4{ data: local_assigns.fetch(:data, {}) }
|
||||
.svg-content.svg-80
|
||||
= image_tag 'illustrations/secure-sm.svg'
|
||||
%h2
|
||||
= s_('IdentityVerification|Verification successful')
|
||||
%p.gl-pt-2.gl-px-6
|
||||
- redirect_url_start = '<a href="%{url}">'.html_safe % { url: @redirect_url }
|
||||
- redirect_url_end = '</a>'.html_safe
|
||||
= html_escape(s_("IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}.")) % { redirect_url_start: redirect_url_start, redirect_url_end: redirect_url_end }
|
||||
|
|
@ -1,12 +1,8 @@
|
|||
= content_for :meta_tags do
|
||||
%meta{ 'http-equiv': 'refresh', content: "3; url=#{@redirect_url}" }
|
||||
|
||||
.gl-text-center.gl-max-w-62.gl-mx-auto{ data: local_assigns.fetch(:data, {}) }
|
||||
.svg-content.svg-80
|
||||
= image_tag 'illustrations/success-sm.svg'
|
||||
%h2
|
||||
= s_('IdentityVerification|Verification successful')
|
||||
%p.gl-pt-2
|
||||
- redirect_url_start = '<a href="%{url}"">'.html_safe % { url: @redirect_url }
|
||||
- redirect_url_end = '</a>'.html_safe
|
||||
= html_escape(s_("IdentityVerification|Your account has been successfully verified. You'll be redirected to your account in just a moment. You can also %{redirect_url_start}refresh the page%{redirect_url_end}.")) % { redirect_url_start: redirect_url_start, redirect_url_end: redirect_url_end }
|
||||
- if current_user.try(:onboarding_status_initial_registration_type) != "trial"
|
||||
= render 'devise/sessions/successful_verification', local_assigns
|
||||
- else
|
||||
- experiment(:lightweight_trial_registration_redesign, actor: current_user) do |e|
|
||||
- e.control do
|
||||
= render 'devise/sessions/successful_verification', local_assigns
|
||||
- e.candidate do
|
||||
= render 'devise/sessions/successful_verification_lightweight', local_assigns
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
projects_url: dashboard_projects_url,
|
||||
parent_group_url: @project.parent && group_url(@project.parent),
|
||||
parent_group_name: @project.parent&.name,
|
||||
project_help_path: help_page_path("user/project/_index.md"),
|
||||
is_ci_cd_available: remote_mirror_setting_enabled?.to_s,
|
||||
can_import_projects: params[:namespace_id].presence ? current_user.can?(:import_projects, @namespace).to_s : 'true',
|
||||
import_sources_enabled: import_sources_enabled?.to_s,
|
||||
|
|
@ -56,7 +55,6 @@
|
|||
has_errors: @project.errors.any?.to_s,
|
||||
new_project_guidelines: brand_new_project_guidelines,
|
||||
push_to_create_project_command: push_to_create_project_command,
|
||||
project_help_path: help_page_path("user/project/_index.md"),
|
||||
root_path: root_path,
|
||||
parent_group_url: @project.parent && group_url(@project.parent),
|
||||
parent_group_name: @project.parent&.name,
|
||||
|
|
|
|||
|
|
@ -28,17 +28,24 @@ module Gitlab
|
|||
feature_category :continuous_integration
|
||||
urgency :throttled
|
||||
idempotent!
|
||||
deduplicate :until_executed
|
||||
deduplicate :until_executing
|
||||
sidekiq_options retry: true
|
||||
|
||||
def perform_work
|
||||
return unless ::Gitlab.com_except_jh? # rubocop:disable Gitlab/AvoidGitlabInstanceChecks -- we need to check on which instance this happens
|
||||
|
||||
ID_RANGES.each do |model, attributes|
|
||||
min_id = start_id(model)
|
||||
last_id = flush_stale_for_model(model, min_id, attributes[:end_id])
|
||||
# we need to add +1 here, because otherwise, we'd process the last record twice.
|
||||
update_start_id(model, last_id + 1)
|
||||
# Process up to 100 batches per job execution as a compromise between
|
||||
# performance (avoiding too many small jobs) and efficiency (preventing
|
||||
# jobs from running too long and potentially timing out)
|
||||
100.times do
|
||||
ID_RANGES.each do |model, attributes|
|
||||
min_id = start_id(model)
|
||||
remaining_work = [(attributes[:end_id] - min_id), 0].max
|
||||
last_id = flush_stale_for_model(model, min_id, attributes[:end_id])
|
||||
# we need to add +1 here, because otherwise, we'd process the last record twice.
|
||||
update_start_id(model, last_id + 1)
|
||||
return if remaining_work == 0 # rubocop:disable Lint/NonLocalExitFromIterator -- return if we don't have anymore work to do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/538388
|
|||
milestone: '18.0'
|
||||
group: group::authentication
|
||||
type: beta
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
|||
|
|
@ -173,7 +173,9 @@ Doorkeeper.configure do
|
|||
expires_in: configuration.device_code_expires_in,
|
||||
scopes: scopes.to_s,
|
||||
user_code: generate_user_code,
|
||||
organization_id: Organizations::Organization::DEFAULT_ORGANIZATION_ID
|
||||
# This will result in a fallback to Default Organizzation
|
||||
# OAuth device grant flow doesn't support other organizations yet
|
||||
organization_id: Gitlab::Current::Organization.new.organization.id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Tracking
|
||||
class AiTracking
|
||||
def self.track_event(*args, **kwargs)
|
||||
new.track_event(*args, **kwargs)
|
||||
end
|
||||
|
||||
def self.track_user_activity(*args)
|
||||
new.track_user_activity(*args)
|
||||
end
|
||||
|
||||
def track_event(_event_name, **_context_hash)
|
||||
# no-op for CE
|
||||
end
|
||||
|
||||
def track_user_activity(_user)
|
||||
# no-op for CE
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Tracking::AiTracking.prepend_mod
|
||||
|
|
@ -8,7 +8,6 @@ describe('New project push tip popover', () => {
|
|||
let wrapper;
|
||||
const targetId = 'target';
|
||||
const pushToCreateProjectCommand = 'command';
|
||||
const projectHelpPath = 'path';
|
||||
|
||||
const findPopover = () => wrapper.findComponent(GlPopover);
|
||||
const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
|
||||
|
|
@ -27,7 +26,6 @@ describe('New project push tip popover', () => {
|
|||
},
|
||||
provide: {
|
||||
pushToCreateProjectCommand,
|
||||
projectHelpPath,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -74,8 +72,6 @@ describe('New project push tip popover', () => {
|
|||
});
|
||||
|
||||
it('displays a link to open the push command help page reference', () => {
|
||||
expect(findHelpLink().attributes().href).toBe(
|
||||
`${projectHelpPath}#create-a-new-project-with-git-push`,
|
||||
);
|
||||
expect(findHelpLink().attributes().href).toBe('/help/topics/git/project.md');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import {
|
|||
describe('formatListBoxItems', () => {
|
||||
const FORMATTED_SELECTED = {
|
||||
text: DEFAULT_I18N.selected,
|
||||
options: [{ text: 'main', value: 'main', default: undefined, protected: undefined }],
|
||||
options: [{ text: 'selected', value: 'selected', default: undefined, protected: undefined }],
|
||||
};
|
||||
const selected = { name: 'main', value: 'main' };
|
||||
const selected = { name: 'selected', value: 'selected' };
|
||||
|
||||
it.each`
|
||||
branches | tags | commits | selectedRef | expectedResult
|
||||
|
|
|
|||
|
|
@ -144,6 +144,12 @@ RSpec.describe Gitlab::Tracking::EventDefinition, feature_category: :service_pin
|
|||
end
|
||||
|
||||
describe '.extra_trackers' do
|
||||
let(:dummy_tracking_class) { Class.new }
|
||||
|
||||
before do
|
||||
stub_const('Gitlab::Tracking::DummyTracking', dummy_tracking_class)
|
||||
end
|
||||
|
||||
it 'returns an empty hash when no extra tracking classes are set' do
|
||||
expect(described_class.new(nil, {}).extra_trackers).to eq([])
|
||||
end
|
||||
|
|
@ -153,7 +159,7 @@ RSpec.describe Gitlab::Tracking::EventDefinition, feature_category: :service_pin
|
|||
extra_trackers:
|
||||
[
|
||||
{
|
||||
tracking_class: 'Gitlab::Tracking::AiTracking',
|
||||
tracking_class: 'Gitlab::Tracking::DummyTracking',
|
||||
protected_properties: { prop: { description: 'description' } }
|
||||
}
|
||||
]
|
||||
|
|
@ -161,7 +167,7 @@ RSpec.describe Gitlab::Tracking::EventDefinition, feature_category: :service_pin
|
|||
config = attributes.merge(extra_trackers)
|
||||
|
||||
expect(described_class.new(nil, config).extra_trackers)
|
||||
.to eq({ Gitlab::Tracking::AiTracking => { protected_properties: [:prop] } })
|
||||
.to eq({ dummy_tracking_class => { protected_properties: [:prop] } })
|
||||
end
|
||||
|
||||
it 'returns the hash with extra tracking class with empty array when props are not set' do
|
||||
|
|
@ -169,14 +175,14 @@ RSpec.describe Gitlab::Tracking::EventDefinition, feature_category: :service_pin
|
|||
extra_trackers:
|
||||
[
|
||||
{
|
||||
tracking_class: 'Gitlab::Tracking::AiTracking'
|
||||
tracking_class: 'Gitlab::Tracking::DummyTracking'
|
||||
}
|
||||
]
|
||||
}
|
||||
config = attributes.merge(extra_trackers)
|
||||
|
||||
expect(described_class.new(nil, config).extra_trackers)
|
||||
.to eq({ Gitlab::Tracking::AiTracking => { protected_properties: [] } })
|
||||
.to eq({ dummy_tracking_class => { protected_properties: [] } })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do
|
|||
let_it_be(:project, reload: true) { create(:project) }
|
||||
let_it_be(:personal_access_token) { create(:personal_access_token) }
|
||||
let_it_be(:job) { create(:ci_build, :running, user: personal_access_token.user, project: project) }
|
||||
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
|
||||
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
|
||||
let_it_be(:deploy_token) do
|
||||
create(:deploy_token, read_package_registry: true, write_package_registry: true, projects: [project])
|
||||
end
|
||||
|
||||
let_it_be(:another_project, reload: true) { create(:project) }
|
||||
let_it_be(:model) { create(:ml_models, user: project.owner, project: project) }
|
||||
let_it_be(:model_version) { create(:ml_model_versions, :with_package, model: model, version: '0.1.0') }
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ require 'spec_helper'
|
|||
RSpec.describe 'OAuth tokens', feature_category: :system_access do
|
||||
include HttpBasicAuthHelpers
|
||||
|
||||
let_it_be(:organization) { create(:organization, :default) }
|
||||
let_it_be(:organization) { create(:organization) }
|
||||
|
||||
before do
|
||||
stub_current_organization(organization)
|
||||
end
|
||||
|
||||
context 'Resource Owner Password Credentials' do
|
||||
def request_oauth_token(user, headers = {}, password = user.password)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Gitlab OAuth2 Device Authorization Grant', feature_category: :system_access do
|
||||
let_it_be(:organization) { create(:organization, :default) }
|
||||
RSpec.describe 'Gitlab OAuth2 Device Authorization Grant', :with_current_organization, feature_category: :system_access do
|
||||
let_it_be(:organization) { current_organization }
|
||||
let_it_be(:application) { create(:oauth_application, redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', confidential: false) }
|
||||
let_it_be(:user) { create(:user, :with_namespace, organizations: [organization]) }
|
||||
let_it_be(:client_id) { application.uid }
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ module Ci
|
|||
let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
|
||||
let_it_be(:shared_runner) { create(:ci_runner, :instance) }
|
||||
let!(:project_runner) { create(:ci_runner, :project, projects: [project]) }
|
||||
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
|
||||
let_it_be_with_reload(:project_runner) { create(:ci_runner, :project, projects: [project]) }
|
||||
let_it_be_with_reload(:group_runner) { create(:ci_runner, :group, groups: [group]) }
|
||||
let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
|
||||
|
||||
describe '#execute' do
|
||||
|
|
@ -463,9 +463,11 @@ module Ci
|
|||
|
||||
context 'when first build is stalled' do
|
||||
before do
|
||||
allow_any_instance_of(described_class).to receive(:assign_runner!).and_call_original
|
||||
allow_any_instance_of(described_class).to receive(:assign_runner!)
|
||||
.with(pending_job, anything).and_raise(ActiveRecord::StaleObjectError)
|
||||
allow_next_instance_of(described_class) do |instance|
|
||||
allow(instance).to receive(:assign_runner!).and_call_original
|
||||
allow(instance).to receive(:assign_runner!)
|
||||
.with(pending_job, anything).and_raise(ActiveRecord::StaleObjectError)
|
||||
end
|
||||
end
|
||||
|
||||
subject { described_class.new(project_runner, nil).execute }
|
||||
|
|
@ -474,9 +476,10 @@ module Ci
|
|||
let!(:other_build) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(::Ci::Queue::BuildQueueService)
|
||||
.to receive(:execute)
|
||||
.and_return(Ci::Build.where(id: [pending_job, other_build]).pluck(:id, :partition_id))
|
||||
allow_next_instance_of(::Ci::Queue::BuildQueueService) do |instance|
|
||||
allow(instance).to receive(:execute)
|
||||
.and_return(Ci::Build.where(id: [pending_job, other_build]).pluck(:id, :partition_id))
|
||||
end
|
||||
end
|
||||
|
||||
it "receives second build from the queue" do
|
||||
|
|
@ -487,9 +490,10 @@ module Ci
|
|||
|
||||
context 'when single build is in queue' do
|
||||
before do
|
||||
allow_any_instance_of(::Ci::Queue::BuildQueueService)
|
||||
.to receive(:execute)
|
||||
.and_return(Ci::Build.where(id: pending_job).pluck(:id, :partition_id))
|
||||
allow_next_instance_of(::Ci::Queue::BuildQueueService) do |instance|
|
||||
allow(instance).to receive(:execute)
|
||||
.and_return(Ci::Build.where(id: pending_job).pluck(:id, :partition_id))
|
||||
end
|
||||
end
|
||||
|
||||
it "does not receive any valid result" do
|
||||
|
|
@ -499,9 +503,10 @@ module Ci
|
|||
|
||||
context 'when there is no build in queue' do
|
||||
before do
|
||||
allow_any_instance_of(::Ci::Queue::BuildQueueService)
|
||||
.to receive(:execute)
|
||||
.and_return([])
|
||||
allow_next_instance_of(::Ci::Queue::BuildQueueService) do |instance|
|
||||
allow(instance).to receive(:execute)
|
||||
.and_return([])
|
||||
end
|
||||
end
|
||||
|
||||
it "does not receive builds but result is valid" do
|
||||
|
|
@ -893,6 +898,66 @@ module Ci
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when metrics recording fails' do
|
||||
before do
|
||||
project.update!(shared_runners_enabled: true)
|
||||
pending_job.reload.create_queuing_entry!
|
||||
|
||||
allow_next_instance_of(::Gitlab::Ci::Queue::Metrics) do |metric|
|
||||
allow(metric).to receive(:register_success).and_raise(StandardError, 'metrics failure')
|
||||
end
|
||||
end
|
||||
|
||||
it 'continues assignment when register_success fails' do
|
||||
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
|
||||
.with(
|
||||
instance_of(StandardError),
|
||||
hash_including(
|
||||
build_id: pending_job.id,
|
||||
build_name: pending_job.name,
|
||||
build_stage: pending_job.stage_name,
|
||||
pipeline_id: pending_job.pipeline_id,
|
||||
project_id: pending_job.project_id
|
||||
)
|
||||
)
|
||||
|
||||
result = described_class.new(shared_runner, nil).execute
|
||||
|
||||
expect(result).to be_valid
|
||||
expect(result.build).to eq(pending_job)
|
||||
expect(result.build_json).to be_present
|
||||
expect(pending_job.reload).to be_running
|
||||
end
|
||||
|
||||
it 'continues assignment when observe_queue_depth fails' do
|
||||
allow_next_instance_of(::Gitlab::Ci::Queue::Metrics) do |metric|
|
||||
allow(metric).to receive(:register_success).and_call_original
|
||||
allow(metric).to receive(:observe_queue_depth)
|
||||
.with(:found, anything)
|
||||
.and_raise(StandardError, 'queue depth metrics failure')
|
||||
end
|
||||
|
||||
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
|
||||
.with(
|
||||
instance_of(StandardError),
|
||||
hash_including(
|
||||
build_id: pending_job.id,
|
||||
build_name: pending_job.name,
|
||||
build_stage: pending_job.stage_name,
|
||||
pipeline_id: pending_job.pipeline_id,
|
||||
project_id: pending_job.project_id
|
||||
)
|
||||
)
|
||||
|
||||
result = described_class.new(shared_runner, nil).execute
|
||||
|
||||
expect(result).to be_valid
|
||||
expect(result.build).to eq(pending_job)
|
||||
expect(result.build_json).to be_present
|
||||
expect(pending_job.reload).to be_running
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using pending builds table' do
|
||||
|
|
@ -1137,6 +1202,25 @@ module Ci
|
|||
expect(result.build).to be_nil
|
||||
expect(result.build_json).to be_nil
|
||||
end
|
||||
|
||||
context 'when metrics tracking raises an error during conflict' do
|
||||
let(:error) { StandardError.new('Metrics tracking failed') }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(Gitlab::Ci::Queue::Metrics) do |metric|
|
||||
allow(metric).to receive(:observe_queue_depth).with(:conflict, any_args).and_raise(error)
|
||||
end
|
||||
end
|
||||
|
||||
it 'tracks and raises the exception for dev without affecting the result' do
|
||||
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error)
|
||||
|
||||
result = described_class.new(project_runner, nil).execute
|
||||
|
||||
expect(result).not_to be_valid
|
||||
expect(result.build).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_on(runner, runner_manager: nil, params: {})
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ RSpec.configure do |config|
|
|||
config.include_context 'when rendered has no HTML escapes', type: :view
|
||||
config.include_context 'with STI disabled', type: :model
|
||||
|
||||
include StubCurrentOrganization
|
||||
include StubFeatureFlags
|
||||
include StubSnowplow
|
||||
include StubMember
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module StubCurrentOrganization
|
||||
def stub_current_organization(organization)
|
||||
allow_next_instance_of(Gitlab::Current::Organization) do |instance|
|
||||
allow(instance).to receive(:organization).and_return(organization)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -8,9 +8,7 @@ RSpec.shared_context 'with current_organization setting' do
|
|||
end
|
||||
|
||||
before do
|
||||
allow_next_instance_of(::Gitlab::Current::Organization) do |organization|
|
||||
allow(organization).to receive(:organization).and_return(current_organization)
|
||||
end
|
||||
stub_current_organization(current_organization)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,7 @@ RSpec.shared_context 'with conan api setup' do
|
|||
let_it_be(:user) { create(:user, developer_of: [project]) }
|
||||
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
|
||||
let_it_be(:deploy_token) do
|
||||
create(:deploy_token, read_package_registry: true, write_package_registry: true)
|
||||
end
|
||||
|
||||
let_it_be(:project_deploy_token, freeze: true) do
|
||||
create(:project_deploy_token, deploy_token: deploy_token, project: project)
|
||||
create(:deploy_token, read_package_registry: true, write_package_registry: true, projects: [project])
|
||||
end
|
||||
|
||||
let_it_be(:job, freeze: true) { create(:ci_build, :running, user: user, project: project) }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ RSpec.describe ::Gitlab::Counters::FlushStaleCounterIncrementsCronWorker, featur
|
|||
context 'when we are on gitlab.com' do
|
||||
before do
|
||||
allow(Gitlab).to receive(:com_except_jh?).and_return(true)
|
||||
allow(::Gitlab::Counters::FlushStaleCounterIncrementsWorker).to receive(:perform_with_capacity)
|
||||
end
|
||||
|
||||
it 'calls FlushStaleCounterIncrementsWorker.perform_with_capacity' do
|
||||
|
|
|
|||
|
|
@ -78,18 +78,26 @@ RSpec.describe ::Gitlab::Counters::FlushStaleCounterIncrementsWorker, :saas, :cl
|
|||
before do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.set(redis_key, project_daily_statistic.id)
|
||||
stub_const("#{described_class}::ID_RANGES", { ProjectDailyStatistic => {
|
||||
end_id: project_daily_statistic_three.id
|
||||
} })
|
||||
stub_const("#{described_class}::BATCH_LIMIT", 1)
|
||||
end
|
||||
allow(Gitlab::Saas).to receive(:feature_available?).with(:purchases_additional_minutes).and_return(true)
|
||||
end
|
||||
|
||||
it "flushes stale counters and updates the redis start id" do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis.get(redis_key).to_i).to eq(project_daily_statistic.id)
|
||||
end
|
||||
|
||||
# Test that the service is called multiple times (batching behavior)
|
||||
# without running the full 100 iterations, and verify early termination
|
||||
# when no more work is available
|
||||
|
||||
expect_next_instance_of(Gitlab::Counters::FlushStaleCounterIncrements) do |service|
|
||||
expect(service).to receive(:execute)
|
||||
.and_call_original
|
||||
end
|
||||
end.thrice
|
||||
|
||||
expect_initial_counts
|
||||
worker.perform_work
|
||||
|
|
|
|||
Loading…
Reference in New Issue