Chapter 14Lesson 05~305 minutes

Checkpoint Lab — GitLab Runners, Executors, Tags, Registration, Autoscaling, Isolation, and Security

Map job-to-runner eligibility in a disposable project, capture one intentional pending-job failure, optionally prove an isolated local runner path, and verify complete runner/config cleanup.

CheckpointEligibility matrixEvidenceOptional registrationCleanupChapter 15 bridge

Learning objectives

  • Create a job-to-runner eligibility matrix before executing any pipeline.
  • Prove one successful or statically validated free-compatible route and one intentionally pending tag-mismatch route.
  • Explain the exact eligibility predicate responsible for the pending job using two independent evidence views.
  • Optionally register one isolated project runner and prove that only the tagged synthetic job routes to it.
  • Clean up runner manager/configuration, GitLab runner records, synthetic refs, and pipeline configuration with verifiable evidence.
Availability baseline (verified 2026-08-21 against current GitLab documentation). GitLab Runner, project/group/instance runner scopes, tags, protected runners, the supported executor framework, and self-managed runners are available across Free/Premium/Ultimate. GitLab-hosted runners are a GitLab.com service and are also available for GitLab Dedicated under a separately provisioned Limited Availability offering; Self-Managed installations provide their own runner infrastructure. Hosted-runner compute can be quota/billing constrained, so every mandatory exercise has a no-runner/static or evidence-fixture path. Legacy runner registration tokens are deprecated and scheduled for removal in GitLab 20.0; this chapter teaches the modern runner creation workflow with runner authentication tokens.

1. Checkpoint mission

You are responsible for a small disposable project with two classes of CI work:

  1. a harmless general verification job that may use an existing hosted/untagged runner; and
  2. a capability-specific job that must never run unless a runner explicitly advertises ch14-isolated.

Your job is to predict which runner is eligible, prove the selection logic, deliberately create one pending condition, repair it without weakening a runner, and produce a credential-free evidence packet. Registering your own runner is optional.

2. Preflight and assumptions

Item Requirement
Project Disposable project only; recommended gitlab-ch14-checkpoint.
Tier Free mandatory path. No Premium/Ultimate feature required.
Offering GitLab.com easiest for hosted-runner path; Self-Managed/Dedicated use visible runner capacity or the fixture path.
Role Developer for branch/pipeline work; Maintainer if creating optional project runner.
Runner host Optional only: disposable isolated VM/container host with no production credentials/network.
Compute Tiny jobs; if quota/capacity unavailable, use CI Lint + runner inventory + expected-state evidence.
Secrets None. Runner auth token, if used, is handled interactively on the runner host and never recorded.

3. Capture baseline runner inventory

Before editing YAML, capture two independent views:

  • UI: Settings → CI/CD → Runners.
  • API: project-visible runner metadata.
PROJECT_ID="12345678"
glab api "projects/$PROJECT_ID/runners" --paginate \
  --jq '.[] | {id, description, runner_type, status, paused, tag_list}' 

Record runner IDs and tags, but no tokens. If the project shows zero usable runners, mark the successful execution step as “static/no-compute” and continue.

4. Write the prediction ledger before the pipeline

Job Requested tags Expected candidate Prediction
general_probe none Any visible runner configured for untagged work. Runs if such a runner/capacity exists; otherwise remains pending for an understood reason.
isolated_probe ch14-isolated Only a runner containing that tag. Pending initially because baseline inventory intentionally lacks the tag.

Also predict two state changes: the push creates a pipeline bound to the new commit SHA; the mismatched job enters pending without executing its script.

5. Build the smallest checkpoint configuration

stages: [verify]

general_probe:
  stage: verify
  script:
    - printf 'probe=general\n'
    - printf 'source=%s\n' "$CI_PIPELINE_SOURCE"
    - printf 'sha=%s\n' "$CI_COMMIT_SHA"
    - printf 'runner_id=%s\n' "$CI_RUNNER_ID"
    - printf 'runner_tags=%s\n' "$CI_RUNNER_TAGS"

isolated_probe:
  stage: verify
  tags: [ch14-isolated]
  script:
    - printf 'probe=isolated\n'
    - printf 'sha=%s\n' "$CI_COMMIT_SHA"
    - printf 'runner_id=%s\n' "$CI_RUNNER_ID" 

The configuration prints only safe pipeline/runner metadata. It does not dump all environment variables, tokens, host mounts, network routes, or runner configuration.

6. Validate, commit, and bind evidence to SHA

Use CI Lint/Pipeline Editor first. Then:

git switch -c ch14/checkpoint
git add .gitlab-ci.yml
git diff --cached --check
git diff --cached
git commit -m "ch14: runner eligibility checkpoint"
CHECKPOINT_SHA="$(git rev-parse HEAD)"
printf 'checkpoint_sha=%s\n' "$CHECKPOINT_SHA"
git push -u origin ch14/checkpoint

Record pipeline ID/source/ref/SHA. If general_probe runs, record the runner ID and compare it to the baseline inventory. If it remains pending because no compute is available, document that as a capacity/availability observation rather than changing security controls.

7. Prove the intentional pending job from two views

View 1 — job: isolated_probe requests ch14-isolated and is pending. View 2 — runner inventory: no available runner contains that tag. The two views establish causality without executor logs.

# Read-only job/pipeline discovery pattern; exact IDs come from your disposable run.
glab ci status
# Or inspect through the GitLab UI: Build > Pipelines > pipeline > isolated_probe.

Do not “fix” this checkpoint by adding the tag to a broad production runner. The expected result is a controlled failure.

