Add user_initiated flag to MR pipeline creation requests

What does this MR do and why?

MR pipeline creation requests, the short-lived Redis entries behind the MR Pipelines tab's real-time creation states, don't record who started them. The tab alerts whenever the FAILED count grows, so "Pipeline creation failed. Please try again." shows up even when the failed attempt was started automatically on MR creation. In a project whose CI config produces no merge request pipelines, every MR greets its author with that alert. Based on the discussion in this thread, we decided that a failed automatic background attempt isn't a user error, and no message should show for it.

This MR is the backend half of the fix discussed in that thread.

Ci::PipelineCreation::Requests.start_for_merge_request now takes user_initiated: and hset writes id and user_initiated into the JSON value stored in Redis. The request hash already rides through Sidekiq args back into Requests.failed/succeeded, so both fields survive to completion with no extra reads. Requests have exactly one writer, CreatePipelineService#execute_async, with five callers:

execute_async caller Origin user_initiated
async REST run-pipeline endpoint, what the tab's "Run pipeline" button calls user true
/run_pipeline quick action user true
MR creation automatic false
push to the source branch automatic false
retarget after the target branch merges automatic false

GraphQL's CiPipelineCreationRequest exposes both new fields: userInitiated for the follow-up frontend MR to gate the alert on, and a nullable id so that we can persist per creation request dismissals for Dismissed pipeline creation failure alerts shou... (#612803 - closed).

How to set up and validate locally

  1. Trigger the automatic path from the rails console and read the stored request back. user_initiated is false:

    mr = MergeRequest.find(<id>)
    MergeRequests::CreatePipelineService
      .new(project: mr.project, current_user: mr.author, params: { allow_duplicate: true })
      .execute_async(mr)
    Ci::PipelineCreation::Requests.for_merge_request(mr)
    # => [{"status"=>"in_progress", "id"=>"<uuid>", "user_initiated"=>false}]
  2. Trigger a user path: select "Run pipeline" on the MR's Pipelines tab, comment /run_pipeline on the MR, or POST /api/v4/projects/:id/merge_requests/:iid/pipelines?async=true. Reading the requests back now shows the new entry with "user_initiated"=>true.

  3. Within 5 minutes (the Redis TTL), query the new fields in /-/graphql-explorer:

    {
      project(fullPath: "<full-path>") {
        mergeRequest(iid: "<iid>") {
          pipelineCreationRequests {
            id
            status
            userInitiated
          }
        }
      }
    }
  4. Requests created before this branch (or with the JSON fields stripped from Redis by hand) return "id" => nil and "userInitiated" => true.

References

Edited by Sahil Sharma

Merge request reports

Loading
Loading