Send runner info with the verify request

What does this MR do?

gitlab-runner verify now sends the runner's info payload (version, platform, architecture, executor and features) alongside the token and system ID, matching what POST /runners and POST /jobs/request already send.

Why was this MR needed?

GitLab creates the Ci::RunnerManager record from the first authenticated request it receives, via ensure_manager. When that request carries no info, get_runner_details_from_request returns only the IP address, so the record is created with runtime_features empty.

verify sent no info, and it is the first call a fresh runner makes. The Helm chart runs it in the entrypoint before gitlab-runner run, and register calls it for glrt- authentication tokens.

GitLab then persists runner manager details at most once per 40 to 55 minutes (UPDATE_CONTACT_COLUMN_EVERY), and the verify heartbeat has already stamped contacted_at, which closes that window. runtime_features is not in the cached_attr_reader set, so the read hits the database rather than the cache.

The effect is that for at least 40 minutes after every runner pod starts, GitLab reads cancel_gracefully as false. Cancelling a job then transitions it straight to canceled instead of canceling, which invalidates the job token. The runner's next trace PATCH returns 403, which IsFailed treats as fatal and escalates to Abort rather than a graceful cancel. Abort cancels the parent build context, and since the after_script context is a sibling of the script context derived from that parent, after_script dies immediately with context canceled and never runs.

Sending info on verify means the record is created with capabilities already populated, so the window never opens. This needs no GitLab-side or chart change.

Despite the issue title this is not Kubernetes-specific; the capability check is executor-independent, and the Kubernetes executor only makes it noisier in the logs because its cancellation script execs with the build context.

Note that register calls verify before the executor is chosen, so the record can be created with executor_type: unknown until the next persist window, where today it is created as null. RegisterRunner has the same limitation and an existing // TODO: pass executor.

What's the best way to test this MR?

go test ./network/ -run TestGitLabClient_VerifyRunner_TransmitsRunnerInfo

Manually: register a runner, then read runtime_features on the freshly created runner manager record. It should contain cancel_gracefully immediately, rather than staying empty for the first 40 to 55 minutes. End to end, deploy the runner chart fresh and cancel a job with an after_script within 40 minutes of pod start; after_script is skipped before this change and runs after it.

Unrelated to this MR: common.TestBuildVariablesAsFileType currently fails on main (verified at 8199ceef2d, passing at 122e9218c7) and is not listed in .flaky-tests.txt.

What are the relevant issue numbers?

Closes #39657 (closed)

Merge request reports

Loading