Skip to content

Commit 33b1b76

Browse files
committed
chore: update readme
1 parent 2907a62 commit 33b1b76

1 file changed

Lines changed: 74 additions & 13 deletions

File tree

README.md

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -358,24 +358,85 @@ model:
358358
- **Per-chain config** — separate RPC endpoints, rate-limit tiers, resource
359359
requests, Prometheus pod labels.
360360

361-
### Kubernetes (production)
361+
### Kubernetes
362362

363363
Deployed via [cowprotocol/infrastructure](https://github.com/cowprotocol/infrastructure)
364-
using Pulumi (DNS, secrets) + Flux (k8s manifests). One `Deployment` + `Service`
365-
per chain in the `balances-watcher` namespace, with a shared `Ingress` routing
366-
`/<chain_id>/...` and `/sse/<chain_id>/...` to the matching service.
364+
using Pulumi (DNS) + Flux (k8s manifests):
367365

368-
Docker images are built and pushed to GHCR by `.github/workflows/build-image.yml`
369-
on push to `main` or on semver tags (`vX.Y.Z`). Flux picks up new image tags
370-
from `ghcr.io/cowprotocol/balances-watcher`.
366+
- **Staging**: `balances-watcher.barn.cow.fi`. Flux `ImagePolicy` watches GHCR
367+
and auto-opens a bump PR when a new semver tag lands (see the
368+
`staging-auto-pr` workflow in the infra repo).
369+
- **Prod**: `balances-watcher.cow.fi`. **No Flux image automation** on the prod
370+
cluster — the tag is pinned manually in `cluster/prod/balances-watcher/…/kustomization.yaml`,
371+
bumped via an infra PR when someone decides to promote a version from staging.
372+
This is the deliberate promotion gate between the two environments.
371373

372-
### Releases
374+
One `Deployment` + `Service` per chain in the `balances-watcher` namespace,
375+
with a shared `Ingress` routing `/<chain_id>/...` and `/sse/<chain_id>/...` to
376+
the matching service. Each chain is a kustomize overlay (`nameSuffix: -mainnet`
377+
etc.) over one shared `flux-apps/balances-watcher/` template.
373378

374-
Versioning is fully automatic. Every merge to `main` triggers the `release` job
375-
which bumps the minor version from the latest git tag (`v0.1.0``v0.2.0` → …)
376-
and pushes the new tag. The tag push re-triggers the build pipeline, producing
377-
a GHCR image tagged with the semver version (`v0.2.0`, `0.2`) alongside `sha-xxx`
378-
and `latest`.
379+
### Release flow
380+
381+
Versioning is semantic and label-driven. Two workflows split the work:
382+
383+
- **`release.yml`** — fires on `pull_request_target: closed` when a PR is merged
384+
into `main`. Reads the merged PR's labels and picks the bump:
385+
386+
| PR label | Bump | Example |
387+
|---|---|---|
388+
| `breaking` | MAJOR + 1 | `v1.4.7 → v2.0.0` |
389+
| `hotfix` | PATCH + 1 | `v1.4.7 → v1.4.8` |
390+
| (none) | MINOR + 1 (default) | `v1.4.7 → v1.5.0` |
391+
392+
Then it creates the git tag, pushes it, and creates a GitHub Release with
393+
auto-generated notes (PR titles + authors between the previous Release and
394+
the new one).
395+
396+
- **`build-image.yml`** — fires on push to `main` (produces `:sha-<7>` +
397+
`:latest`) and on push of a `v*` git tag (produces the semver tags
398+
`:vX.Y.Z` and `:vX.Y`). Buildx multi-stage build → GHCR.
399+
400+
The two are decoupled: `release.yml` tags, tag push triggers `build-image.yml`.
401+
402+
#### Two gotchas worth knowing
403+
404+
1. **Tag push must use a PAT, not `GITHUB_TOKEN`.** GitHub silently exempts
405+
`GITHUB_TOKEN`-driven pushes from triggering downstream workflows (loop
406+
protection). To make the tag push fire `build-image.yml`, `release.yml`
407+
uses the `RELEASE_TOKEN` repo secret (fine-grained PAT with
408+
`Contents: read/write` on this repo). Rotate the PAT before its expiration
409+
or CI will silently stop bumping images.
410+
411+
2. **Docker tag `v`-prefix is preserved intentionally.** `docker/metadata-action`
412+
by default strips the `v` from semver docker tags (so `v1.6.0` becomes
413+
`:1.6.0`), but our overlays and history use `v1.5.0`, `v1.4.0` etc. with
414+
the prefix. We keep the prefix via `pattern=v{{version}}` in the
415+
metadata-action config — if you touch that step, keep the `v`.
416+
417+
#### Skip-empty guard
418+
419+
`release.yml` short-circuits if `HEAD` already sits on the latest tag (`git
420+
diff --quiet $LATEST..HEAD`). This handles two cases: re-runs after a
421+
transient failure, and no-op merges (revert-then-reapply). Without it we'd
422+
tag the same commit under two versions.
423+
424+
#### Promoting staging → prod
425+
426+
Manual and intentional:
427+
428+
```bash
429+
# In cowprotocol/infrastructure
430+
git checkout -b promote/balances-watcher-v1.7.0
431+
# Bump: cluster/prod/balances-watcher/balances-watcher/kustomization.yaml
432+
# newTag: v1.6.1 → newTag: v1.7.0
433+
git commit -am "promote balances-watcher to v1.7.0 in prod"
434+
git push -u origin promote/balances-watcher-v1.7.0
435+
gh pr create --title "promote balances-watcher v1.7.0 → prod"
436+
```
437+
438+
Reviewer approves, merges, Flux applies. No automation between the version
439+
existing on staging and it landing in prod — that's the gate.
379440

380441
### docker-compose (local dev)
381442

0 commit comments

Comments
 (0)