Reusable workflow that builds a Docker image from a Python / uv project and optionally pushes it to GCP Artifact Registry. Credentials are read from 1Password — only OP_SERVICE_ACCOUNT_TOKEN is passed as a secret; everything else is fetched and masked at runtime.
Replace
<current-sha>with the current SHA from the root README.
on: [pull_request]
jobs:
docker-build:
uses: orangitfi/platform-tooling/.github/workflows/python-build-and-publish-docker.yml@<current-sha>
with:
image-name: my-apion:
push:
branches: [main]
jobs:
docker-publish:
uses: orangitfi/platform-tooling/.github/workflows/python-build-and-publish-docker.yml@<current-sha>
with:
image-name: my-api
project-id: my-gcp-project
registry-repo: my-repo
gcp-sa-key-op-ref: op://my-vault/gcp-sa/service-account-key
publish: true
secrets:
op-service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}jobs:
docker:
uses: orangitfi/platform-tooling/.github/workflows/python-build-and-publish-docker.yml@<current-sha>
with:
image-name: my-api
project-id: my-gcp-project
registry-repo: my-repo
gcp-sa-key-op-ref: op://my-vault/gcp-sa/service-account-key
publish: ${{ github.ref == 'refs/heads/main' }}
secrets:
op-service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}| Input | Default | Description |
|---|---|---|
image-name |
required | Image name without registry prefix or tag |
working-directory |
. |
Docker build context directory |
dockerfile-path |
Dockerfile |
Path to the Dockerfile relative to working-directory |
region |
europe-north1 |
GCP region of the Artifact Registry |
project-id |
— | GCP project ID — required when publish: true |
registry-repo |
— | Artifact Registry repository name — required when publish: true |
gcp-sa-key-op-ref |
— | 1Password reference to the GCP SA key JSON — required when publish: true |
publish |
false |
Push the image to Artifact Registry after a successful build |
| Secret | Description |
|---|---|
op-service-account-token |
1Password service account token — required when publish: true |
When publish: false (default):
- Builds the Docker image locally with a
git-<sha>-buildtag - Cleans up the local image
When publish: true:
- Validates that
project-id,registry-repo, andgcp-sa-key-op-refare all provided - Reads the GCP service account key from 1Password and masks it immediately with
::add-mask:: - Logs in to Artifact Registry
- Builds the Docker image
- Tags and pushes both
git-<sha>(pinned, immutable) andlatest - Logs out from the registry
- Cleans up all local images
- Unified Dockerfile validation: the same workflow validates the Dockerfile on PRs (build only) and publishes on merge — one definition to maintain
- Immutable image tags:
git-<sha>tags make every pushed image fully traceable back to the exact commit. You can redeploy any version by its SHA tag without guessing - 1Password integration: the GCP SA key is never stored in GitHub Secrets — it is fetched at runtime and masked before use, invisible in logs
- The
publish: ${{ github.ref == 'refs/heads/main' }}pattern is the recommended way to enable push only on the main branch while reusing the samewith:block. - For FastAPI / Django projects, ensure the Dockerfile does
uv sync --frozen(notpip install -r requirements.txt) so the Docker image also uses the committed lockfile. - Images are cleaned up in an
if: always()step so a failed scan or push never leaves dangling images on the runner. - The
gcp-sa-key-op-reffollows the 1Password CLI secret reference format:op://<vault>/<item>/<field>. Example:op://ci-secrets/gcp-artifact-registry/service-account-key.