fix: derive Azure kube-recipe pins from the recipe pack (#12688) - #12690
fix: derive Azure kube-recipe pins from the recipe pack (#12688)#12690sk593 wants to merge 4 commits into
Conversation
The generated run-rad-commands-azure.yml rewrites each mutable kube-recipes/*:latest source in the Azure recipe pack to a commit-pinned source, then asserts none remain. The pin list was hardcoded to five recipes, but the pack now ships a sixth (kube-recipes/rabbitmq:latest, pulled in when the pack ref was bumped). The unpinned :latest survived the rewrite and tripped the mutable-tag guard, failing every Azure deploy before the app model was ever read. Add a pin_kube_recipe line for Radius.Messaging/rabbitMQ, handling it the same way as the other Kubernetes recipes (e.g. containerImages). It resolves to the Radius.Messaging namespace ref already validated in defaults.yaml. Also make the guard name the offending kube-recipes/*:latest sources and tell the maintainer to add a matching pin_kube_recipe line, instead of emitting a single generic error, so this class of drift is diagnosable. Fixes #12688 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: sk593 <shruthikumar@microsoft.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this comment.
Pull request overview
This PR updates the generated Azure deploy workflow used by the Radius extension to prevent Azure deploys from failing during the “Create Radius environment and recipe pack” step due to an unpinned kube-recipes/*:latest reference in the upstream recipe pack.
Changes:
- Adds
pin_kube_recipe Radius.Messaging/rabbitMQ rabbitmqso the Azure recipe pack rewrite covers the newly introduced RabbitMQ kube recipe. - Improves the mutable-tag guard to list the exact remaining
kube-recipes/*:latestoffenders and provide actionable remediation text.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The offenders scan ran as `grep ... | sort -u` inside a command substitution. Under the workflow's default `set -eo pipefail`, grep exits 1 when there are no matches (the success case), which propagated through the pipeline and failed the step. Capture grep's status directly, treat exit 1 (no matches) as success, and still fail on a real grep error (status > 1). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: sk593 <shruthikumar@microsoft.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #12690 +/- ##
==========================================
- Coverage 54.20% 54.18% -0.02%
==========================================
Files 770 770
Lines 51085 51085
==========================================
- Hits 27690 27682 -8
- Misses 20789 20793 +4
- Partials 2606 2610 +4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The Azure deploy workflow rewrote a fixed list of kube-recipe sources to commit-pinned refs, then failed if any 'kube-recipes/*:latest' survived. When the upstream pack gained a sixth recipe (rabbitMQ) the hardcoded list did not follow, so the mutable tag survived and blocked every Azure deploy (#12688). Derive the pin set directly from the downloaded pack instead. Each recipe entry is keyed by its Radius resource type, so both the type (which selects the namespace commit in defaults.yaml) and the kube-recipe artifact come from the pack itself; whatever Kubernetes recipes the pack ships, present or future, are pinned automatically. The mutable-tag guard remains as a safety net and now explains what an operator must fix. verify-contrib-consumers.sh downloads each consumed recipe pack, derives the same pairs, and docker-manifest-inspects every pinned source, so CI still proves each ref exists upstream without a parallel hardcoded list. A new test, test_azure_recipe_pack_pin_coverage, runs the workflow's own derivation against a fixture pack (including rabbitMQ, the recipe the old list omitted) and asserts every kube recipe is pinned with none left for the guard, plus that the guard still fires for an unmappable recipe. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: sk593 <shruthikumar@microsoft.com>
The derive-from-pack comment in run-rad-commands-azure.yml references the awk built-in match variables RSTART/RLENGTH and the mawk implementation used on the Ubuntu runner. Add them to the repo cspell word list so the Spellcheck check passes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: sk593 <shruthikumar@microsoft.com>
Radius functional test overviewClick here to see the test run details
Test Status⌛ Building Radius and pushing container images for functional tests... |
What
Fixes #12688.
Every Azure deploy driven by the generated
run-rad-commands-azure.ymlwas failing in the Create Radius environment and recipe pack step, beforerad deployever read the application model:Why
The step downloads the upstream Azure recipe pack and rewrites each mutable
ghcr.io/radius-project/kube-recipes/*:latestsource to a commit-pinned source, then asserts none remain. The pin list was hardcoded to five recipes, but the pack now ships a sixth —kube-recipes/rabbitmq:latest— pulled in when the pack ref was bumped. Nothing pinned it, so the mutable:latestsurvived the rewrite, the guard'sgrepmatched it, and the job exited 1 for every repo, independent of app content.This is drift between two independently versioned things. Rather than re-sync the hardcoded list, this takes the issue's recommended durable fix: stop hardcoding and derive the pin set from the pack.
Change
.github/extension/run-rad-commands-azure.yml— derive the pins from the downloaded pack instead of a fixed list. Each recipe entry is keyed by its Radius resource type, e.g.so both the resource type (which selects the namespace commit in
deploy/manifest/defaults.yaml) and the kube-recipe artifact come from the pack itself.awkwalks the pack, pairs eachkube-recipes/*:latestsource with its owning resource type, and each pair is pinned via the existingpin_kube_recipe/radius_contrib_kube_recipe_sourcepath. Whatever Kubernetes recipes the pack ships —rabbitmqtoday, anything new tomorrow — are pinned automatically, so this class of drift can't reblock deploys.The mutable-tag guard stays as a safety net. It now names the offending sources (fixing the "deploy failed with no error text" symptom), tolerates
grep's no-match exit underset -eo pipefailinstead of failing the success path, and explains what an operator must fix.build/scripts/verify-contrib-consumers.sh— CI'sverify-contrib-consumersused to enumerate recipes by scraping the (now-removed) staticpin_kube_recipelines. It now downloads each consumed recipe pack, derives the same<resourceType, artifact>pairs, anddocker manifest inspects every pinned source — so CI still proves each ref exists upstream at build time, without a parallel hardcoded list.build/scripts/test-sync-resource-types.sh— newtest_azure_recipe_pack_pin_coverageruns the workflow's own derivation against a fixture pack (includingrabbitMQ, the recipe the old list omitted, plus a managed AVM recipe that must be left untouched) and asserts every kube recipe is pinned with nothing left for the guard, and that the guard still fires for a recipe that can't be mapped.Mapping to the issue's criteria
$ENV_BICEP; anykube-recipes/<artifact>:latestis pinned automatically via its owning resource type's namespace ref. ✅pipefailcorrectness fix)Validation
test_azure_recipe_pack_pin_coveragepasses:containers+rabbitmqderived and pinned, AVM source untouched, zero offenders; unmappable recipe trips the guard.verify-contrib-consumers.shpasses, verifying all six Azure-pack kube recipes (includingrabbitmqat theRadius.Messagingref) plus AWS's direct recipe and the git recipes;--source-of-truth-onlypasses.test_azure_recipe_pack_pinning(thepin_kube_recipeunit test) and the rest of the sync test suite still pass.Note: no
resource-types-contribchange is needed — the read-onlysecretsschema block onRadius.Messaging/rabbitMQfollows the existing repo convention and is kept.