Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
d88bd7ffe3
commit
d762b1add0
|
|
@ -144,6 +144,7 @@ db:check-schema:
|
|||
function db_check_schema() {
|
||||
bundle exec rake db:drop db:create db:migrate
|
||||
scripts/validate_migration_timestamps
|
||||
scripts/validate_migration_checksum
|
||||
}
|
||||
|
||||
run_with_custom_exit_code db_check_schema
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default {
|
|||
forceCancelJobButtonLabel: s__('Job|Force cancel'),
|
||||
forceCancelJobButtonTooltip: s__('Job|Force cancel a job stuck in `canceling` state'),
|
||||
forceCancelJobConfirmText: s__(
|
||||
'Job|Are you sure you want to force cancel this job? This will immediately mark the job as canceled, even if the runner is unresponsive.',
|
||||
'Job|Are you sure you want to force cancel this job? This will immediately mark the job as canceled, even if the job is still running.',
|
||||
),
|
||||
},
|
||||
forwardDeploymentFailureModalId,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class Admin::RunnersController < Admin::ApplicationController
|
|||
def assign_projects
|
||||
@projects =
|
||||
if params[:search].present?
|
||||
::Project.search(params[:search])
|
||||
::Project.search(params[:search], include_namespace: true)
|
||||
else
|
||||
Project.all
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@ module AutoMerge # rubocop:disable Gitlab/BoundedContexts -- Existing module
|
|||
default: 'this merge request cannot be added to the merge train.'
|
||||
}.freeze
|
||||
|
||||
VALID_STATUSES = %i[available unavailable].freeze
|
||||
|
||||
def self.success
|
||||
new(
|
||||
status: :available
|
||||
)
|
||||
end
|
||||
|
||||
def self.error(unavailable_reason:, unsuccessful_check: nil)
|
||||
def self.error(unavailable_reason: :default, unsuccessful_check: nil)
|
||||
new(
|
||||
status: :unavailable,
|
||||
unavailable_reason: unavailable_reason,
|
||||
|
|
@ -30,6 +32,8 @@ module AutoMerge # rubocop:disable Gitlab/BoundedContexts -- Existing module
|
|||
attr_reader :status, :unavailable_reason, :unsuccessful_check
|
||||
|
||||
def initialize(status:, unavailable_reason: nil, unsuccessful_check: nil)
|
||||
raise ArgumentError, "Invalid status" unless VALID_STATUSES.include?(status)
|
||||
|
||||
self.status = status
|
||||
self.unavailable_reason = unavailable_reason
|
||||
self.unsuccessful_check = unsuccessful_check
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ module AutoMerge
|
|||
override :availability_details
|
||||
def availability_details(merge_request)
|
||||
super do
|
||||
default_reason = AutoMerge::AvailabilityCheck.error(unavailable_reason: :default)
|
||||
next default_reason if merge_request.project.merge_trains_enabled?
|
||||
next default_reason if merge_request.mergeable? && !merge_request.diff_head_pipeline_considered_in_progress?
|
||||
default_error = AutoMerge::AvailabilityCheck.error
|
||||
next default_error if merge_request.project.merge_trains_enabled?
|
||||
next default_error if merge_request.mergeable? && !merge_request.diff_head_pipeline_considered_in_progress?
|
||||
|
||||
AutoMerge::AvailabilityCheck.success
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
- project = local_assigns[:project].nil? || local_assigns[:project]
|
||||
- assigned = false unless local_assigns[:assigned] == true
|
||||
- is_owner = false unless local_assigns[:is_owner] == true
|
||||
- is_assigned = false unless local_assigns[:is_assigned] == true
|
||||
|
||||
%li
|
||||
.gl-flex.gl-gap-3
|
||||
- if assigned
|
||||
- if is_assigned
|
||||
.gl-min-w-6.gl-w-6
|
||||
= sprite_icon('status-success', variant: 'success', css_class: 'gl-mt-3')
|
||||
- else
|
||||
|
|
@ -13,6 +14,8 @@
|
|||
.gl-grow.gl-self-center
|
||||
%h3.gl-m-0.gl-text-base
|
||||
= project.full_name
|
||||
- if is_owner
|
||||
= render Pajamas::BadgeComponent.new(s_('Runners|Owner'), variant: 'info')
|
||||
- if project.description
|
||||
%p.gl-mb-0.gl-text-sm.gl-text-subtle
|
||||
= project.description
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#js-admin-runner-edit{ data: {runner_id: @runner.id, runner_path: admin_runner_path(@runner) } }
|
||||
|
||||
- if @runner.project_type?
|
||||
= render ::Layouts::SettingsSectionComponent.new(_('Restrict projects for this runner'), options: { class: 'gl-mt-7 gl-pt-6 gl-border-t' }) do |c|
|
||||
= render ::Layouts::SettingsSectionComponent.new(s_('Runners|Assign this runner to projects'), options: { class: 'gl-mt-7 gl-pt-6 gl-border-t' }) do |c|
|
||||
- c.with_body do
|
||||
.gl-flex.gl-flex-col.gl-gap-5
|
||||
= render ::Layouts::CrudComponent.new(_('Assigned projects'), icon: 'project', count: @runner.runner_projects.count) do |c|
|
||||
|
|
@ -17,13 +17,15 @@
|
|||
- @runner.runner_projects.each do |runner_project|
|
||||
- project = runner_project.project
|
||||
- if project
|
||||
= render "project", project: project, assigned: true do
|
||||
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, href: admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, button_options: { class: 'gl-self-center' }) do
|
||||
= _('Disable')
|
||||
- is_owner = project == @runner.owner
|
||||
= render "project", project: project, is_owner: is_owner, is_assigned: true do
|
||||
- if !is_owner
|
||||
= render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, href: admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, button_options: { class: 'gl-self-center' }) do
|
||||
= s_('Runners|Unassign')
|
||||
|
||||
= render ::Layouts::CrudComponent.new(s_('Runners|Select projects to assign to this runner')) do |c|
|
||||
- c.with_body do
|
||||
= form_tag edit_admin_runner_path(@runner), id: 'runner-projects-search', class: 'gl-w-full gl-p-5', method: :get do
|
||||
= form_tag edit_admin_runner_path(@runner), class: 'gl-w-full gl-p-5', method: :get do
|
||||
.input-group
|
||||
= search_field_tag :search, params[:search], class: 'form-control gl-form-input', spellcheck: false
|
||||
.input-group-append
|
||||
|
|
@ -35,7 +37,7 @@
|
|||
= gitlab_ui_form_for project.runner_projects.new, url: admin_namespace_project_runner_projects_path(project.namespace, project), method: :post, html: { class: 'gl-self-center' } do |f|
|
||||
= f.hidden_field :runner_id, value: @runner.id
|
||||
= render Pajamas::ButtonComponent.new(size: :small, type: :submit) do
|
||||
= _('Enable')
|
||||
= s_('Runners|Assign')
|
||||
|
||||
- c.with_pagination do
|
||||
= paginate_without_count @projects
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
scope: project
|
||||
resolution_role: Maintainer
|
||||
manual_task: true
|
||||
window: 1
|
||||
body: | # (required) Don't change this line.
|
||||
We introduced the OpenTofu CI/CD template in 16.8 as CI/CD components were not available for GitLab Self-Managed yet.
|
||||
With the introduction of [GitLab CI/CD components for GitLab Self-Managed](https://docs.gitlab.com/ci/components/#use-a-gitlabcom-component-in-a-self-managed-instance)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
removal_milestone: "Pending"
|
||||
announcement_milestone: "17.9"
|
||||
breaking_change: true
|
||||
window: 2
|
||||
reporter: nagyv-gitlab
|
||||
stage: deploy
|
||||
issue_url: https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/656
|
||||
|
|
@ -13,7 +12,7 @@
|
|||
resolution_role: Maintainer
|
||||
manual_task: true
|
||||
body: | # (required) Don't change this line.
|
||||
In GitLab 18.0, we'll remove support for the `kpt`-based installation of the agent for Kubernetes.
|
||||
We'll remove support for the `kpt`-based installation of the agent for Kubernetes.
|
||||
Instead, you should install the agent with one of the supported installation methods:
|
||||
|
||||
- Helm (recommended)
|
||||
|
|
|
|||
|
|
@ -8081,7 +8081,7 @@ This change has been removed from its original milestone and is being reassessed
|
|||
|
||||
{{< /alert >}}
|
||||
|
||||
In GitLab 18.0, we'll remove support for the `kpt`-based installation of the agent for Kubernetes.
|
||||
We'll remove support for the `kpt`-based installation of the agent for Kubernetes.
|
||||
Instead, you should install the agent with one of the supported installation methods:
|
||||
|
||||
- Helm (recommended)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ pre-push:
|
|||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: '{db/migrate/*.rb,db/post_migrate/*.rb}'
|
||||
run: scripts/validate_migration_timestamps
|
||||
db-migration-checksum:
|
||||
tags: database
|
||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: '{db/migrate/*.rb,db/post_migrate/*.rb}'
|
||||
run: scripts/validate_migration_checksum
|
||||
static-verification:
|
||||
skip: true # This is disabled by default. You can enable this check by adding skip: false in lefthook-local.yml https://github.com/evilmartians/lefthook/blob/master/docs/configuration.md#skip
|
||||
tags: backend
|
||||
|
|
|
|||
|
|
@ -34670,7 +34670,7 @@ msgstr[1] ""
|
|||
msgid "Job|Are you sure you want to erase this job log and artifacts?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|Are you sure you want to force cancel this job? This will immediately mark the job as canceled, even if the runner is unresponsive."
|
||||
msgid "Job|Are you sure you want to force cancel this job? This will immediately mark the job as canceled, even if the job is still running."
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|Browse"
|
||||
|
|
@ -51123,9 +51123,6 @@ msgstr ""
|
|||
msgid "Restrict membership by email domain"
|
||||
msgstr ""
|
||||
|
||||
msgid "Restrict projects for this runner"
|
||||
msgstr ""
|
||||
|
||||
msgid "Restricted access"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -51559,6 +51556,12 @@ msgstr ""
|
|||
msgid "Runners|Are you sure you want to disable instance runners for %{groupName}?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Assign"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Assign this runner to projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Assigned Group"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -52400,6 +52403,9 @@ msgstr ""
|
|||
msgid "Runners|UTC Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Unassign"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Understand how long it takes for runners to pick up a job. %{linkStart}How is this calculated?%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,9 @@ module Gitlab
|
|||
"gitlab.webservice.workhorse.image" => "#{IMAGE_REPOSITORY}/gitlab-workhorse-ee",
|
||||
"gitlab.webservice.workhorse.tag" => workhorse_version,
|
||||
"gitlab.kas.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-kas",
|
||||
"gitlab.kas.image.tag" => with_semver_prefix(kas_version)
|
||||
"gitlab.kas.image.tag" => with_semver_prefix(kas_version),
|
||||
"gitlab.registry.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-container-registry",
|
||||
"gitlab.registry.image.tag" => registry_version
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ module Gitlab
|
|||
File.join(ci_project_dir, "GITLAB_KAS_VERSION")
|
||||
).strip
|
||||
end
|
||||
|
||||
def registry_version
|
||||
@registry_version ||= ENV["GITLAB_CONTAINER_REGISTRY_TAG"].presence || commit_sha
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ RSpec.describe Gitlab::Orchestrator::Deployment::DefaultValues do
|
|||
:@webservice_version,
|
||||
:@workhorse_version,
|
||||
:@gitlab_shell_version,
|
||||
:@sidekiq_version
|
||||
:@sidekiq_version,
|
||||
:@registry_version
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -90,7 +91,9 @@ RSpec.describe Gitlab::Orchestrator::Deployment::DefaultValues do
|
|||
"gitlab.webservice.workhorse.image" => "#{image_repository}/gitlab-workhorse-ee",
|
||||
"gitlab.webservice.workhorse.tag" => ci_commit_sha,
|
||||
"gitlab.kas.image.repository" => "#{image_repository}/gitlab-kas",
|
||||
"gitlab.kas.image.tag" => kas_version
|
||||
"gitlab.kas.image.tag" => kas_version,
|
||||
"gitlab.registry.image.repository" => "#{image_repository}/gitlab-container-registry",
|
||||
"gitlab.registry.image.tag" => ci_commit_sha
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -113,7 +116,8 @@ RSpec.describe Gitlab::Orchestrator::Deployment::DefaultValues do
|
|||
"GITLAB_SIDEKIQ_TAG" => "1088d209ac5dd8d245b00946de0760eb8fc9a181",
|
||||
"GITLAB_WEBSERVICE_TAG" => "b0ccc088a766801c8db9e7c564ad28472f33916c",
|
||||
"GITLAB_WORKHORSE_TAG" => "4a3990fb621ba6f6b7ddf36089868b24e22bb598",
|
||||
"GITLAB_KAS_TAG" => "03faf0a4227405febb714c4eaa78e4f16f5d0a37"
|
||||
"GITLAB_KAS_TAG" => "03faf0a4227405febb714c4eaa78e4f16f5d0a37",
|
||||
"GITLAB_CONTAINER_REGISTRY_TAG" => "595f6534d8286bf1b9d3b1f527cb3af93a9a63c5"
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -125,7 +129,8 @@ RSpec.describe Gitlab::Orchestrator::Deployment::DefaultValues do
|
|||
"gitlab.sidekiq.image.tag" => image_tags["GITLAB_SIDEKIQ_TAG"],
|
||||
"gitlab.webservice.image.tag" => image_tags["GITLAB_WEBSERVICE_TAG"],
|
||||
"gitlab.webservice.workhorse.tag" => image_tags["GITLAB_WORKHORSE_TAG"],
|
||||
"gitlab.kas.image.tag" => image_tags["GITLAB_KAS_TAG"]
|
||||
"gitlab.kas.image.tag" => image_tags["GITLAB_KAS_TAG"],
|
||||
"gitlab.registry.image.tag" => image_tags["GITLAB_CONTAINER_REGISTRY_TAG"]
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Checks for presence of migration checksum files when adding new migrations
|
||||
class MigrationChecksumChecker
|
||||
MIGRATION_DIRS = %w[db/migrate db/post_migrate].freeze
|
||||
CHECKSUM_DIR = 'db/schema_migrations'
|
||||
TIMESTAMP_REGEX = /\A(\d+)_/
|
||||
CHECKSUM_LENGTH = 64
|
||||
ERROR_CODE = 1
|
||||
|
||||
Result = Struct.new(:error_code, :error_message)
|
||||
|
||||
def check
|
||||
missing_or_invalid_files = find_checksum_issues
|
||||
|
||||
return if missing_or_invalid_files.empty?
|
||||
|
||||
format_error_result(missing_or_invalid_files)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_checksum_issues
|
||||
issues = {}
|
||||
|
||||
MIGRATION_DIRS.each do |migration_dir|
|
||||
next unless Dir.exist?(migration_dir)
|
||||
|
||||
Dir[File.join(migration_dir, '*.rb')].each do |migration_file|
|
||||
timestamp = extract_timestamp(migration_file)
|
||||
next unless timestamp
|
||||
|
||||
checksum_file = File.join(CHECKSUM_DIR, timestamp)
|
||||
|
||||
if !File.exist?(checksum_file)
|
||||
issues[migration_file] = "Missing checksum file"
|
||||
elsif File.zero?(checksum_file)
|
||||
issues[migration_file] = "Empty checksum file"
|
||||
else
|
||||
checksum_content = File.read(checksum_file).chomp
|
||||
issues[migration_file] = "Invalid checksum length" if checksum_content.length != CHECKSUM_LENGTH
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
issues
|
||||
end
|
||||
|
||||
def extract_timestamp(filename)
|
||||
file_basename = File.basename(filename)
|
||||
match = TIMESTAMP_REGEX.match(file_basename)
|
||||
match ? match[1] : nil
|
||||
end
|
||||
|
||||
def format_error_result(issues)
|
||||
message = issues.map do |file, issue_type|
|
||||
"#{issue_type} for migration: #{file}\n"
|
||||
end.join('')
|
||||
|
||||
Result.new(ERROR_CODE, "\e[31mError: Issues found with migration checksum files\n\n#{message}\e[0m")
|
||||
end
|
||||
end
|
||||
|
|
@ -494,7 +494,8 @@ module Trigger
|
|||
"GITLAB_SIDEKIQ_TAG" => container_versions["gitlab-sidekiq-#{edition}"],
|
||||
"GITLAB_WEBSERVICE_TAG" => container_versions["gitlab-webservice-#{edition}"],
|
||||
"GITLAB_WORKHORSE_TAG" => container_versions["gitlab-workhorse-#{edition}"],
|
||||
"GITLAB_KAS_TAG" => container_versions["gitlab-kas"]
|
||||
"GITLAB_KAS_TAG" => container_versions["gitlab-kas"],
|
||||
"GITLAB_CONTAINER_REGISTRY_TAG" => container_versions["gitlab-container-registry"]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative './database/migration_checksum_checker'
|
||||
|
||||
result = MigrationChecksumChecker.new.check
|
||||
|
||||
if result
|
||||
puts result.error_message
|
||||
exit result.error_code
|
||||
end
|
||||
|
|
@ -79,8 +79,8 @@ RSpec.describe Admin::RunnersController, feature_category: :fleet_visibility do
|
|||
describe '#edit' do
|
||||
render_views
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:project_two) { create(:project) }
|
||||
let_it_be(:project) { create(:project, name: 'My project 1') }
|
||||
let_it_be(:project_two) { create(:project, name: 'My project 2') }
|
||||
|
||||
it 'shows a runner edit page' do
|
||||
get :edit, params: { id: runner.id }
|
||||
|
|
@ -88,6 +88,13 @@ RSpec.describe Admin::RunnersController, feature_category: :fleet_visibility do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
it 'shows a list of projects in runner edit page' do
|
||||
get :edit, params: { id: runner.id, search: 'My project' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(assigns(:projects)).to match_array([project, project_two])
|
||||
end
|
||||
|
||||
it 'shows 404 for unknown runner' do
|
||||
get :edit, params: { id: 0 }
|
||||
|
||||
|
|
|
|||
|
|
@ -112,9 +112,8 @@ RSpec.describe "Admin manages runner in admin section", :js, feature_category: :
|
|||
|
||||
describe 'search' do
|
||||
before do
|
||||
search_form = find('#runner-projects-search')
|
||||
search_form.fill_in 'search', with: project1.name
|
||||
search_form.click_button 'Search'
|
||||
fill_in 'search', with: project1.name
|
||||
click_button 'Search'
|
||||
end
|
||||
|
||||
it 'contains name of correct project' do
|
||||
|
|
@ -123,12 +122,12 @@ RSpec.describe "Admin manages runner in admin section", :js, feature_category: :
|
|||
end
|
||||
end
|
||||
|
||||
describe 'enable/create' do
|
||||
describe 'assign' do
|
||||
shared_examples 'assignable runner' do
|
||||
it 'enables a runner for a project' do
|
||||
within_testid('unassigned-projects') do
|
||||
within('li', text: project2.full_name) do
|
||||
click_on 'Enable'
|
||||
click_on 'Assign'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -160,47 +159,32 @@ RSpec.describe "Admin manages runner in admin section", :js, feature_category: :
|
|||
end
|
||||
end
|
||||
|
||||
describe 'disable/destroy' do
|
||||
context 'when runner is being removed from owner project' do
|
||||
it 'denies removing project runner from project' do
|
||||
within_testid('assigned-projects') do
|
||||
click_on 'Disable'
|
||||
end
|
||||
describe 'unassign' do
|
||||
let_it_be(:runner) { create(:ci_runner, :project, projects: [project1, project2]) }
|
||||
|
||||
new_runner_project = find_by_testid('unassigned-projects')
|
||||
|
||||
expect(page).to have_content('Failed unassigning runner from project')
|
||||
expect(new_runner_project).to have_content(project2.name)
|
||||
end
|
||||
let(:project_to_unassign) { project2 }
|
||||
let(:runner_project_to_unassign) { runner.runner_projects.find_by_project_id(project_to_unassign.id) }
|
||||
let(:delete_route_path) do
|
||||
admin_namespace_project_runner_project_path(
|
||||
id: runner_project_to_unassign,
|
||||
project_id: project_to_unassign,
|
||||
namespace_id: project_to_unassign.parent
|
||||
)
|
||||
end
|
||||
|
||||
context 'when project being disabled is runner owner project' do
|
||||
let_it_be(:runner) { create(:ci_runner, :project, projects: [project1, project2]) }
|
||||
before do
|
||||
visit edit_admin_runner_path(runner)
|
||||
end
|
||||
|
||||
let(:project_to_delete) { project2 }
|
||||
let(:runner_project_to_delete) { runner.runner_projects.find_by_project_id(project_to_delete.id) }
|
||||
let(:delete_route_path) do
|
||||
admin_namespace_project_runner_project_path(
|
||||
id: runner_project_to_delete,
|
||||
project_id: project_to_delete,
|
||||
namespace_id: project_to_delete.parent
|
||||
)
|
||||
it 'removes project runner from project' do
|
||||
within_testid('assigned-projects') do
|
||||
find("a[href='#{delete_route_path}']").click
|
||||
end
|
||||
|
||||
before do
|
||||
visit edit_admin_runner_path(runner)
|
||||
end
|
||||
new_runner_project = find_by_testid('unassigned-projects')
|
||||
|
||||
it 'removes project runner from project' do
|
||||
within_testid('assigned-projects') do
|
||||
find("a[href='#{delete_route_path}']").click
|
||||
end
|
||||
|
||||
new_runner_project = find_by_testid('unassigned-projects')
|
||||
|
||||
expect(page).to have_content('Runner unassigned from project.')
|
||||
expect(new_runner_project).to have_content(project_to_delete.name)
|
||||
end
|
||||
expect(page).to have_content('Runner unassigned from project.')
|
||||
expect(new_runner_project).to have_content(project_to_unassign.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const mockRunnerSha = mockRunner.shortSha;
|
|||
Vue.use(VueApollo);
|
||||
Vue.use(VueRouter);
|
||||
|
||||
describe('AdminRunnerShowApp', () => {
|
||||
describe('ProjectRunnerShowApp', () => {
|
||||
let wrapper;
|
||||
let mockRunnerQuery;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require_relative '../../../scripts/database/migration_checksum_checker'
|
||||
|
||||
RSpec.describe MigrationChecksumChecker, "#check", feature_category: :database do
|
||||
let(:db_migration_path) { 'spec/fixtures/migrations/db/migrate' }
|
||||
let(:checksum_dir_path) { 'spec/fixtures/migrations/db/schema_migrations' }
|
||||
let(:timestamp) { '20250320005730' }
|
||||
let(:migration_file) { "#{db_migration_path}/#{timestamp}_test_migration.rb" }
|
||||
let(:checksum_file) { "#{checksum_dir_path}/#{timestamp}" }
|
||||
let(:valid_checksum) { "85210d36999484fafe57284bc5c68985d68f48061530ff79429c84875a6420f2" }
|
||||
|
||||
before do
|
||||
stub_const('MigrationChecksumChecker::MIGRATION_DIRS', [db_migration_path])
|
||||
stub_const('MigrationChecksumChecker::CHECKSUM_DIR', checksum_dir_path)
|
||||
FileUtils.mkdir_p(db_migration_path)
|
||||
FileUtils.mkdir_p(checksum_dir_path)
|
||||
File.write(migration_file, "class TestMigration < ActiveRecord::Migration[7.0]; end")
|
||||
end
|
||||
|
||||
subject(:check) { described_class.new.check }
|
||||
|
||||
context "when all migrations have matching checksum files" do
|
||||
before do
|
||||
File.write(checksum_file, valid_checksum)
|
||||
end
|
||||
|
||||
after do
|
||||
File.delete(migration_file)
|
||||
File.delete(checksum_file)
|
||||
end
|
||||
|
||||
it { expect(check).to be_nil }
|
||||
end
|
||||
|
||||
context "when a migration is missing a checksum file" do
|
||||
after do
|
||||
File.delete(migration_file)
|
||||
end
|
||||
|
||||
it 'returns an error result' do
|
||||
expect(check.error_code).to eq(1)
|
||||
expect(check.error_message).to include('Missing checksum file for migration')
|
||||
expect(check.error_message).to include(migration_file)
|
||||
end
|
||||
end
|
||||
|
||||
context "when a migration has an empty checksum file" do
|
||||
before do
|
||||
File.write(checksum_file, "")
|
||||
end
|
||||
|
||||
after do
|
||||
File.delete(migration_file)
|
||||
File.delete(checksum_file)
|
||||
end
|
||||
|
||||
it 'returns an error result' do
|
||||
expect(check.error_code).to eq(1)
|
||||
expect(check.error_message).to include('Empty checksum file for migration')
|
||||
expect(check.error_message).to include(migration_file)
|
||||
end
|
||||
end
|
||||
|
||||
context "when a migration has a checksum file with invalid length" do
|
||||
before do
|
||||
File.write(checksum_file, "invalid_checksum_that_is_not_64_characters")
|
||||
end
|
||||
|
||||
after do
|
||||
File.delete(migration_file)
|
||||
File.delete(checksum_file)
|
||||
end
|
||||
|
||||
it 'returns an error result' do
|
||||
expect(check.error_code).to eq(1)
|
||||
expect(check.error_message).to include('Invalid checksum length for migration')
|
||||
expect(check.error_message).to include(migration_file)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with multiple migrations' do
|
||||
let(:timestamp2) { '20250325123456' }
|
||||
let(:migration_file2) { "#{db_migration_path}/#{timestamp2}_another_migration.rb" }
|
||||
|
||||
before do
|
||||
File.write(migration_file2, "class AnotherMigration < ActiveRecord::Migration[7.0]; end")
|
||||
File.write(checksum_file, valid_checksum)
|
||||
end
|
||||
|
||||
after do
|
||||
File.delete(migration_file)
|
||||
File.delete(migration_file2)
|
||||
File.delete(checksum_file)
|
||||
end
|
||||
|
||||
it 'reports only the missing checksum' do
|
||||
expect(check.error_message).to include(migration_file2)
|
||||
expect(check.error_message).not_to include(migration_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -176,13 +176,6 @@ RSpec.describe SemgrepResultProcessor, feature_category: :tooling do
|
|||
describe SemgrepResultProcessor do
|
||||
describe '#perform_allowlist_check' do
|
||||
let(:processor) { described_class.new }
|
||||
let(:original_env) { ENV.to_hash }
|
||||
|
||||
after do
|
||||
# Restore original environment after each test
|
||||
ENV.clear
|
||||
original_env.each { |k, v| stub_env(k, v) }
|
||||
end
|
||||
|
||||
context 'when CI_PROJECT_DIR is not allowlisted' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AutoMerge::AvailabilityCheck, feature_category: :shared do
|
||||
context 'with invalid status' do
|
||||
it { expect { described_class.new(status: :invalid) }.to raise_error(ArgumentError, 'Invalid status') }
|
||||
end
|
||||
|
||||
describe '.success' do
|
||||
it 'creates a success response without an unavailable_reason or unsuccessful_check' do
|
||||
expect(described_class.success).to be_truthy
|
||||
|
|
@ -26,8 +30,10 @@ RSpec.describe AutoMerge::AvailabilityCheck, feature_category: :shared do
|
|||
end
|
||||
|
||||
context 'without an unavailable reason' do
|
||||
it 'raises an argument error' do
|
||||
expect { described_class.error }.to raise_error(ArgumentError)
|
||||
it 'returns the default error' do
|
||||
response = described_class.error
|
||||
|
||||
expect(response.unavailable_reason).to eq(:default)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue