ci: publish the production image to Harbor on merges to main - #87
Merged
Conversation
CI already builds a production linux/amd64 image on every push to main, but build-push-action runs without a registry login and without push, so the image only ever exists inside the runner's buildkit and is discarded when the job ends. Deploys have to reproduce that build by hand -- which on an arm64 workstation means an emulated amd64 build instead of the ~9 minute native one the runner already performs. Add the registry login and metadata steps the existing TODO called for, and publish from the production matrix leg. Publishing is gated on `github.event_name == 'push' && github.ref == 'refs/heads/main'`, so pull request runs remain build-only and never execute with registry access. This repository is public: GitHub does not grant secrets to fork pull requests, and the gate means even a branch PR cannot reach the credentials. The registry host and project are secrets rather than vars because a public repository has public Actions logs, and secrets are masked there. The cost is that image tags render as *** when reading a run. Images are tagged `sha-<short>` so a deploy can pin to an exact commit, plus `latest` on the default branch. Attestations are disabled -- Harbor surfaces buildkit provenance as a separate untagged "unknown/unknown" artifact next to the image. Requires four repository secrets: HARBOR_REGISTRY, HARBOR_PROJECT, HARBOR_USERNAME, HARBOR_PASSWORD. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 tasks
oten91
added a commit
that referenced
this pull request
Jul 26, 2026
…ress (#88) ## Summary Two fixes to the Harbor publish added in #87. The first publish run, [`30209200969`](https://github.com/pokt-network/pocketdex/actions/runs/30209200969), failed at the build step: ``` ERROR: failed to build: invalid tag "***/***/pocketdex-indexer:latest": invalid reference format ``` ### 1. Wrong image name The workflow built `pocketdex-indexer`, but the `pnf` project already contains a **`pnf/pocketdex`** repository — 5 artifacts, 46 pulls. Publishing under a new name would have silently created a second, parallel repository that no deployment pulls from. Now builds `pocketdex`, matching what's already deployed. ### 2. Registry address stored as secrets `HARBOR_REGISTRY` and `HARBOR_PROJECT` were secrets, so the failure rendered as `***/***` with no way to tell which value was malformed. They're addresses, not credentials — masking bought nothing and cost the diagnosis. Moved to vars, where they appear verbatim in the log. `HARBOR_USERNAME` and `HARBOR_PASSWORD` remain secrets. ## Tagging Only `sha-<short>` is published, matching the convention already in the repository (`sha-ce01c85` is commit `ce01c85`). No moving `latest` tag — every existing artifact is explicitly pinned, either `sha-*` or a hand-published release tag like `0.1.34-rc2`. `flavor: latest=false` also disables metadata-action's default `latest=auto`. Release tags remain manual; this only automates the `sha-*` series. ## Required configuration change Add two repository **variables**: | variable | value | |---|---| | `HARBOR_REGISTRY` | `registry.infra.pocket.network` | | `HARBOR_PROJECT` | `pnf` | Host only — no `https://` scheme, no trailing slash. That was most likely the original defect. The `HARBOR_REGISTRY` and `HARBOR_PROJECT` **secrets** are now unused and can be deleted. ## Result after merge Every push to `main` publishes `registry.infra.pocket.network/pnf/pocketdex:sha-<short>`. ## Test plan - [ ] Add the two variables before merging - [ ] Delete the two now-unused secrets - [ ] Confirm the post-merge run pushes and the log shows the real tag rather than `***` - [ ] Confirm the new tag appears under the existing `pnf/pocketdex` repository, not a new one 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Summary
CI already builds a production
linux/amd64image on every push tomain— run30207494667did exactly that in 9m30s. Butbuild-push-actionruns with no registry login and nopush, so the image only exists inside the runner's buildkit and is discarded when the job ends. Nothing to pull, so deploys have to reproduce the build by hand — and on an arm64 workstation that's an emulated amd64 build (~45–90 min) of an image the runner already produced natively.This adds the registry login and metadata steps the
# TODO: add later in another PR the registry login and docker metadata base on commit shacomment called for, and publishes from the production matrix leg.Safety on a public repository
Publishing is gated on
github.event_name == 'push' && github.ref == 'refs/heads/main':pull_request, so fork PRs cannot see the credentials regardlesspull_request_target, no self-hosted runners — on a public repo a self-hosted runner would let any fork PR run arbitrary code on our infrastructureThe registry host and project are stored as secrets rather than vars, because a public repository has public Actions logs and secrets are masked there. Tradeoff: image tags render as
***when reading a run.Tagging
sha-<short>latestprovenance: false/sbom: false— Harbor lists buildkit attestation manifests as a separate untaggedunknown/unknownartifact next to the image.Required repository secrets
HARBOR_REGISTRYharbor.example.comHARBOR_PROJECTpocketdexHARBOR_USERNAMErobot$pocketdex+ciHARBOR_PASSWORDThe robot account should be scoped to that single project with push permission and an expiry set.
Not changed
The
developmentmatrix leg still builds nothing —Build Productionis gated oninputs.env == 'production'and there has never been a development build step, which is why that job finishes in ~29s. Left as-is; happy to add a development image in a follow-up if it's wanted.Test plan
sha-<short>andlatestappear in the Harbor project🤖 Generated with Claude Code