Skip to content

fix(deploy,renovate): forward GITHUB_TOKEN to ghcr.io login on the host - #231

Merged
ineedjet merged 2 commits into
mainfrom
ghcr-token-login
Oct 12, 2026
Merged

ineedjet merged 2 commits into
mainfrom
ghcr-token-login

Conversation

@ineedjet

Copy link
Copy Markdown
Collaborator

Summary

  • docker compose pull fails with unauthorized on a private ghcr.io image, because the target host's Docker daemon is never authenticated for it - no registry login mechanism exists anywhere in the repo today.
  • Instead of minting and storing a separate long-lived registry credential as a new GitHub Secret, forward the Actions run's own GITHUB_TOKEN over the existing SSH connection and docker login ghcr.io (via stdin, never on the command line) right before docker compose pull - in both deploy.py (before pushing the release) and renovate.py (before each app's pull).
  • This only ever authenticates to ghcr.io - a private image published from a different repo under the same org/user needs that package's own "Manage Actions access" setting to grant read to this workflow's repository, since GITHUB_TOKEN doesn't carry further than that by default.
  • deploy's github-token input already existed (used for resolving release refs) and now does double duty. renovate's github-token input is new and optional - skipped entirely when unset, so existing callers are unaffected.

Test plan

  • python3 -m unittest discover -s tests passes in both .github/actions/deploy (59 tests) and .github/actions/renovate (21 tests), including new login_registry coverage (no-op without a token, correct docker login command, token delivered over stdin rather than the command line, default actor fallback, and ordering relative to the pull/push steps).
  • Verify against a real deploy once a private GHCR app is wired into a target, per No way to deploy/renovate images from a private registry (docker compose pull has no auth hook) #230.

Fixes #230
🤖 Generated with Claude Code

docker compose pull fails with unauthorized on a private ghcr.io image
because the target host's Docker daemon is never authenticated for it.
Forward the Actions run's own GITHUB_TOKEN over the existing SSH
connection and docker login ghcr.io before pulling, instead of minting
and storing a separate long-lived registry credential as a new GitHub
Secret.

Fixes #230

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Docker login persists and overwrites host credentials despite the documented no-disk guarantee.

2 open findings
What changed in this PR

Adds GHCR authentication to deployment and renovation flows so private container images can be pulled.

Changes:

  • Forwards GITHUB_TOKEN securely over SSH stdin.
  • Logs hosts into GHCR before image pulls.
  • Adds tests and usage documentation.
File Description
README.md Documents GHCR authentication.
AGENTS.md Updates deployment architecture guidance.
.github/​workflows/​renovate.yml Supplies the workflow token.
.github/​actions/​renovate/​action.yml Adds the optional token input.
.github/​actions/​renovate/​renovate.py Implements GHCR login.
.github/​actions/​renovate/​tests/​test_renovate.py Tests login and ordering.
.github/​actions/​renovate/​README.md Documents token usage.
.github/​actions/​deploy/​action.yml Expands the token contract.
.github/​actions/​deploy/​deploy.py Adds login before deployment.
.github/​actions/​deploy/​tests/​test_deploy.py Tests login and ordering.
.github/​actions/​deploy/​README.md Documents dual token usage.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +156 to +160
connection.run(
f"docker login ghcr.io -u {shlex.quote(actor)} --password-stdin",
hide=True,
in_stream=io.StringIO(token),
)
Comment on lines +61 to +65
connection.run(
f"docker login ghcr.io -u {shlex.quote(actor)} --password-stdin",
hide=True,
in_stream=io.StringIO(token),
)
Copilot review on #231 flagged that a plain `docker login` writes into
the host's default ~/.docker/config.json, leaving the short-lived
GITHUB_TOKEN on disk past the run and silently replacing whatever
ghcr.io credential was already configured there. Point DOCKER_CONFIG at
a throwaway directory for the login and the pull that follows instead,
and remove it in a finally block once done, even if the pull fails.

Also drops the #230 cross-references added in the previous commit, per
request - the behavior is documented on its own terms instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ineedjet
ineedjet merged commit 27a2e79 into main Oct 12, 2026
4 checks passed
@ineedjet
ineedjet deleted the ghcr-token-login branch October 12, 2026 11:14
@ineedjet ineedjet mentioned this pull request Oct 12, 2026
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.

No way to deploy/renovate images from a private registry (docker compose pull has no auth hook)

2 participants