Publish the chart and its images from ACR - #38
Merged
Conversation
Moves the chart itself and every image it references off Amazon ECR, and
removes the CronJob that existed only because ECR credentials expire.
release.yml:
Publishes to oci://openops.azurecr.io/helm using GitHub OIDC rather than a
static ECR key. `az acr login --expose-token` rather than a plain `az acr
login`, because the latter writes Docker's credential store and helm does not
read it - helm needs its own registry login.
chart/values.yaml:
image.repository public.ecr.aws/openops -> openops.azurecr.io
tables.repository/tag -> openops.azurecr.io, 0.2.22
analytics.repository -> openops.azurecr.io, 0.14.8
OPS_SUBAGENT_RUNNER_IMAGE -> ""
The tables and analytics versions move because 0.2.21 and 0.14.7 do not exist
in the ACR public registry - 0.2.22 and 0.14.8 are what those repositories
published when they migrated.
OPS_SUBAGENT_RUNNER_IMAGE is emptied rather than repointed. Subagents are an
enterprise feature configured on internal deployments, so the public chart
had no business carrying a hardcoded reference to a private registry that no
one installing this chart can pull from - and every other value for that
feature, OPS_SUBAGENT_S3_* included, is already empty by default. It also
took an AWS account ID out of a public repository.
cronjob-ecr-credential-refresh.yaml is deleted:
It minted a 12-hour ECR token into an imagePullSecret every six hours, and
its own comment gave the reason - "Required when AKS or non-AWS clusters need
to pull from private ECR". That is precisely the problem this migration
solves. It could not have been ported either: it runs `aws ecr
get-login-password` and cannot mint an ACR token, so it was AWS-specific
machinery for a registry the images have left. What remains general is
global.imagePullSecrets, which eight templates already consume, so anyone
mirroring images elsewhere still has the hook.
The README section it served is replaced rather than dropped, because the
capability is not lost - release images need no credentials at all now, and
on AKS the kubelet's own identity replaces the secret.
Verified by rendering both paths:
chart defaults openops.azurecr.io/openops-{app,worker}:0.6.26
deploy-helm --set openopsprivate.azurecr.io/openops-{app,worker}:<sha>
with tables and analytics on the public registry by version in both.
Part of OPS-4817
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The section is documentation for people installing the chart, and what the chart used to do two versions ago is not something they need to carry. The reasoning belongs in the commit that removed it, which is where it is. Part of OPS-4817 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
values.ci.yaml explained the CI version override by saying the repo default does not exist in ECR. The registry is beside the point - 0.0.1-dev is a placeholder release.yml rewrites, so it is never published anywhere. AGENTS.md claimed draft chart versions are overwritable while final versions are immutable. That was a property of ECR Public, not of the release process: ACR does not enforce tag immutability unless it is configured on the registry, so a released chart version can now be overwritten by a later push of the same version. Worth deciding whether to configure immutability there; the -draft suffix is a naming convention either way. The two remaining ECR mentions are in docs/DEPLOY_TO_AWS_EKS.md, about ECR permissions and ECR image scanning. Both are advice for someone running on EKS with their own registry, so they stay. Part of OPS-4817 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The images dropped their path segment when they moved: openops/ was ECR's registry namespace, and ACR puts the organisation in the hostname, so openops-tables and the rest sit at the root. The chart kept a helm/ segment and was the only thing left nested. oci://openops.azurecr.io/helm/openops -> oci://openops.azurecr.io/openops No collision with the image repositories: they are openops-app, openops-worker, openops-tables, openops-analytics, openops-mcp and subagent-runner, and the chart is named openops. Anything already installed from the ECR path keeps working - that registry still holds the old chart versions - but an upgrade has to use the new reference, which is why NOTES.txt prints it after every install. Part of OPS-4817 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This reverts commit 9db57e8. The chart stays at oci://openops.azurecr.io/helm, so it keeps a path of its own rather than sitting alongside the image repositories at the root. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The chart push moves off github-actions-acr-push, which CI shares and which any pull request in six repositories can assume, onto github-actions-acr-release - whose credentials are scoped to the release environment and which holds nothing CI can reach. environment: release is not optional. The credential's subject is repo:openops-cloud/helm-chart:environment:release, so without the environment the subject does not match and azure/login fails. It is also branch-agnostic, which is what lets this release run from mg/OPS-4456 rather than only from main. Requires openops-cloud/devops#287 applied, the organisation secret AZURE_ACR_RELEASE_CLIENT_ID set, and a release environment on this repository. Part of OPS-4817 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every run currently warns that actions/checkout@v4, actions/cache@v4, azure/setup-helm@v4 and helm/kind-action@v1.9.0 target a runtime the runners are dropping, and are being forced onto Node 24 anyway. Same bump the other repositories got. Inputs are unchanged across all five: kind-action still takes cluster_name and wait, setup-helm still takes version, cache still takes path/key/restore-keys, and action-gh-release still takes files/tag_name/name/body/draft. Part of OPS-4817 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.
Part of OPS-4817
Moves the chart itself and every image it references off Amazon ECR, and removes the CronJob that existed only because ECR credentials expire. Based on
mg/OPS-4456, for the0.6.26-draftrelease.Completes the chart side of the migration. Follows openops-cloud/openops#2489, openops-cloud/devops#281 / #282 / #283 / #284.
0.
helm-e2ewill fail on this PR untilopenopsreleases. That workflow builds a kind cluster and runshelm upgrade --install -f chart/values.ci.yaml --wait, andvalues.ci.yamlpinsglobal.version: "latest"— so it pullsopenops.azurecr.io/openops-app:latest, which does not exist.latestis written byopenops' release whengithub_releaseis true, so e2e can only go green after that release.tablesandanalyticswill pull fine; app and worker are what fail.Two prerequisites before releasing
1.
openopsmust release0.6.26first.release.ymlrewritesglobal.version, which is the app and worker image tag — so a0.6.26-draftchart pullsopenops.azurecr.io/openops-app:0.6.26. There is no0.6.26tag inopenopsand noopenops-appin the public ACR at all today:So: run
openops' release for0.6.26, then release this chart. Note thatopenops'trigger-helm-chart-releasepasses-f draft=false, so a draft has to be dispatched by hand.2. openops-cloud/devops#285 must be merged and applied — this repository has no federated credential yet, so
azure/loginfails without it. That credential's subject isrefs/heads/main, so a release dispatched frommg/OPS-4456will fail; release frommainafter merging, or say so and I'll add the branch as a second subject.release.ymlPublishes to
oci://openops.azurecr.io/helmwith OIDC instead of a static ECR key.az acr login --expose-tokenrather than a plainaz acr login— the latter writes Docker's credential store, whichhelmdoes not read. Helm needs its ownhelm registry login.Image references
image.repositorypublic.ecr.aws/openopsopenops.azurecr.iotables…/openops-tables:0.2.21openops.azurecr.io/openops-tables:0.2.22analytics…/openops-analytics:0.14.7openops.azurecr.io/openops-analytics:0.14.8OPS_SUBAGENT_RUNNER_IMAGE""The tables and analytics versions move because
0.2.21and0.14.7don't exist in the ACR public registry —0.2.22and0.14.8are what those repositories published when they migrated. So the shipped stack picks up newer Baserow and Superset builds; worth a smoke test of a full install.OPS_SUBAGENT_RUNNER_IMAGEis emptied, not repointed. Subagents are an enterprise feature configured on internal deployments, so the public chart had no business carrying a hardcoded reference to a private registry nobody installing this chart can pull from. Every other value for that feature —OPS_SUBAGENT_S3_*— is already empty by default, so this makes it consistent. It also removes an AWS account ID from a public repository. The real reference now lives only indevops' values files (openops-cloud/devops#284).The CronJob is deleted
cronjob-ecr-credential-refresh.yaml— 184 lines of ServiceAccount, Role, RoleBinding, CronJob and one-shot Job — plus its values block and README section.Its own comment gave the reason to remove it: "Required when AKS or non-AWS clusters need to pull from private ECR". That is precisely the problem this migration solves. It also could not have been ported: it runs
aws ecr get-login-passwordand cannot mint an ACR token, so it was AWS-specific machinery for a registry the images have left.What remains general is
global.imagePullSecrets, which eight templates already consume, so anyone mirroring images elsewhere still has the hook.The README section is replaced, not dropped — the capability isn't lost, so "Private ECR access from non-AWS clusters" becomes "Pulling from a private registry", explaining that release images need no credentials and that on AKS the kubelet identity replaces the secret. The EKS guides keep working: public images need no pull secret.
Verified by rendering, not by reading values
Both paths correct: our own deployments take app and worker from the private registry by SHA via
deploy-helm's--set, while tables and analytics come from the public one by version in both cases.helm lintpasses and noecr-credential-refreshobjects render.Also in here
values.ci.yaml's comment explained the version override by saying the default "does not exist in ECR" — the registry was beside the point,0.0.1-devis a placeholderrelease.ymlrewrites and is never published anywhere.AGENTS.mdclaimed draft versions are overwritable while final versions are immutable. That was a property of ECR Public, not of this release process. ACR does not enforce tag immutability unless configured, so a released chart version can now be overwritten by a later push of the same version. Worth deciding whether to turn that on; the-draftsuffix is a naming convention either way.docs/DEPLOY_TO_AWS_EKS.md, are advice about ECR permissions and ECR image scanning for someone running on EKS with their own registry. They stay.Test plan
azure/loginworks hereopenopsreleased at0.6.26, so its images exist in the public ACR0.6.26-draftfrommainpushes tooci://openops.azurecr.io/helmhelm installfrom that chart on a clean cluster with noimagePullSecretsstaging) still resolves its runner image fromdevopsvalues🤖 Generated with Claude Code