Skip to content

Inject registry creds into app rad deploy instead of provisioning a control-plane Secret - #12510

Merged
sk593 merged 16 commits into
mainfrom
sk593-inject-registry-creds-on-deploy
Jul 24, 2026
Merged

sk593 merged 16 commits into
mainfrom
sk593-inject-registry-creds-on-deploy

Conversation

@sk593

@sk593 sk593 commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The Radius.Compute/containerImages recipe moved from a Terraform recipe to a Bicep recipe. Under the new model, the app's .radius/app.bicep declares a Radius.Security/secrets resource named radius-ghcr-registry-creds (keys username/password) fed by two params: registryUsername (plain) and registryPassword (@secure()). That resource materializes the registry push/pull Secret on the target cluster, and the recipe reads it by the name the recipe pack registers.

So the credentials must now reach the app deploy as rad deploy parameters, valued from the runner identity — registryUsername = ${{ github.actor }} and registryPassword = ${{ secrets.GITHUB_TOKEN }} — instead of being provisioned as a Kubernetes Secret on the control-plane cluster.

Changes

.github/extension/actions/run-rad-commands/action.yml

  • Append --parameters registryUsername=… and --parameters registryPassword=… to the app-file rad deploy invocations (the default deploy branch, and the custom-commands deploy branch only when the deploy target is APP_FILE). Built into the existing argv array so special characters aren't word-split, added only when non-empty and not already supplied via RADIUS_DEPLOY_PARAMS, and kept out of the recorded command string.
  • Remove the Provision registry credentials on control plane step (kubectl create secret generic radius-ghcr-registry-creds …). The Secret is now created on the target cluster by the app's Radius.Security/secrets resource during rad deploy.
  • Mask and scrub secret values so they never reach the logs or the uploaded rad-commands-result artifact.
  • Refresh the action description, header comment, and input descriptions.

run-rad-commands-azure.yml / run-rad-commands-aws.yml

  • Recipe-pack registration is functionally unchanged: Azure passes containerImagesRegistry / containerImagesRegistrySecretName=radius-ghcr-registry-creds; the AWS inline pack passes registry / registrySecretName=radius-ghcr-registry-creds. Only the now-stale comments that described control-plane provisioning were updated for accuracy.

.github/extension/README.md

  • Updated the numbered flow: dropped the control-plane provisioning step and described the injected registryUsername/registryPassword runner credentials in the run step.

Notes

  • These credentials belong only to the app deploy. They are not added to the recipe-pack rad deploy (radius-env.bicep), which does not declare them — doing so would make rad reject unknown parameters.
  • registryPassword is secret: passed via an argv array, never echoed or written into the recorded/logged command string.
  • Consistent across both the Azure and AWS provider workflows.

This is the upstream half of a change coordinated with radius-project/ai-extensions, which stops auto-generating registryUsername/registryPassword in the app bicep so the workflow can inject the runner values instead.

  • The registry-push Secret is named radius-ghcr-registry-creds (the radius- prefix was added in a follow-up to this branch for parity with the ai-extensions radius-app-bicep skill). The name stays consistent across all three points: the workflow value → the recipe-pack parameter (containerImagesRegistrySecretName / registrySecretName) → the app's Radius.Security/secrets resource. No recipe-pack change in resource-types-contrib is needed since it takes the name as a parameter.

Copilot AI review requested due to automatic review settings July 22, 2026 20:24
@sk593
sk593 requested review from a team as code owners July 22, 2026 20:24
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the GitHub Actions Radius extension workflows/composite action to stop provisioning registry credentials on the control-plane cluster and instead pass registry credentials into the app rad deploy as parameters, enabling the app’s Radius.Security/secrets resource to materialize the registry Secret on the target cluster.

Changes:

  • Removes the control-plane kubectl create secret generic ghcr-registry-creds ... step from the shared run-rad-commands composite action.
  • Injects registryUsername / registryPassword via --parameters on app deploy(s), while keeping secrets out of the recorded command string.
  • Updates Azure/AWS provider workflow comments and the extension README to reflect the new model.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
