Skip to content

ci: publish the production image to Harbor on merges to main - #87

Merged
oten91 merged 1 commit into
mainfrom
ci/publish-image-to-harbor
Jul 26, 2026
Merged

ci: publish the production image to Harbor on merges to main#87
oten91 merged 1 commit into
mainfrom
ci/publish-image-to-harbor

Conversation

@oten91

@oten91 oten91 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

CI already builds a production linux/amd64 image on every push to main — run 30207494667 did exactly that in 9m30s. But build-push-action runs with no registry login and no push, 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 sha comment 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 runs stay build-only and never execute with registry access
  • GitHub does not grant secrets to fork pull requests on pull_request, so fork PRs cannot see the credentials regardless
  • No pull_request_target, no self-hosted runners — on a public repo a self-hosted runner would let any fork PR run arbitrary code on our infrastructure

The 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

tag when
sha-<short> every publish — lets a deploy pin to an exact commit
latest default branch only

provenance: false / sbom: false — Harbor lists buildkit attestation manifests as a separate untagged unknown/unknown artifact next to the image.

Required repository secrets

secret example
HARBOR_REGISTRY harbor.example.com
HARBOR_PROJECT pocketdex
HARBOR_USERNAME robot$pocketdex+ci
HARBOR_PASSWORD robot account token

The robot account should be scoped to that single project with push permission and an expiry set.

Not changed

The development matrix leg still builds nothing — Build Production is gated on inputs.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

  • Add the four secrets before merging — without them the login step fails and the merge build goes red
  • Confirm this PR's own CI run builds without attempting a push
  • After merge, confirm sha-<short> and latest appear in the Harbor project
  • Pull the published image on an amd64 host and confirm the indexer starts

🤖 Generated with Claude Code

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>
@oten91
oten91 merged commit 4d926ee into main Jul 26, 2026
3 checks passed
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>
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.

1 participant