Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-05-12 12:14:39 +00:00
parent e08403843b
commit fb02c9f93d
37 changed files with 349 additions and 66 deletions

View File

@ -1 +1 @@
07f4e69a92acbd390b3576970bc46f89bc35e673
503d70e59609c805742ef9ac6537240e0db33c40

View File

@ -45,6 +45,7 @@ export default {
:svg-height="150"
:primary-button-text="$options.i18n.createNew"
:primary-button-link="newSchedulePath"
data-testid="empty-state-new-schedule-button"
>
<template #description>
<p class="gl-mb-0">{{ $options.i18n.description }}</p>

View File

@ -11,16 +11,19 @@ const DEFAULT_DOCS_URL = 'https://docs.gitlab.com';
// eslint-disable-next-line no-restricted-syntax
const DEFAULT_PROMO_URL = 'https://about.gitlab.com';
const DEFAULT_CONTRIBUTE_URL = 'https://contributors.gitlab.com';
const {
forum_url: FORUM_URL = DEFAULT_FORUM_URL,
docs_url: DOCS_URL = DEFAULT_DOCS_URL,
promo_url: PROMO_URL = DEFAULT_PROMO_URL,
contribute_url: CONTRIBUTE_URL = DEFAULT_CONTRIBUTE_URL,
} = window.gon;
// eslint-disable-next-line no-restricted-syntax
export const DOCS_URL_IN_EE_DIR = `${DOCS_URL}/ee`;
export { FORUM_URL, DOCS_URL, PROMO_URL };
export { FORUM_URL, DOCS_URL, PROMO_URL, CONTRIBUTE_URL };
export const GL_DARK = 'gl-dark';
export const GL_LIGHT = 'gl-light';

View File

@ -36,6 +36,7 @@ export default {
<template>
<gl-disclosure-dropdown-item
v-if="ideItem.items"
:data-testid="ideItem.testId"
class="gl-mb-3 gl-flex gl-w-full gl-items-center gl-justify-between gl-px-4 gl-py-2"
>
<span class="gl-min-w-0">{{ ideItem.text }}</span>
@ -56,6 +57,7 @@ export default {
<gl-disclosure-dropdown-item
v-else-if="ideItem.href"
:item="ideItem"
:data-testid="ideItem.testId"
@action="trackAndClose(ideItem.tracking)"
>
<template #list-item>

View File

@ -96,6 +96,7 @@ export default {
action: 'click_consolidated_edit',
label: 'web_ide',
},
testId: 'webide-menu-item',
href: this.webIdeUrl,
extraAttrs: {
target: '_blank',

View File

@ -2,7 +2,7 @@
import { GlBadge, GlButton, GlDisclosureDropdown, GlDisclosureDropdownGroup } from '@gitlab/ui';
import GitlabVersionCheckBadge from 'jh_else_ce/gitlab_version_check/components/gitlab_version_check_badge.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
import { FORUM_URL, PROMO_URL } from '~/constants';
import { FORUM_URL, PROMO_URL, CONTRIBUTE_URL } from '~/constants';
import { __ } from '~/locale';
import { STORAGE_KEY } from '~/whats_new/utils/notification';
import Tracking from '~/tracking';
@ -12,7 +12,6 @@ export default {
components: {
GlBadge,
GlButton,
GlDisclosureDropdown,
GlDisclosureDropdownGroup,
GitlabVersionCheckBadge,
@ -87,7 +86,7 @@ export default {
},
{
text: this.$options.i18n.contribute,
href: helpPagePath('_index.md', { anchor: 'contribute-to-gitlab' }),
href: CONTRIBUTE_URL,
extraAttrs: {
...this.trackingAttrs('contribute_to_gitlab'),
},

View File

@ -12,9 +12,11 @@ module Import
end
def execute
ensure_auth_credentials!
if uri && uri.hostname && Project::VALID_IMPORT_PROTOCOLS.include?(uri.scheme)
ensure_auth_credentials!
return ServiceResponse.success if Gitlab::GitalyClient::RemoteService.exists?(uri.to_s) # rubocop: disable CodeReuse/ActiveRecord -- false positive
return ServiceResponse.success if Gitlab::GitalyClient::RemoteService.exists?(uri.to_s) # rubocop: disable CodeReuse/ActiveRecord -- false positive
end
ServiceResponse.error(
message: 'Unable to access repository with the URL and credentials provided',

View File

@ -85,8 +85,12 @@ module WorkItems
def update_work_item_parent(parent)
return remove_parent_link(work_item) if parent.nil?
service_params = { target_issuable: work_item }.merge(
params.slice(:relative_position)
)
service_response = ::WorkItems::ParentLinks::CreateService
.new(parent, current_user, { target_issuable: work_item })
.new(parent, current_user, service_params)
.execute
# Reference the parent instead because the error is returned in the child context

View File

@ -24,11 +24,9 @@ module WorkItems
end
def linkable_issuables(work_items)
@linkable_issuables ||= if can_add_to_parent?(issuable)
work_items.select { |work_item| linkable?(work_item) }
else
[]
end
@linkable_issuables ||= work_items.select do |work_item|
can_add_to_parent?(issuable, work_item) && linkable?(work_item)
end
end
def linkable?(work_item)
@ -40,7 +38,7 @@ module WorkItems
end
# Overriden in EE
def can_add_to_parent?(parent_work_item)
def can_add_to_parent?(parent_work_item, _child_work_item = nil)
can_admin_link?(parent_work_item)
end

View File

@ -9,7 +9,7 @@ class GroupImportWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :importers
def perform(user_id, group_id)
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/464675')
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/464675', new_threshold: 225)
current_user = User.find(user_id)
group = Group.find(group_id)

View File

@ -0,0 +1,10 @@
---
name: bbm_retry_sidekiq_shutdown_exception
description:
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366720
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/182060
rollout_issue_url:
milestone: '18.0'
group: group::database frameworks
type: experiment
default_enabled: false

View File

@ -2,7 +2,7 @@
name: importer_user_mapping_allow_bypass_of_confirmation
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/534328
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/187616
rollout_issue_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/541373
milestone: '17.11'
group: group::import and integrate
type: wip

View File

@ -491,6 +491,9 @@ p_ci_pipelines:
- table: projects
column: project_id
on_delete: async_delete
- table: ci_triggers
column: trigger_id
on_delete: async_delete
p_ci_runner_machine_builds:
- table: ci_runner_machines
column: runner_machine_id

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class RemoveIssuesCorrectWorkItemTypeIdCh < ClickHouse::Migration
def up
execute <<~SQL
ALTER TABLE siphon_issues DROP COLUMN IF EXISTS correct_work_item_type_id
SQL
end
def down
execute <<~SQL
ALTER TABLE siphon_issues ADD COLUMN IF NOT EXISTS correct_work_item_type_id Int64
SQL
end
end

View File

@ -10,3 +10,4 @@ milestone: '17.11'
gitlab_schema: gitlab_main_cell
sharding_key:
organization_id: organizations
table_size: small

View File

@ -14,4 +14,4 @@ gitlab_schema: gitlab_main_cell
sharding_key:
project_id: projects
organization_id: organizations
table_size: small
table_size: medium

View File

@ -8,4 +8,4 @@ description: Storing custom attributes per user
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13038
milestone: '10.1'
gitlab_schema: gitlab_main_clusterwide
table_size: small
table_size: medium

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class TrackRecordDeletionsForCiTriggers < Gitlab::Database::Migration[2.3]
include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
milestone '18.1'
def up
track_record_deletions(:ci_triggers)
end
def down
untrack_record_deletions(:ci_triggers)
end
end

View File

@ -0,0 +1 @@
aa9ab5b359cc934c3a38f4335a11f87fadff4e7e6aa066894271716c7263abda

View File

@ -41164,6 +41164,8 @@ CREATE TRIGGER ci_runner_machines_loose_fk_trigger AFTER DELETE ON ci_runner_mac
CREATE TRIGGER ci_runners_loose_fk_trigger AFTER DELETE ON ci_runners REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records_override_table('ci_runners');
CREATE TRIGGER ci_triggers_loose_fk_trigger AFTER DELETE ON ci_triggers REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
CREATE TRIGGER cluster_agents_loose_fk_trigger AFTER DELETE ON cluster_agents REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
CREATE TRIGGER clusters_loose_fk_trigger AFTER DELETE ON clusters REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();

View File

@ -0,0 +1,106 @@
---
stage: AI-powered
group: AI Framework
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
title: Vertex AI Model Enablement Process
---
## Production Environment Setup
### 1. Request Initiation
- Create an issue in the [GitLab project](https://gitlab.com/gitlab-org/gitlab/-/issues)
- Use the Model Enablement Request template - see below
- Specify the model(s) to be enabled (e.g., Codestral)
- Share the issue link in the `#ai-infrastructure` channel for visibility
### 2. Request Processing
- Request is handled by either:
- Infrastructure team (Infra)
- AI Framework team (AIF)
### 3. Model Enablement
- For Vertex AI managed models:
- Team enables the model via the Vertex AI console ("click on enable")
- For custom configurations:
- AIF team opens a ticket with Google for customization needs
### 4. Quota Management
- Monitoring for existing quota is available from the [AI-gateway dashboard](https://dashboards.gitlab.net/d/ai-gateway-main/ai-gateway3a-overview?from=now-6h%2Fm&orgId=1&timezone=utc&to=now%2Fm&var-PROMETHEUS_DS=mimir-runway&var-environment=gprd&viewPanel=panel-1217942947). Use the little arrow on the top left to drill down and see quota usage per model.
- Not all quota are available in our monitoring, all visible quota are available in the [GCP console for the `gitlab-ai-framework-prod` project](https://console.cloud.google.com/iam-admin/quotas?referrer=search&inv=1&invt=Abs5YQ&project=gitlab-ai-framework-prod)
- Quota capacity forecasting is available in [tamland](https://gitlab-com.gitlab.io/gl-infra/capacity-planning-trackers/gitlab-com/service_groups/ai-gateway/)
- Quota increases to shared resources need to be requested from Google
- Provisioned throughput could be purchased from Google if justifiable.
- Even when quota is available, requests may be throttled during high demand periods due to Anthropic's resource provisioning model. Unlike direct Google services which over-provision resources, Anthropic provisions based on actual demand. To ensure consistent throughput without throttling, dedicated provisioned throughput can be purchased through Anthropic.
## Load Testing Environment Setup
### 1. Environment Selection
- Options include:
- ai-framework-dev
- ai-framework-stage
- Dedicated load test environment (e.g., sandbox project)
### 2. Access Request
- Create an access request using the [template](https://gitlab.com/gitlab-com/team-member-epics/access-requests/-/issues/new?description_template=Individual_Bulk_Access_Request)
- Request roles/writer role for the project
### 3. Environment Configuration
- Replicate the exact same model configuration from production
- Ensure isolation from production to prevent:
- Load test interrupting production traffic
- External traffic skewing load test results
### 4. Model Verification
- Verify model specs match production environment
- Validate quotas and capacity before running tests
## Best Practices
- Test new models or model versions before deploying to production
- Use isolated environments for load testing to prevent impacting users
- Monitor for GPU capacity issues and rate limits during testing
- Document configuration changes for future reference
## Model Enablement Request Template
```markdown
### Model Details
- **Model Name**: [e.g., Codestral, Claude 3 Opus, etc.]
- **Provider**: [e.g., Google Vertex AI, Anthropic, etc.]
- **Model Version/Edition**: [e.g., v1, Sonnet, Haiku, etc.]
### Business Justification
- **Purpose**: [Brief description of how this model will be used]
- **Features/Capabilities Required**: [Specific capabilities needed from this model]
- **Expected Impact**: [How this model will improve GitLab features/services]
### Technical Requirements
- **Environment(s)**: [Production, Staging, Dev, etc.]
- **Expected Traffic/Usage**: [Estimated QPS, daily usage, etc.]
- **Required Quotas**: [TPU/GPU hours, tokens per minute, etc. if known]
- **Integration Point**: [Which GitLab service(s) will use this model]
### Timeline
- **Requested By Date**: [When you need this model to be available]
- **Testing Period**: [Planned testing dates before full deployment]
### Additional Information
- **Special Configuration Needs**: [Any custom settings needed]
- **Similar Models Already Enabled**: [For reference/comparison]
- **Links to Relevant Documentation**: [Model documentation, internal specs, etc.]
/label ~"group::ai framework"
```

View File

@ -11,7 +11,7 @@ This page is about developing dark mode for GitLab. For more information on how
### Current approach
1. GitLab UI includes light and dark mode [design tokens](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/contributing/design_tokens.md) CSS custom properties for colors and components.
1. GitLab UI includes light and dark mode [design tokens](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/contributing/design_tokens.md) CSS custom properties for colors and components. See [design tokens technical implementation](https://design.gitlab.com/product-foundations/design-tokens-technical-implementation)
1. [Semantic design tokens](https://design.gitlab.com/product-foundations/design-tokens#semantic-design-tokens) provide values for light and dark mode in general usage, for example: background, text, and border colors.
### Deprecated approach
@ -32,7 +32,11 @@ Design tokens generate both CSS custom properties and SCSS variables which are i
- **CSS custom properties:** are preferred to update color modes without loading a color mode specific stylesheet, and are required for any colors within the `app/assets/stylesheets/page_bundles` directory.
- **SCSS variables:** override existing color usage for dark mode and are compiled into a color mode specific stylesheet.
### Adding CSS custom properties
Create bespoke CSS custom properties when design tokens cannot be used with either Tailwind utilities or existing CSS custom properties. See [guidance for manually adding CSS custom properties](https://design.gitlab.com/product-foundations/design-tokens-technical-implementation#bespoke-dark-mode-solutions) in projects.
### Page bundles
To support dark mode CSS custom properties should be used in `page_bundle` styles as we do not generate separate
To support dark mode, CSS custom properties should be used in `page_bundle` styles as we do not generate separate
`*_dark.css` variants of each `page_bundle` file.

View File

@ -43,13 +43,13 @@ To deploy GitLab on GCP you must create a virtual machine:
1. Go to <https://console.cloud.google.com/compute/instances> and sign in with your Google credentials.
1. Select **Create**
![Search for GitLab](img/launch_vm_v10_6.png)
![Select "Create" to create an instance.](img/launch_vm_v10_6.png)
1. On the next page, you can select the type of VM as well as the
estimated costs. Provide the name of the instance, desired data center, and machine type.
Note our [hardware requirements for different user base sizes](../requirements.md).
![Launch on Compute Engine](img/vm_details_v13_1.png)
![Configure your instance.](img/vm_details_v13_1.png)
1. To select the size, type, and desired [operating system](../../administration/package_information/supported_os.md),
select **Change** under `Boot disk`. select **Select** when finished.
@ -60,19 +60,19 @@ To deploy GitLab on GCP you must create a virtual machine:
After a few seconds, the instance is created and available to sign in. The next step is to install GitLab onto the instance.
![Deploy settings](img/vm_created_v10_6.png)
![The instance was created successfully.](img/vm_created_v10_6.png)
1. Make a note of the external IP address of the instance, as you will need that in a later step. <!-- using future tense is okay here -->
1. Select **SSH** under the connect column to connect to the instance.
1. A new window appears, with you logged into the instance.
![GitLab first sign in](img/ssh_terminal_v10_6.png)
![The command line interface of the instance](img/ssh_terminal_v10_6.png)
1. Next, follow the instructions for installing GitLab for the operating system you choose, at <https://about.gitlab.com/install/>. You can use the external IP address you noted before as the hostname.
1. Congratulations! GitLab is now installed and you can access it via your browser. To finish installation, open the URL in your browser and provide the initial administrator password. The username for this account is `root`.
![GitLab first sign in](img/first_signin_v10_6.png)
![GitLab first sign in after installation.](img/first_signin_v10_6.png)
## Next steps
@ -96,7 +96,7 @@ here's how you configure GitLab to be aware of the change:
1. SSH into the VM. You can select **SSH** in the Google console
and a new window pops up.
![SSH button](img/vm_created_v10_6.png)
![Instance details with an SSH button to log into it.](img/vm_created_v10_6.png)
In the future you might want to set up [connecting with an SSH key](https://cloud.google.com/compute/docs/connect/standard-ssh)
instead.

View File

@ -282,6 +282,8 @@ Placeholder users are associated only with the top-level group.
When you delete a subgroup or project, their placeholder users
no longer reference any contributions in the top-level group.
For testing, you should use a designated top-level group.
Deleting placeholder users is proposed in [issue 519391](https://gitlab.com/gitlab-org/gitlab/-/issues/519391)
and [issue 537340](https://gitlab.com/gitlab-org/gitlab/-/issues/537340).
{{< /alert >}}
@ -377,7 +379,7 @@ You can reassign contributions from multiple placeholder users to the same user
on the destination instance if the placeholder users are from:
- Different source instances
- The same source instance and are imported to different top-level groups on the destination instance
- The same source instance and are imported to different top-level groups on the destination instance
If an assigned user becomes inactive before accepting the reassignment request,
the pending reassignment remains linked to the user until they accept it.

View File

@ -13,6 +13,7 @@ module Gitlab
self.table_name = :batched_background_migration_jobs
MAX_ATTEMPTS = 3
MAX_SIDEKIQ_SHUTDOWN_FAILURES = 15
MIN_BATCH_SIZE = 1
SUB_BATCH_SIZE_REDUCE_FACTOR = 0.75
SUB_BATCH_SIZE_THRESHOLD = 65
@ -65,6 +66,10 @@ module Gitlab
after_transition any => :failed do |job, transition|
exception, from_sub_batch = job.class.extract_transition_options(transition.args)
# For jobs that could not complete work within the shutdown timeout when Sidekiq
# is shutting down, do not count this as an attempt.
job.decrement!(:attempts) if job.handle_sidekiq_shutdown_failure?(exception)
job.reduce_sub_batch_size! if from_sub_batch && job.can_reduce_sub_batch_size?
job.split_and_retry! if job.can_split?(exception)
@ -102,6 +107,8 @@ module Gitlab
delegate :job_class, :table_name, :column_name, :job_arguments, :job_class_name,
to: :batched_migration, prefix: :migration
delegate :sidekiq_shutdown_failures, to: :batched_job_transition_logs
def self.extract_transition_options(args)
error_hash = args.find { |arg| arg[:error].present? }
@ -243,6 +250,19 @@ module Gitlab
(1.0 * diff / initial_sub_batch_size * 100).round(2) > SUB_BATCH_SIZE_THRESHOLD
end
def sidekiq_shutdown_failures_count
sidekiq_shutdown_failures.count
end
def handle_sidekiq_shutdown_failure?(exception)
return false unless Feature.enabled?(:bbm_retry_sidekiq_shutdown_exception, Feature.current_request)
return false unless exception.is_a?(Sidekiq::Shutdown)
return false unless attempts > 1
return false unless sidekiq_shutdown_failures_count <= MAX_SIDEKIQ_SHUTDOWN_FAILURES
true
end
end
end
end

View File

@ -21,6 +21,8 @@ module Gitlab
enum :previous_status, Gitlab::Database::BackgroundMigration::BatchedJob.state_machine.states.map(&:name), prefix: true
enum :next_status, Gitlab::Database::BackgroundMigration::BatchedJob.state_machine.states.map(&:name), prefix: true
scope :sidekiq_shutdown_failures, -> { where(next_status: :failed, exception_class: 'Sidekiq::Shutdown') }
end
end
end

View File

@ -19,6 +19,10 @@ module QA
element 'webide-menu-item', ':data-testid="`${action.key}-menu-item`"' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/repository/components/code_dropdown/compact_code_dropdown.vue' do
element 'code-dropdown'
end
def click_edit
click_element('action-dropdown')
click_element('edit-menu-item')

View File

@ -133,7 +133,12 @@ module QA
end
def open_web_ide!
click_element('action-dropdown')
if has_element?('action-dropdown')
click_element('action-dropdown')
else
click_element('code-dropdown')
end
click_element('webide-menu-item')
page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
FactoryBot.define do
factory :batched_background_job_transition_log,
class: '::Gitlab::Database::BackgroundMigration::BatchedJobTransitionLog' do
batched_job factory: :batched_background_migration_job
trait(:sidekiq_shutdown_failure) do
previous_status { 1 }
next_status { 2 }
exception_class { 'Sidekiq::Shutdown' }
end
trait(:succeeded) do
previous_status { 0 }
next_status { 3 }
end
end
end

View File

@ -8,7 +8,6 @@ RSpec.describe "Populate new pipeline CI variables with url params", :js, featur
let(:page_path) { new_project_pipeline_path(project) }
before do
stub_feature_flags(ci_inputs_for_pipelines: false)
sign_in(user)
project.add_maintainer(user)

View File

@ -14,7 +14,6 @@ RSpec.describe 'Pipeline Schedules', :js, feature_category: :continuous_integrat
before do
project.update!(ci_pipeline_variables_minimum_override_role: :developer)
stub_feature_flags(ci_inputs_for_pipelines: false)
end
context 'logged in as the pipeline schedule owner' do
@ -139,11 +138,8 @@ RSpec.describe 'Pipeline Schedules', :js, feature_category: :continuous_integrat
it 'changes ownership of the pipeline' do
find_by_testid('take-ownership-pipeline-schedule-btn').click
page.within('#pipeline-take-ownership-modal') do
click_button s_('PipelineSchedules|Take ownership')
wait_for_requests
end
send_keys [:tab, :enter]
wait_for_requests
within_testid('pipeline-schedule-table-row') do
expect(page).not_to have_content('No owner')
@ -151,14 +147,17 @@ RSpec.describe 'Pipeline Schedules', :js, feature_category: :continuous_integrat
end
end
it 'deletes the pipeline' do
it 'deletes the pipeline schedule' do
row_text = find_by_testid('pipeline-schedule-table-row').text
within_testid('pipeline-schedule-table-row') do
click_button s_('PipelineSchedules|Delete scheduled pipeline')
find_by_testid('delete-pipeline-schedule-btn').click
end
accept_gl_confirm(button_text: s_('PipelineSchedules|Delete scheduled pipeline'))
wait_for_requests
expect(page).not_to have_css('[data-testid="pipeline-schedule-table-row"]')
expect(page).not_to have_css('[data-testid="pipeline-schedule-table-row"]', text: row_text, wait: 10)
end
end
@ -308,47 +307,44 @@ RSpec.describe 'Pipeline Schedules', :js, feature_category: :continuous_integrat
end
end
shared_examples 'when not logged in' do
shared_examples 'user without project access' do
describe 'GET /projects/pipeline_schedules' do
describe 'the view' do
it 'does not show create schedule button' do
visit_pipelines_schedules
it 'does not show create schedule button' do
visit_pipelines_schedules
expect(page).not_to have_link('New schedule')
expect(page).not_to have_link('New schedule')
end
context 'when project is public' do
let_it_be(:public_project) { create(:project, :repository, :public, public_builds: true) }
it 'shows Pipelines Schedules page' do
visit project_pipeline_schedules_path(public_project, scope: scope)
expect(page).to have_selector(:css, '[data-testid="empty-state-new-schedule-button"]')
end
context 'when project is public' do
let_it_be(:project) { create(:project, :repository, :public, public_builds: true) }
it 'shows Pipelines Schedules page' do
visit_pipelines_schedules
expect(page).to have_selector(:css, '[data-testid="new-schedule-button"]')
context 'when public pipelines are disabled' do
before do
public_project.update!(public_builds: false)
end
context 'when public pipelines are disabled' do
before do
project.update!(public_builds: false)
visit_pipelines_schedules
end
it 'shows Not Found page' do
expect(page).to have_content('Page not found')
end
it 'shows Not Found page' do
visit project_pipeline_schedules_path(public_project, scope: scope)
expect(page).to have_content('Page not found')
end
end
end
end
end
it_behaves_like 'when not logged in'
it_behaves_like 'user without project access'
context 'logged in as non-member' do
before do
gitlab_sign_in(user)
end
it_behaves_like 'when not logged in'
it_behaves_like 'user without project access'
end
def visit_new_pipeline_schedule

View File

@ -14,7 +14,6 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
let(:user) { create(:user) }
before do
stub_feature_flags(ci_inputs_for_pipelines: false)
sign_in(user)
project.add_developer(user)
@ -118,7 +117,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
end
context 'when canceling' do
it 'indicates that pipelines was canceled', :sidekiq_inline do
it 'indicates that pipeline was canceled', :sidekiq_inline do
find('.js-pipelines-cancel-button').click
click_button 'Stop pipeline'

View File

@ -5,6 +5,7 @@ export const mockIdeItems = [
},
href: 'webIdeUrl://foo.bar',
shortcut: '.',
testId: 'webide-menu-item',
text: 'Web IDE',
tracking: {
action: 'click_consolidated_edit',

View File

@ -4,7 +4,7 @@ import toggleWhatsNewDrawer from '~/whats_new';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import HelpCenter from '~/super_sidebar/components/help_center.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
import { FORUM_URL, PROMO_URL } from '~/constants';
import { FORUM_URL, PROMO_URL, CONTRIBUTE_URL } from '~/constants';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { STORAGE_KEY } from '~/whats_new/utils/notification';
import { mockTracking } from 'helpers/tracking_helper';
@ -77,7 +77,7 @@ describe('HelpCenter component', () => {
},
{
text: HelpCenter.i18n.contribute,
href: helpPagePath('_index.md', { anchor: 'contribute-to-gitlab' }),
href: CONTRIBUTE_URL,
extraAttrs: trackingAttrs('contribute_to_gitlab'),
},
{

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model do
RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model, feature_category: :database do
it_behaves_like 'having unique enum values'
it { is_expected.to be_a Gitlab::Database::SharedModel }
@ -183,6 +183,52 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
expect(transition_log.exception_class).to eq('RuntimeError')
expect(transition_log.exception_message).to eq('RuntimeError')
end
context 'with Sidekiq::Shutdown' do
it 'decrements job attemts' do
job.update!(attempts: 2)
expect { job.failure!(error: Sidekiq::Shutdown.new) }.to change { job.reload.attempts }.by(-1)
end
it 'does not decrement job attemts if less than or equal to 1' do
job.update!(attempts: 1)
expect { job.failure!(error: Sidekiq::Shutdown.new) }.not_to change { job.reload.attempts }
end
it 'does not decrement job attemts if there are more than MAX_SIDEKIQ_SHUTDOWN_FAILURES' do
job.update!(attempts: 2)
stub_const("#{described_class}::MAX_SIDEKIQ_SHUTDOWN_FAILURES", 3)
(described_class::MAX_SIDEKIQ_SHUTDOWN_FAILURES + 1).times do
create(:batched_background_job_transition_log, :sidekiq_shutdown_failure, batched_job: job)
end
expect { job.failure!(error: Sidekiq::Shutdown.new) }.not_to change { job.reload.attempts }
end
context 'when bbm_retry_sidekiq_shutdown_exception is disabled' do
before do
stub_feature_flags(bbm_retry_sidekiq_shutdown_exception: false)
end
it 'does not decrements job attemts' do
job.update!(attempts: 2)
expect { job.failure!(error: Sidekiq::Shutdown.new) }.not_to change { job.reload.attempts }
end
end
end
context 'with other exception' do
it 'does not update job attemts' do
job.update!(attempts: 2)
expect { job.failure!(error: RuntimeError.new) }.not_to change { job.reload.attempts }
end
end
end
context 'when job fails during sub batch processing' do

View File

@ -18,4 +18,15 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJobTransitionLog, t
it { is_expected.to define_enum_for(:previous_status).with_values(%i[pending running failed succeeded]).with_prefix }
it { is_expected.to define_enum_for(:next_status).with_values(%i[pending running failed succeeded]).with_prefix }
end
describe '.sidekiq_shutdown_failures' do
it 'returns failures because of Sidekiq::Shutdown errors' do
create(:batched_background_job_transition_log, :succeeded)
sidekiq_shutdown = create(:batched_background_job_transition_log, :sidekiq_shutdown_failure)
failures = described_class.sidekiq_shutdown_failures
expect(failures).to match_array(sidekiq_shutdown)
end
end
end

View File

@ -43,6 +43,18 @@ RSpec.describe Import::ValidateRemoteGitEndpointService, feature_category: :impo
end
end
context 'when uri is nil' do
let(:url) { nil }
include_examples 'error response'
end
context 'when uri does not have a schema' do
let(:url) { 'example.com' }
include_examples 'error response'
end
context 'when uri is using an invalid protocol' do
let(:url) { 'ssh://demo.host/repo' }