.github/extension/actions/run-rad-commands/action.yml Removes control-plane Secret provisioning and injects registry credentials into rad deploy argv.
.github/extension/run-rad-commands-azure.yml Updates comments and passes registry creds inputs to the shared action.
.github/extension/run-rad-commands-aws.yml Updates comments and passes registry creds inputs to the shared action.
.github/extension/README.md Updates documented workflow steps to match the new credential flow.
Comments suppressed due to low confidence (1)

.github/extension/actions/run-rad-commands/action.yml:201

  • In the custom rad_commands path, registryUsername/registryPassword get appended to any deploy command, not just the app deploy. This can break supported custom command scenarios like deploying radius-env.bicep (unknown parameters) and it also silently skips injection when the required inputs are empty. Only inject these parameters when the deploy target is the app file (and fail fast if creds are missing for that case).
              fi
              if [ -n "${RADIUS_DEPLOY_PARAMS//[[:space:]]/}" ]; then
                while IFS= read -r _pname; do
                  [ -z "$_pname" ] && continue
                  _pval=$(printf '%s' "$RADIUS_DEPLOY_PARAMS" | jq -r --arg k "$_pname" '.[$k]')

Copilot AI review requested due to automatic review settings July 22, 2026 20:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread .github/extension/actions/run-rad-commands/action.yml Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 20:41
@sk593 sk593 added the pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work label Jul 22, 2026
sk593 and others added 4 commits July 22, 2026 13:44
…cret

The Radius.Compute/containerImages recipe moved from Terraform to Bicep. The
registry push/pull credentials must now reach the app deploy as rad deploy
parameters so the app's Radius.Security/secrets resource (ghcr-registry-creds)
materializes the registry Secret on the target cluster.

- Pass registryUsername (github.actor) and registryPassword (GITHUB_TOKEN) as
  --parameters to both app-file rad deploy sites (custom-commands deploy branch
  and default deploy), via the existing argv array so secret values are not
  word-split and stay out of the recorded command string. Only when non-empty.
- Remove the 'Provision registry credentials on control plane' step that ran
  kubectl create secret generic ghcr-registry-creds on the control-plane cluster.
- Refresh action metadata, workflow comments, and README to match. Recipe-pack
  registration is unchanged (secret name stays ghcr-registry-creds).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
Guard against passing the same --parameters twice: only append the
runner-injected registryUsername/registryPassword when RADIUS_DEPLOY_PARAMS
does not already carry that key (older environments may still supply them).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
The rad-commands-result artifact captures rad stdout/stderr, but GitHub's log
masking does not apply to artifact file contents. Collect the secret values
(registry password / GITHUB_TOKEN and every RADIUS_DEPLOY_PARAMS value),
register each with ::add-mask:: for defense-in-depth log redaction, and scrub
them from each command's captured output before it is written into the
artifact JSON.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
In the custom rad_commands path, image/application/registry parameters were
appended to every deploy command. rad deploy rejects unknown parameters, so a
custom command deploying a non-app template (e.g. radius-env.bicep) would fail.
Gate the app-only parameters on the deploy target matching APP_FILE.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread .github/extension/actions/run-rad-commands/action.yml
Comment thread .github/extension/actions/run-rad-commands/action.yml Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 20:44
@sk593
sk593 force-pushed the sk593-inject-registry-creds-on-deploy branch from 671af20 to 17e4ebe Compare July 22, 2026 20:44
Address review feedback on the secret-redaction helpers:
- add_secret now emits ::add-mask:: one line at a time, strips CR, and escapes
  '%' (the workflow-command escape char). A multiline secret previously left its
  second and later lines unmasked and printed verbatim, and an unescaped '%'
  could break or inject the workflow command.
- Clarify that scrub_secrets double-quotes the search value inside the
  substitution, which disables pattern matching so glob metacharacters
  (* ? [ ] \) in a secret are matched literally rather than as a glob.

Signed-off-by: sk593 <shruthikumar@microsoft.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

.github/extension/actions/run-rad-commands/action.yml:170

  • add_secret echoes the secret value directly into the ::add-mask:: workflow command. If a secret contains %, \n, or \r, GitHub Actions requires escaping (otherwise masking can fail and multiline values can inject extra log lines/commands). Escape the value for the workflow command while still storing the raw value for artifact scrubbing.
        add_secret() {
          [ -n "$1" ] || return 0
          SECRET_VALUES+=("$1")
          # Mask one line at a time. GitHub reliably masks a single-line value, but
          # a multiline ::add-mask:: leaves the second and later lines unmasked (and

Copilot AI review requested due to automatic review settings July 22, 2026 20:48
sk593 added a commit to radius-project/ai-extensions that referenced this pull request Jul 22, 2026
Temporarily set RADIUS_REF to the sk593-inject-registry-creds-on-deploy
branch (radius-project/radius#12510) so end-to-end deploys use the updated
run-rad-commands action that injects registryUsername/registryPassword as
app-deploy parameters, materializing the ghcr-registry-creds Secret on the
target cluster.

RADIUS_REF drives both the fetched deploy/verify workflow templates and the
{{RADIUS_REF}} the committed workflows pin their composite `uses:` actions to,
so the PR-branch action is what actually runs. Made it overridable via
RADIUS_DEPLOY_REF (mirroring DELETE_RADIUS_REF) so the branch can be repointed
without a new core release. Revert to "main" once #12510 merges.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

.github/extension/actions/run-rad-commands/action.yml:195

  • scrub_secrets is not literal-safe: in Bash ${var//pattern/repl} the pattern is always treated as a glob pattern, even when it comes from a quoted variable. Secrets containing glob metacharacters (notably [/], but also */?) may fail to match (or overmatch) and leak into the uploaded artifact. Update the comment (it currently claims quoting disables pattern matching) and escape glob metacharacters before doing the substitution (or switch to a literal-safe replacer).
        # the artifact never carries a credential that `rad` happened to echo. The
        # search value is double-quoted inside the substitution, which disables
        # pattern matching so it is compared as a literal string -- glob
        # metacharacters (* ? [ ] \) in a secret are matched verbatim, not as
        # patterns.

@github-actions

github-actions Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Unit Tests

    2 files  ±0    457 suites  ±0   6m 26s ⏱️ - 1m 14s
6 075 tests ±0  6 073 ✅ ±0  2 💤 ±0  0 ❌ ±0 
7 294 runs  ±0  7 292 ✅ ±0  2 💤 ±0  0 ❌ ±0 

Results for commit d29c180. ± Comparison against base commit d86285e.

♻️ This comment has been updated with latest results.

@codecov

codecov Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 53.90%. Comparing base (d86285e) to head (d29c180).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12510      +/-   ##
==========================================
- Coverage   53.91%   53.90%   -0.02%     
==========================================
  Files         765      765              
  Lines       50689    50689              
==========================================
- Hits        27328    27322       -6     
- Misses      20793    20796       +3     
- Partials     2568     2571       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread .github/extension/actions/run-rad-commands/action.yml Outdated
@github-actions

github-actions Bot commented Jul 23, 2026 •

Copy link
Copy Markdown

Functional Tests - corerp-noncloud

180 tests  ±0   178 ✅ ±0   1h 23m 26s ⏱️ - 7m 24s
  3 suites ±0     2 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 9d8ece7. ± Comparison against base commit ca1568e.

♻️ This comment has been updated with latest results.

Copilot AI review requested due to automatic review settings July 24, 2026 00:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

.github/extension/actions/run-rad-commands/action.yml:280

  • The disallowed-command path (above this loop) records/logs the raw caller command string without passing it through scrub_string. If a disallowed command includes any value from REGISTRY_PASSWORD or RADIUS_DEPLOY_PARAMS inline, it can bypass redaction and end up in both logs and rad-commands-result.json. Scrub the command string before writing it to COMMANDS_JSON and stderr in that disallowed branch.
          for cmd in "${CLEAN[@]}"; do
            verb="${cmd%% *}"
            if [ "$verb" = "deploy" ]; then

Copilot AI review requested due to automatic review settings July 24, 2026 18:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@github-actions

github-actions Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Functional Tests - ucp-cloud

4 tests  ±0   4 ✅ ±0   35s ⏱️ ±0s
1 suites ±0   0 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit 56d695a. ± Comparison against base commit d86285e.

♻️ This comment has been updated with latest results.

sk593 and others added 6 commits July 24, 2026 13:52
…WS containerImages Bicep

- run-rad-commands action: determine the deploy target as the first non-flag
  argument after `deploy`, skipping flags and value-taking flag values, so
  `deploy -e dev app.bicep` still injects app-only parameters.
- record(): escape workflow-command metacharacters (CR, newline, %) in the
  ::group:: title to prevent breakage/injection from caller command strings.
- AWS workflow: switch Radius.Compute/containerImages to the Bicep recipe to
  match the Azure hosted recipe pack.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
…oducibility

Introduce RADIUS_KUBE_RECIPES_REF (default 'latest') so the AWS inline recipe
pack's Bicep containerImages source can be pinned to an immutable digest or a
specific tag, instead of hard-coding the mutable ':latest' tag. A digest ref is
joined with '@', a tag with ':'.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
…ams JSON

- Scrub the recorded command `display` with the known SECRET_VALUES before it
  reaches the ::group:: title or the JSON `command` field, so a secret passed
  inline via --parameters can't be uploaded in the result artifact.
- Validate RADIUS_DEPLOY_PARAMS is a JSON object once, up front, and reference
  the validated copy everywhere; suppress jq stderr so a malformed value can't
  spill raw secret content into the logs. Malformed input is rejected with a
  generic message and treated as empty.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
- deploy_params_has_key() now returns false when the key's value is JSON null
  or an empty string, so runner-provided registry credentials are still injected
  when an older params secret carries the key with no usable value.
- When building the mask list, emit nothing for a JSON null instead of the
  literal string "null", so masking/scrubbing can't redact unrelated "null"
  output. A genuine string value is still masked.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
add_secret now records each stripped, non-empty line of a secret in
SECRET_VALUES in addition to the full value. Masking is emitted per line, so
without this the artifact scrubber only matched the exact multi-line string and
a value echoed line-by-line by rad could leak into the uploaded artifact. Lines
are added before % escaping so they match the real output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
The custom rad_commands deploy path gated app-only parameter injection on a raw
string compare, which missed equivalent spellings of the app file. Normalize
both sides -- strip a matched pair of surrounding quotes (read -ra preserves
them) and a single leading './' -- so `deploy ./.radius/app.bicep` and
`deploy ".radius/app.bicep"` still inject image/deploy params/registry creds.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
Copilot AI review requested due to automatic review settings July 24, 2026 20:52
@sk593
sk593 force-pushed the sk593-inject-registry-creds-on-deploy branch from 56d695a to 8a215a1 Compare July 24, 2026 20:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@github-actions

github-actions Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Functional Tests - statestore-noncloud

2 tests  ±0   2 ✅ ±0   3m 10s ⏱️ +5s
1 suites ±0   0 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit d29c180. ± Comparison against base commit d86285e.

♻️ This comment has been updated with latest results.

@sylvainsf sylvainsf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, very well thought out.

@radius-functional-tests

radius-functional-tests Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Radius functional test overview

🔍 Go to test action run

Click here to see the test run details
Name Value
Repository radius-project/radius
Commit ref d29c180
Unique ID funcdffe6b75a7
Image tag pr-funcdffe6b75a7
  • Dapr: 1.14.4
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-funcdffe6b75a7
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-funcdffe6b75a7
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-funcdffe6b75a7
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-funcdffe6b75a7
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-funcdffe6b75a7
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting ucp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

@sk593
sk593 enabled auto-merge July 24, 2026 21:28
@sk593
sk593 added this pull request to the merge queue Jul 24, 2026
Merged via the queue into main with commit e2bdba2 Jul 24, 2026
75 checks passed
@sk593
sk593 deleted the sk593-inject-registry-creds-on-deploy branch July 24, 2026 22:07
sk593 added a commit that referenced this pull request Jul 24, 2026
Resolve README conflict from #12510 (registry creds injected into the app
deploy instead of a control-plane Secret). Keep the custom-types /
recipe-pack step and the OCI state-archive wording; adopt main's updated
run-rad-commands step and drop the obsolete control-plane registry-cred
provisioning step. Renumber the deploy stages accordingly.

Signed-off-by: sk593 <shruthikumar@microsoft.com>

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants