diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 5551d68..43ab953 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -442,12 +442,30 @@ jobs: echo "channel=dev" >> "$GITHUB_OUTPUT" 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/ 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 - uses: docker/login-action@v3 - with: - registry: git.fabledsword.com - username: ${{ github.actor }} - password: ${{ secrets.RELEASE_TOKEN }} + env: + TOKEN: ${{ secrets.RELEASE_TOKEN }} + ACTOR: ${{ github.actor }} + run: echo "$TOKEN" | docker login git.fabledsword.com -u "$ACTOR" --password-stdin - name: Build and push web image uses: docker/build-push-action@v5 @@ -490,12 +508,13 @@ jobs: echo "tags=git.fabledsword.com/bvandeusen/fabledcurator-ml:dev" >> "$GITHUB_OUTPUT" 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 - uses: docker/login-action@v3 - with: - registry: git.fabledsword.com - username: ${{ github.actor }} - password: ${{ secrets.RELEASE_TOKEN }} + env: + TOKEN: ${{ secrets.RELEASE_TOKEN }} + ACTOR: ${{ github.actor }} + run: echo "$TOKEN" | docker login git.fabledsword.com -u "$ACTOR" --password-stdin - name: Build and push ml image uses: docker/build-push-action@v5 @@ -528,12 +547,13 @@ jobs: echo "tags=git.fabledsword.com/bvandeusen/fabledcurator-agent:dev" >> "$GITHUB_OUTPUT" 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 - uses: docker/login-action@v3 - with: - registry: git.fabledsword.com - username: ${{ github.actor }} - password: ${{ secrets.RELEASE_TOKEN }} + env: + TOKEN: ${{ secrets.RELEASE_TOKEN }} + ACTOR: ${{ github.actor }} + run: echo "$TOKEN" | docker login git.fabledsword.com -u "$ACTOR" --password-stdin - name: Build and push agent image uses: docker/build-push-action@v5