CI Lint with pipeline simulation option causes 500 when default branch last pipeline was skipped
Summary
We are experiencing some 500 errors on our Siemens self-hosted setup when users try to use the CI Lint with the simulate pipeline option activated, when also the last commit caused a skipped pipeline. Normal linting without the simulate pipeline option works.
Steps to reproduce
- Make a commit to the default branch of a project with a message that will skip the pipeline, e.g.
[skip ci] foobar - Try to check any content on CI Lint activating the pipeline simulation
Probable cause
On lib/gitlab/ci/pipeline/chain/skip.rb, the skipped? condition is true when the last commit has a skipped pipeline (or when push options skip the pipeline):
def perform!
if skipped?
@pipeline.skip if @command.save_incompleted
end
end
@pipeline.skip seems to cause an actual change on the active record model, but the pipeline object is set to read-only earlier in the chain on app/services/ci/create_pipeline_service.rb:
# Ensure we never persist the pipeline when dry_run: true
@pipeline.readonly! if command.dry_run?
Changing the order of the chained commands might be a solution, running Gitlab::Ci::Pipeline::Chain::Skip after Gitlab::Ci::Pipeline::Chain::StopDryRun.
Details
The actual exception raised:
...
"exception.message": "Ci::Pipeline is marked as readonly",
"exception.class": "ActiveRecord::ReadOnlyRecord",
"controller": "Projects::Ci::LintsController",
"exception.backtrace": [
"lib/gitlab/ci/pipeline/chain/skip.rb:14:in `perform!'",
"lib/gitlab/ci/pipeline/chain/sequence.rb:19:in `block in build!'",
"lib/gitlab/ci/pipeline/chain/sequence.rb:16:in `each'",
"lib/gitlab/ci/pipeline/chain/sequence.rb:16:in `build!'",
"app/services/ci/create_pipeline_service.rb:80:in `execute'",
"lib/gitlab/ci/lint.rb:38:in `simulate_pipeline_creation'",
"lib/gitlab/ci/lint.rb:27:in `validate'",
"app/controllers/projects/ci/lints_controller.rb:18:in `create'",
"app/controllers/application_controller.rb:491:in `set_current_admin'",
"lib/gitlab/session.rb:11:in `with_session'",
"app/controllers/application_controller.rb:482:in `set_session_storage'",
"lib/gitlab/i18n.rb:73:in `with_locale'",
"lib/gitlab/i18n.rb:79:in `with_user_locale'",
"app/controllers/application_controller.rb:476:in `set_locale'",
"lib/gitlab/error_tracking.rb:52:in `with_context'",
"app/controllers/application_controller.rb:541:in `sentry_context'",
"app/controllers/application_controller.rb:469:in `block in set_current_context'",
"lib/gitlab/application_context.rb:52:in `block in use'",
"lib/gitlab/application_context.rb:52:in `use'",
"lib/gitlab/application_context.rb:20:in `with_context'",
"app/controllers/application_controller.rb:462:in `set_current_context'",
"lib/gitlab/metrics/elasticsearch_rack_middleware.rb:16:in `call'",
"lib/gitlab/middleware/rails_queue_duration.rb:33:in `call'",
"lib/gitlab/metrics/rack_middleware.rb:16:in `block in call'",
"lib/gitlab/metrics/transaction.rb:61:in `run'",
"lib/gitlab/metrics/rack_middleware.rb:16:in `call'",
"lib/gitlab/request_profiler/middleware.rb:17:in `call'",
"lib/gitlab/jira/middleware.rb:19:in `call'",
"lib/gitlab/middleware/go.rb:20:in `call'",
"lib/gitlab/etag_caching/middleware.rb:13:in `call'",
"lib/gitlab/middleware/multipart.rb:217:in `call'",
"lib/gitlab/middleware/read_only/controller.rb:51:in `call'",
"lib/gitlab/middleware/read_only.rb:18:in `call'",
"lib/gitlab/middleware/same_site_cookies.rb:27:in `call'",
"lib/gitlab/middleware/basic_health_check.rb:25:in `call'",
"lib/gitlab/middleware/handle_ip_spoof_attack_error.rb:25:in `call'",
"lib/gitlab/middleware/request_context.rb:23:in `call'",
"config/initializers/fix_local_cache_middleware.rb:9:in `call'",
"lib/gitlab/metrics/requests_rack_middleware.rb:60:in `call'",
"lib/gitlab/middleware/release_env.rb:12:in `call'"
],
...