8. Free-compatible repair without registering anything

For the mandatory path, repair the synthetic configuration by removing the impossible tag from isolated_probe or converting it to a fixture-only/manual example. Commit the change as a new commit so the failed pipeline remains auditable.

git add .gitlab-ci.yml
git diff --cached --check
git commit -m "ch14: repair synthetic runner selector"
REPAIR_SHA="$(git rev-parse HEAD)"
printf 'repair_sha=%s\n' "$REPAIR_SHA"
git push

Prediction: both jobs now share the same untagged runner eligibility. Verification: the repaired pipeline is bound to REPAIR_SHA, not the original failed SHA.

9. Optional extension: satisfy the selector with isolated capacity

Optional self-managed lab. Use a disposable isolated host only. Do not attach it to production networks, mount the host Docker socket into job containers, enable privileged mode, or give it real deployment credentials.
  1. Create a project runner in the disposable project with tag ch14-isolated, Run untagged disabled, and a clear lab-only description.
  2. On the isolated host, register it with the runner authentication token and Docker executor.
  3. Run sudo gitlab-runner verify without printing config.toml.
  4. Restore the original two-job checkpoint YAML. Predict that isolated_probe routes only to this runner.
  5. Verify the job's CI_RUNNER_ID matches the new runner record.
read -rsp "Runner authentication token: " RUNNER_AUTH_TOKEN; echo
sudo gitlab-runner register \
  --non-interactive \
  --url "https://gitlab.com/" \
  --token "$RUNNER_AUTH_TOKEN" \
  --executor docker \
  --docker-image "alpine:3.22"
unset RUNNER_AUTH_TOKEN
sudo gitlab-runner verify

10. Protection prediction without weakening a runner

Use a written fixture if you do not own a second disposable runner:

Runner Protected? Tags Job ref Eligible?
R1 No [linux] unprotected branch, job tags [linux] Yes if scope/status/capacity match.
R2 Yes [deploy] unprotected branch, job tags [deploy] No — protected policy rejects the ref.
R2 Yes [deploy] protected release branch, job tags [deploy] Potentially yes; still verify user/ref/project policy.
R3 No [linux,gpu] job tags [linux] Yes — extra runner tags are allowed.
R3 No [linux,gpu] job tags [linux,gpu,cuda12] No — runner lacks one required tag.

This satisfies the protected-runner reasoning goal without changing a valuable protected runner.

11. Credential-free evidence packet

Produce a short record containing:

  • GitLab offering/version line used for the lab.
  • Project path and synthetic branch name.
  • Baseline runner IDs/types/status/tags only.
  • Original checkpoint commit SHA and pipeline/job IDs.
  • Prediction table.
  • Screenshot/text of the pending job's requested tag and a separate runner inventory showing no match.
  • Repair commit SHA and new pipeline result.
  • If optional runner used: runner ID/description/tag/executor class and cleanup proof—never authentication token/config file.

12. Cleanup and rollback

After evidence capture:

# Restore the repository state you want to keep, then remove the synthetic branch.
git switch main
git push origin --delete ch14/checkpoint
git branch -D ch14/checkpoint

If you created the optional runner: pause it first, unregister the runner manager from the disposable host, delete the runner object from the project's Runners UI, then destroy the VM/container/config volume. Confirm it no longer appears in runner inventory. Cancel any intentionally pending synthetic job before deleting the branch.

Deletion warning. Do not use broad runner deletion commands such as --all-runners on a host that manages anything except this disposable lab. Target the lab runner by its unique name and verify the selected configuration first.

13. Final verification checklist

  • The ZIP/course lab never required a paid tier or production runner.
  • The expected eligibility matrix was written before execution.
  • The pending job was explained by two independent observations.
  • The original failure remains preserved; repair used a new commit rather than history rewrite.
  • No token, secret, full environment, runner config, private network data, or host credential appears in evidence.
  • The optional runner, runner manager, host/config volume, and synthetic branch are all removed.
  • Any remaining pipeline is tied to an intentional repository commit and has no external side effect.

14. What Chapter 14 adds to the operating model

The production model now has an explicit compute authorization layer. GitLab decides that a job exists; runner scope/tags/protection decide which execution fleet may accept it; the executor and host/network/cache design determine what that code can affect. This closes the loop from Chapter 13's variable authorization to actual code execution.

15. Bridge to Chapter 15

Chapter 15 moves from where jobs run to how many jobs may run concurrently and in what dependency order: DAG pipelines, needs, parallel jobs/matrices, resource groups, and concurrency. Runner capacity and isolation are prerequisites for reasoning correctly about pipeline throughput.

Knowledge check

Why was the pending job considered a successful checkpoint result?

What two observations prove a tag mismatch?

Why does the repair use a new commit instead of rewriting the failed commit?

What extra cleanup is required after unregistering a modern UI-created runner manager?

Why can an untagged hosted runner be used for the mandatory path but not assumed to exist?

What does Chapter 15 depend on from this chapter?

Summary

The checkpoint proved runner governance without privileged production infrastructure: inventory first, predict eligibility, run or statically validate the safe path, preserve an intentional pending job, identify the exact failed predicate, repair only the synthetic selector, and clean up both repository and runner state. Runner selection is now an auditable part of the GitLab delivery model.

Official references

Chapter 15

DAG Pipelines, needs, Parallel Jobs, Matrices, Resource Groups, and Concurrency

Next you will use the runner-capacity model to reason about dependency graphs, parallel work, serialization, and controlled concurrency without confusing scheduler topology with runner availability.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.