Skip to content

feat(ci): publish main Bicep types to GHCR - #13119

Draft
willdavsmith wants to merge 2 commits into
willdavsmith-cloud-publishing-isolationfrom
willdavsmith-ghcr-publisher-dispatch
Draft

willdavsmith wants to merge 2 commits into
willdavsmith-cloud-publishing-isolationfrom
willdavsmith-ghcr-publisher-dispatch

Conversation

@willdavsmith

@willdavsmith willdavsmith commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Merging is the main Bicep publishing cutover. Protected Radius main builds publish ghcr.io/radius-project/bicep-types-radius:edge and mirror the same manifest digest to biceptypes.azurecr.io/radius:latest, with no external-main fallback.

This six-file layer preserves the current snapshot job graph, edge-only main CLI/image publication, external-image alias policy, release attestation gates, current-main checks, Helm gate, and native main queue. It replaces only the main Bicep caller and adds its publication-status check. Release workflows, tag policy, shared publish-bicep environment behavior, consumers, and GHCR stable latest remain unchanged. The existing Radius/AWS immutable ACR staging jobs and promote-bicep-types.mjs finalizer remain intact for the later release-contract layer.

Reason for change

Related to #12937. Read-only generation captures a native OCI snapshot once. A fresh trusted uploader validates source/run/artifact identity, digests, and the Bicep provider contract before native ORAS copies; downloaded code is never executed. The caller forwards only the three required Azure identifiers, and the generation job does not consume them.

Canonical protected main pushes and manual main runs may publish. Successful change detection permits intentional skips; failed/missing classification, unexpected skips, and publication failures fail the summary. Existing release-metadata filtering and cloud skip-report requirements are preserved. Current-main retries reuse the snapshot. Stale first attempts skip before mutation; superseded retries fail closed because previous writes may be partial. Started pairs finish or fail visibly with receipt evidence.

Dependencies and landing

Depends on #13134 -> #13133. The upstream release foundation is merged into main, and this PR is based on the synchronized cloud-isolation branch. The existing downstream stack targets main; land its remaining layers in order. No upstream retarget or replacement release pipeline is required.

Setup before cutover

  • Retain the manual-writer restrictions and cloud credential isolation from the preceding layers. Restrict elevated workflow definitions and production authority to trusted code, including maintained PR base branches; repository package grants are not per-workflow ACLs.
  • Allow the source repository's GITHUB_TOKEN to create the canonical package; the trusted uploader requests packages: write. No PAT or separate publisher repository is needed.
  • The existing repository secrets BICEPTYPES_CLIENT_ID, BICEPTYPES_TENANT_ID, and BICEPTYPES_SUBSCRIPTION_ID are explicitly passed to required callee inputs, without broad secret inheritance. The trusted uploader uses the shared azure-oidc-login.mjs retry helper with those same identifiers and clears its Azure session afterward. Verify ACR authorization and establish federation scoped to the new main reusable workflow; helper reuse does not establish that trust. Preserve legacy issuer bindings, release tag policy, and shared environment approval behavior; no new protected-release-tag prerequisite is introduced.
  • Before merging this main cutover, drain the old Radius development dispatches and in-flight publish-bicep-types.yml receiver jobs, and prevent renewed production development writes from main/edge to biceptypes.azurecr.io/radius:latest, including requests whose omitted target defaults to radius. Keep the legacy tagged Radius release writer until all old unpublished releases finish and the release-contract handoff (R3) is complete; preserve explicit test/radius publishing and existing ACR reads. Do not disable the entire receiver or assume an AWS-only guard covers this Radius path. Private publisher edits/setup require separate approval and have not been performed.

External identity and package setup is not performed by this PR. Full-version/RC publication and AWS/release coordination remain outside this main-only change.

First upload and public access

The first GHCR push can create the package, normally as private. Upload, mirroring, and digest verification happen before the public-visibility check. Private/internal visibility or an API failure fails distribution validation while preserving an uploaded receipt with both verified digests.

A package admin must use Packages -> bicep-types-radius -> Package settings -> Change visibility -> Public, then rerun and verify anonymous restore before switching consumers. Visibility is never changed automatically. Superseded runs with no writes do not query the package.

How to test

Use the repository's Node.js version, Bash, Git, jq, yq, and OpenSSL. From the repository root, run:

node --test .github/scripts/bicep-types.test.mjs .github/scripts/cloud-test-artifacts.test.mjs .github/scripts/changes_test.mjs
TMPDIR="$(node -p 'require("node:fs").realpathSync(require("node:os").tmpdir())')" node --test .github/scripts/azure-oidc-login_test.mjs
bash .github/scripts/build-summary_test.sh
bash .github/scripts/release-cutover_test.sh

These pass 334 publisher/cloud/change-detector Node cases, 44 OIDC helper cases, 10 summary tests, and 15 release-cutover tests, respectively. The canonical TMPDIR avoids the inherited OIDC fixture's /var versus /private/var entry-point comparison on macOS.

