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)