From c379dd7546f448b681087aea57ebdcbf36919599 Mon Sep 17 00:00:00 2001 From: Volodymyr Vreshch Date: Sun, 9 Aug 2026 01:41:44 +0200 Subject: [PATCH] fix(ci): deploy with a durable GHCR token so swarm can self-heal The deploy logs in with secrets.GITHUB_TOKEN and then runs "stack deploy --with-registry-auth", which freezes that credential into every service spec. GITHUB_TOKEN expires when the run ends, so from that moment Swarm cannot pull. Verified on a host: with the node itself logged in and able to pull manually, deleting a service image and scaling up still produced repeated "No such image" rejections. Swarm uses the spec credential, not config.json. GHCR_READ_TOKEN is a classic PAT scoped read:packages only, set as an agentage org secret. The build/push login keeps GITHUB_TOKEN, which needs write and is correctly ephemeral. --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b47361e..925ee46 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -103,7 +103,7 @@ jobs: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "mkdir -p /opt/agentage/ds" scp docker-compose.deploy.yml ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/opt/agentage/ds/docker-compose.yml - name: Login to GHCR on host - run: echo "${{ secrets.GITHUB_TOKEN }}" | ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "docker login ghcr.io -u ${{ github.actor }} --password-stdin" + run: echo "${{ secrets.GHCR_READ_TOKEN }}" | ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "docker login ghcr.io -u vreshch --password-stdin" - name: Deploy stack run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd /opt/agentage/ds && docker stack deploy -c docker-compose.yml agentage-ds --with-registry-auth" - name: Wait + live smoke