Expected behavior includes fail-closed source/bootstrap checks, the trusted Deployment Engine default edge tag with explicit dispatch tags preserved, retained cloud producer-attempt tags, and successful classification plus successful skip reporting before a filtered run is accepted. All 18 Functional Test Run status cases execute the real summary JavaScript. The parent's release-metadata filtering, external-image edge/latest policy, release attestation gates, Helm fixes, Bash helper invocations, and tool/action pins are retained unchanged. The Radius Bicep development mirror deliberately remains GHCR edge to ACR latest; it is not an external-image stable-alias promotion.

Run the scoped workflow and formatting checks:

actionlint -ignore 'unexpected key "queue" for "concurrency" section' .github/workflows/build-main.yaml .github/workflows/__publish-bicep-types.yaml
actionlint -shellcheck= .github/workflows/unit-tests.yaml
npm exec --yes --package=markdownlint-cli2@0.24.0 -- markdownlint-cli2 docs/contributing/contributing-code/contributing-code-github-workflows/README.md --config .github/linters/.markdownlint-cli2.yaml
npm exec --yes --package=prettier@3.9.10 -- prettier --check --config .github/linters/.prettierrc.yml .github/scripts/bicep-types.mjs .github/scripts/bicep-types.test.mjs .github/workflows/__publish-bicep-types.yaml .github/workflows/build-main.yaml .github/workflows/unit-tests.yaml docs/contributing/contributing-code/contributing-code-github-workflows/README.md

All four commands pass. Actionlint 1.7.12 does not recognize native concurrency.queue; the unit workflow also has an unchanged Windows PowerShell SC2086 diagnostic. Both occur on the unmodified parent, so the first command excludes only that queue diagnostic and the second checks workflow schema/expressions without ShellCheck. Exact markdownlint-cli2 0.24.0 and Prettier 3.9.10 pass without changing manifests or lint configuration.

The unchanged publisher runtime previously passed local native OCI tar import, exact registry copies, identical retry digests, anonymous restore/compile, and corrupt-blob rejection. This synchronization is source-level validation, not proof of live Azure authentication or production publication. No production registry, identity, visibility, or settings operations were performed.

File change summary

File Summary of change
.github/scripts/bicep-types.mjs Eligibility/snapshot validation, native tool orchestration, exact publication pair, visibility check, and receipts.
.github/scripts/bicep-types.test.mjs Focused source, bootstrap, failure, and trusted helper/secret-wiring tests.
.github/workflows/__publish-bicep-types.yaml Read-only generation and separate trusted publishing using current action pins and existing retry helpers.
.github/workflows/build-main.yaml Sole direct Bicep caller and summary check while preserving current main classification and orchestration.
.github/workflows/unit-tests.yaml Add the Bicep Node test step without replacing current module-download or Windows tests.
docs/contributing/contributing-code/contributing-code-github-workflows/README.md Publisher setup and retry-helper guidance alongside current contributor instructions.

@willdavsmith
willdavsmith requested review from a team as code owners September 25, 2026 18:24
Copilot AI lite review requested due to automatic review settings September 25, 2026 18:24
@github-actions github-actions Bot added the pr:waiting-for-review A reviewer owns the next action; required approval is pending or unverifiable label Sep 25, 2026
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Dependency Review

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

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/setup-node 949feb2413d6458794dcd2491c4babbbce0c15c1 🟢 6.4
Details
CheckScoreReason
Maintained🟢 1016 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Binary-Artifacts🟢 9binaries present in source code
Code-Review🟢 10all changesets reviewed
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies🟢 5dependency not pinned by hash detected -- score normalized to 5
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
License🟢 10license file detected
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 10SAST tool is run on all commits

Scanned Files

  • .github/workflows/unit-tests.yaml

@willdavsmith willdavsmith added the pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work label Sep 25, 2026

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.

Copilot review overview

🟡 Changes recommended

Unresolved critical validation/configuration issues and moderate workflow/test gaps remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
What changed in this PR

Adds a disabled-by-default protected-main workflow to publish Radius Bicep types to GHCR and mirror them to ACR.

Changes:

  • Adds serialized capture, validation, publication, and retry handling.
  • Adds provenance, receipts, routing safeguards, tests, and documentation.
File Summary
docs/​contributing/​contributing-code/​contributing-code-github-workflows/​README.md Documents activation and verification. Nit (1 vote): install pinned yq in the local verification sequence.
.github/​workflows/​unit-tests.yaml Runs focused Python and Node.js tests.
.github/​workflows/​build-main.yaml Selects one publisher and validates summary results.
.github/​workflows/​__publish-bicep-types.yaml Captures and publishes validated bundles. Moderate (1 vote): wait for the registry service to become ready.
.github/​scripts/​bicep-types.py Validates, stamps, copies, and records publication data. Critical (2 votes): the generated Bicep configuration is not selected. Critical (1 vote): references in decoded type documents are not fully validated.
.github/​scripts/​bicep-types-workflows.test.mjs Tests workflow routing and safeguards.
.github/​scripts/​bicep-types_test.py Tests publisher contracts, retries, and failure cases.
.github/​scripts/​bicep-types_local_test.py Verifies local OCI packaging and compilation. Moderate (1 vote): the alias-specific test uses a digest instead of tag references.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/scripts/bicep-types.py Outdated
for child in value:
check_refs(child)

