Skip to content

fix: introduce per-job cert volume with %gcl% token - #1877

Merged
firecow merged 1 commit into
firecow:masterfrom
ticapix:fix/per-job-cert-volume
Jun 23, 2026
Merged

fix: introduce per-job cert volume with %gcl% token#1877
firecow merged 1 commit into
firecow:masterfrom
ticapix:fix/per-job-cert-volume

Conversation

@ticapix

@ticapix ticapix commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Hello,

This addresses #918

Jobs using docker:dind as a service share TLS client certificates via a named volume. The previous approach relied on a static volume name (e.g. certs) configured in .gitlab-ci-local-env, which caused race conditions when concurrent jobs wrote to and cleaned up the same volume, each dind service writing its own certificates.

A new %gcl-cert%: prefix in VOLUME entries is now resolved at runtime to a per-job unique volume name (gcl-<job>-<id>-cert), matching the naming pattern of the existing build/tmp volumes.
The %gcl-cert% token was chosen because Docker hard-rejects it if it ever reaches the daemon unsubstituted (invalid volume name character), rather than silently bind-mounting an unintended host path.

Changes:

  • get certVolumeName() getter returning a per-job unique name
  • Cert volume is created and registered for cleanup alongside build/tmp volumes when any %gcl-cert%: entry is present in argv.volume
  • %gcl-cert%: prefix is resolved to certVolumeName in both the job container and service container volume loops

I'm not sure how to add a test.

I used this config to test the implementation

docker1:
  stage: test
  image: docker:29-cli
  services:
    - docker:29-dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - docker info

docker2:
  stage: test
  image: docker:29-cli
  services:
    - docker:29-dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
  script:
    - docker info

The .gitlab-ci-local-env looks like

PRIVILEGED=true
ULIMIT=8000:16000
VOLUME=%gcl-cert%:/certs/client
VARIABLE="DOCKER_TLS_CERTDIR=/certs"

Summary by cubic

Adds a per-job cert volume for Docker-in-Docker by introducing a %gcl-cert%: volume token. This prevents cross-job TLS cert races and cleanup conflicts when jobs run in parallel.

  • Bug Fixes

    • Create and track certVolumeName (gcl-<job>-<id>-cert) when any argv.volume starts with %gcl-cert%:, matching build/tmp naming.
    • Resolve %gcl-cert%: to the per-job name for both job and service --volume flags before invoking Docker, avoiding accidental host bind mounts.
  • Migration

    • Replace a static cert volume like certs:/certs/client with %gcl-cert%:/certs/client to enable per-job isolation.

Written for commit 96b49ce. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Re-trigger cubic

Jobs using docker:dind as a service share TLS client certificates via a
named volume. The previous approach relied on a static volume name (e.g.
`certs`) configured in .gitlab-ci-local-env, which caused race conditions
when concurrent jobs wrote to and cleaned up the same volume.

A new `%gcl-cert%:` prefix in VOLUME entries is now resolved at runtime to a
per-job unique volume name (`gcl-<job>-<id>-cert`), matching the naming
pattern of the existing build/tmp volumes. The `%gcl-cert%` token was chosen
because Docker hard-rejects it if it ever reaches the daemon unsubstituted
(invalid volume name character), rather than silently bind-mounting an
unintended host path.

Changes:
- get certVolumeName() getter returning a per-job unique name
- Cert volume is created and registered for cleanup alongside build/tmp
  volumes when any %gcl-cert%: entry is present in argv.volume
- %gcl-cert%: prefix is resolved to certVolumeName in both the job container
  and service container volume loops
Comment thread src/job.ts Outdated
@ticapix
ticapix force-pushed the fix/per-job-cert-volume branch from e3fcf9a to 96b49ce Compare June 22, 2026 20:49
@firecow
firecow merged commit cfc7aaf into firecow:master Jun 23, 2026
13 checks passed
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Aug 11, 2026
This MR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
| [npm:gitlab-ci-local](https://github.com/firecow/gitlab-ci-local) | `4.73.0` → `4.74.0` | ![age](https://developer.mend.io/api/mc/badges/age/npm/gitlab-ci-local/4.74.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/gitlab-ci-local/4.74.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/gitlab-ci-local/4.73.0/4.74.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/gitlab-ci-local/4.73.0/4.74.0?slim=true) |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>firecow/gitlab-ci-local (npm:gitlab-ci-local)</summary>

### [`v4.74.0`](https://github.com/firecow/gitlab-ci-local/releases/tag/4.74.0)

[Compare Source](firecow/gitlab-ci-local@4.73.0...4.74.0)

#### What's Changed

- fix: introduce per-job cert volume with %gcl% token by [@&#8203;ticapix](https://github.com/ticapix) in [#&#8203;1877](firecow/gitlab-ci-local#1877)
- fix: pull registry probe image before the timed readiness check by [@&#8203;firecow](https://github.com/firecow) in [#&#8203;1904](firecow/gitlab-ci-local#1904)
- fix(parser): anchor comment directives correctly and quote injected descriptions by [@&#8203;firecow](https://github.com/firecow) in [#&#8203;1896](firecow/gitlab-ci-local#1896)

**Full Changelog**: <firecow/gitlab-ci-local@4.73.0...4.74.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODguMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants