Publish images under the repository owner and restrict workflow permissions - #50
Merged
Conversation
github.actor is the user who triggered the run, so a push to master or a tag made by anyone other than the repository owner built image names in that person's namespace, and the ghcr.io and Docker Hub logins were attempted with their username against the repository secrets. github.repository_owner keeps the canonical images at ghcr.io/umputun/baseimage/* and umputun/baseimage while forks still publish into the fork owner's own namespace. The Docker Hub half takes its owner from the DOCKERHUB_OWNER repository variable when set, so a fork whose Docker Hub account differs from its GitHub owner can point it at the right account without touching the workflow.
The workflow had no top-level permissions block, so the merge job ran with whatever the repository default grants; it now starts from contents: read, with packages: write added back where images are pushed. The push trigger listed branches and tags with no values, which works but fails actionlint as an empty string; ["**"] states the same intent and keeps the workflow clean under actionlint, along with quoting $GITHUB_OUTPUT and marking the two manifest expansions that have to word-split.
umputun
approved these changes
Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two changes to the build workflow.
Image owner.
github.actoris the account that triggered the run, not the owner of the repository, so a push tomasteror a tag made by anyone else, a collaborator or a bot, builds image names in that account's namespace and attempts the ghcr.io and Docker Hub logins with that username against this repository's secrets. Pushes triggered by you hide the problem, because there both values are identical.github.repository_ownerkeeps the canonical images exactly where they are,ghcr.io/umputun/baseimage/*andumputun/baseimage, and it preserves the part of the current behaviour that makes sense: whoever runs a fork still publishes into their own namespace. The Docker Hub half takes its owner from aDOCKERHUB_OWNERrepository variable when one is set and falls back to the repository owner otherwise, so a fork whose Docker Hub account name differs from its GitHub owner can point it at the right account without editing the workflow. With no variable set, nothing changes here.Permissions and lint. The workflow had no top-level
permissionsblock, so themergejob ran with whatever the repository default grants. It now starts fromcontents: read, withpackages: writeadded back on both jobs that push images. Thepushtrigger listedbranchesandtagswith no values, which behaves as match-all but failsactionlintas an empty string;["**"]states the same intent. Together with quoting$GITHUB_OUTPUTand marking the two manifest expansions that have to word-split,actionlintis now clean on the workflow.Action version bumps are left to the open dependabot PR #49.