check_refs(index)
Comment thread .github/scripts/bicep-types.py Outdated
Comment on lines +582 to +585
command(
"bicep",
"publish-extension",
str(Path(index_file).resolve()),
@codecov

codecov Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.27%. Comparing base (a3cf4de) to head (673005d).

Additional details and impacted files
@@                           Coverage Diff                            @@
##           willdavsmith-cloud-publishing-isolation   #13119   +/-   ##
========================================================================
  Coverage                                    69.27%   69.27%           
========================================================================
  Files                                          735      735           
  Lines                                        40385    40385           
========================================================================
  Hits                                         27976    27976           
  Misses                                       12409    12409           

☔ 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.

@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Unit Tests

    2 files  ±0    420 suites  ±0   18m 45s ⏱️ +50s
7 957 tests ±0  7 955 ✅ ±0  2 💤 ±0  0 ❌ ±0 
9 133 runs  ±0  9 131 ✅ ±0  2 💤 ±0  0 ❌ ±0 

Results for commit 673005d. ± Comparison against base commit a3cf4de.

♻️ This comment has been updated with latest results.

@willdavsmith
willdavsmith marked this pull request as draft September 25, 2026 18:59
@github-actions github-actions Bot removed the pr:waiting-for-review A reviewer owns the next action; required approval is pending or unverifiable label Sep 25, 2026
@willdavsmith willdavsmith changed the title feat(ci): publish Radius Bicep edge types directly feat(ci): publish Radius Bicep edge snapshots Sep 25, 2026
@willdavsmith willdavsmith changed the title feat(ci): publish Radius Bicep edge snapshots feat(ci): publish main Bicep types to GHCR Sep 28, 2026
@willdavsmith
willdavsmith force-pushed the willdavsmith-ghcr-publisher-dispatch branch from 46b57e8 to 5308244 Compare September 29, 2026 21:20
@github-actions github-actions Bot added the pr:needs-rebase The pull request has merge conflicts label Sep 29, 2026
@willdavsmith
willdavsmith changed the base branch from main to willdavsmith-cloud-publishing-isolation September 29, 2026 21:22
@github-actions github-actions Bot removed the pr:needs-rebase The pull request has merge conflicts label Sep 29, 2026
@github-actions github-actions Bot added the pr:needs-rebase The pull request has merge conflicts label Oct 1, 2026
@willdavsmith
willdavsmith force-pushed the willdavsmith-ghcr-publisher-dispatch branch from 5308244 to def54f2 Compare October 1, 2026 16:50
@github-actions github-actions Bot removed the pr:needs-rebase The pull request has merge conflicts label Oct 1, 2026
@github-actions github-actions Bot added the pr:needs-rebase The pull request has merge conflicts label Oct 21, 2026
@willdavsmith
willdavsmith force-pushed the willdavsmith-ghcr-publisher-dispatch branch from def54f2 to 2f8b064 Compare October 21, 2026 18:32
@github-actions github-actions Bot removed the pr:needs-rebase The pull request has merge conflicts label Oct 21, 2026
@willdavsmith
willdavsmith force-pushed the willdavsmith-ghcr-publisher-dispatch branch from 2f8b064 to b6ae383 Compare October 21, 2026 19:40
@github-actions github-actions Bot added the pr:needs-rebase The pull request has merge conflicts label Oct 27, 2026
@willdavsmith
willdavsmith force-pushed the willdavsmith-ghcr-publisher-dispatch branch from b6ae383 to 75d0415 Compare October 27, 2026 21:42
@github-actions github-actions Bot removed the pr:needs-rebase The pull request has merge conflicts label Oct 27, 2026
Generate reusable native OCI snapshots and publish Radius edge with an
exact-digest ACR compatibility mirror on the release foundation.

Preserve upstream snapshot jobs, edge-only publication, release tag policy
and shared release environment behavior. Pass only the three named Azure
identifiers and retain first-upload visibility validation and receipts.

Signed-off-by: willdavsmith <willdavsmith@gmail.com>
Signed-off-by: willdavsmith <willdavsmith@gmail.com>
@willdavsmith
willdavsmith force-pushed the willdavsmith-ghcr-publisher-dispatch branch from 75d0415 to 673005d Compare October 29, 2026 21:53
@radius-functional-tests

radius-functional-tests Bot commented Oct 29, 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 673005d
Unique ID funcb785333f49
Image tag test-funcb785333f49-40961477518-1
  • 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>:test-funcb785333f49-40961477518-1
  • 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:test-funcb785333f49-40961477518-1
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:test-funcb785333f49-40961477518-1
  • controller test image location: ghcr.io/radius-project/dev/controller:test-funcb785333f49-40961477518-1
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:test-funcb785333f49-40961477518-1
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:edge

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 corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

This branch has not been deployed

No deployments
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.

2 participants