ci: log in to the registry with the docker CLI, not docker/login-action
Build images / sign-extension (push) Successful in 4s
CI / lint (push) Successful in 6s
CI / extension-version (push) Successful in 6s
CI / frontend-build (push) Successful in 28s
CI / backend-lint-and-test (push) Successful in 32s
extension / lint (push) Successful in 45s
Build images / build-web (push) Successful in 2m21s
Build images / build-ml (push) Successful in 2m59s
CI / integration (push) Successful in 4m9s
Build images / build-agent (push) Failing after 10m58s
extension / lint (pull_request) Successful in 27s
Build images / sign-extension (push) Successful in 4s
CI / lint (push) Successful in 6s
CI / extension-version (push) Successful in 6s
CI / frontend-build (push) Successful in 28s
CI / backend-lint-and-test (push) Successful in 32s
extension / lint (push) Successful in 45s
Build images / build-web (push) Successful in 2m21s
Build images / build-ml (push) Successful in 2m59s
CI / integration (push) Successful in 4m9s
Build images / build-agent (push) Failing after 10m58s
extension / lint (pull_request) Successful in 27s
build-ml failed at the login step twice ona7e626a, five seconds in, with MODULE_NOT_FOUND on the action's own dist/index.js. Not the token — the secret resolved to *** and the action never ran far enough to use it. The cause is a race in act_runner's shared action cache, not corruption. A remote action is cached at one /root/.cache/act/<hash> per runner, and build-web, build-ml and build-agent all start in the same second and all want docker/login-action@v3. One job re-clones that directory — emptying and repopulating it — while another walks it to copy into its container, and the walker lstat()s a file that just vanished. The two failures named DIFFERENT missing files, eslint.config.mjs then jest.config.ts, which is what rules out a bad cache entry and points at the race: a dangling entry would name the same file every time. Re-running does not help, because the re-run starts the three jobs simultaneously again. It reproduced immediately. Dropping the action removes FC from that race for this step. Logging in is one command, the docker CLI is already in the CI image per ci-requirements.md, and the same reasoning as family rule 5 applies: a marketplace action buys nothing when the tool is baked into the image the workflow already selected. Password on stdin, never as an argument — an argument lands in the process table and draws docker's own deprecation warning. This narrows the exposure rather than closing it. All three jobs also share docker/build-push-action@v5 and can race on it the same way; that one has not lost yet, and replacing it means hand-rolling buildx invocation including the build-args and provenance handling, which is a bigger change than this failure justifies. Recorded on #3118. Live consequence being cleared: fabledcurator-ml:dev was left a commit behind fabledcurator:dev, which is the stale-pairing trap the trigger comment on239b1edwarns about.
This commit is contained in:
@@ -442,12 +442,30 @@ jobs:
|
|||||||
echo "channel=dev" >> "$GITHUB_OUTPUT"
|
echo "channel=dev" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# A shell step, not docker/login-action@v3, because the action's shared
|
||||||
|
# cache races itself (#3118). act_runner caches a remote action under one
|
||||||
|
# /root/.cache/act/<hash> per runner, and build-web, build-ml and
|
||||||
|
# build-agent all start in the same second and all want this same action.
|
||||||
|
# One job re-clones the directory — which empties and repopulates it —
|
||||||
|
# while another is walking it to copy into its container, and the walker
|
||||||
|
# lstat()s a file that has just vanished. It failed twice on 2026-08-27,
|
||||||
|
# naming a DIFFERENT missing file each time (`eslint.config.mjs`, then
|
||||||
|
# `jest.config.ts`), which is what rules out a corrupt cache and points at
|
||||||
|
# a race. The loser dies with MODULE_NOT_FOUND on dist/index.js before the
|
||||||
|
# action runs at all, so the secret is never even reached.
|
||||||
|
#
|
||||||
|
# Nothing is lost by dropping it: logging in is one command, the docker
|
||||||
|
# CLI is already in the CI image (ci-requirements.md), and the same
|
||||||
|
# reasoning as family rule 5 applies — a marketplace action buys nothing
|
||||||
|
# when the tool is baked into the image the workflow already selected.
|
||||||
|
#
|
||||||
|
# Password on stdin, never as an argument: an argument lands in the
|
||||||
|
# process table and draws docker's own deprecation warning.
|
||||||
- name: Login to Forgejo registry
|
- name: Login to Forgejo registry
|
||||||
uses: docker/login-action@v3
|
env:
|
||||||
with:
|
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
registry: git.fabledsword.com
|
ACTOR: ${{ github.actor }}
|
||||||
username: ${{ github.actor }}
|
run: echo "$TOKEN" | docker login git.fabledsword.com -u "$ACTOR" --password-stdin
|
||||||
password: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push web image
|
- name: Build and push web image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
@@ -490,12 +508,13 @@ jobs:
|
|||||||
echo "tags=git.fabledsword.com/bvandeusen/fabledcurator-ml:dev" >> "$GITHUB_OUTPUT"
|
echo "tags=git.fabledsword.com/bvandeusen/fabledcurator-ml:dev" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Shell step rather than docker/login-action — see build-web's note on
|
||||||
|
# the shared action-cache race (#3118).
|
||||||
- name: Login to Forgejo registry
|
- name: Login to Forgejo registry
|
||||||
uses: docker/login-action@v3
|
env:
|
||||||
with:
|
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
registry: git.fabledsword.com
|
ACTOR: ${{ github.actor }}
|
||||||
username: ${{ github.actor }}
|
run: echo "$TOKEN" | docker login git.fabledsword.com -u "$ACTOR" --password-stdin
|
||||||
password: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push ml image
|
- name: Build and push ml image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
@@ -528,12 +547,13 @@ jobs:
|
|||||||
echo "tags=git.fabledsword.com/bvandeusen/fabledcurator-agent:dev" >> "$GITHUB_OUTPUT"
|
echo "tags=git.fabledsword.com/bvandeusen/fabledcurator-agent:dev" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Shell step rather than docker/login-action — see build-web's note on
|
||||||
|
# the shared action-cache race (#3118).
|
||||||
- name: Login to Forgejo registry
|
- name: Login to Forgejo registry
|
||||||
uses: docker/login-action@v3
|
env:
|
||||||
with:
|
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
registry: git.fabledsword.com
|
ACTOR: ${{ github.actor }}
|
||||||
username: ${{ github.actor }}
|
run: echo "$TOKEN" | docker login git.fabledsword.com -u "$ACTOR" --password-stdin
|
||||||
password: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push agent image
|
- name: Build and push agent image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
|
|||||||
Reference in New Issue
Block a user