Skip to content

Revert default resource group and environment creation from rad install kubernetes - #12829

Merged
DariuszPorowski merged 2 commits into
mainfrom
lakshmimsft/revert-install-kubernetes-defaults
Aug 26, 2026
Merged

DariuszPorowski merged 2 commits into
mainfrom
lakshmimsft/revert-install-kubernetes-defaults

Conversation

@lakshmimsft

Copy link
Copy Markdown
Contributor

Summary

Reverts the default resource group and environment creation that rad install kubernetes performed,
returning it to a barebones control-plane install. Also removes the --preview flag from this command,
since its only effect was selecting the resource type (and default recipe pack) for the default
environment that is no longer created.

After this change:

  • rad install kubernetes installs the Radius control plane .
  • No default resource group, no default environment, no default recipe pack, and no environment
    targeting the default Kubernetes namespace.

This reverts the behavior introduced by #11870 (shipped in v0.59.0) and the --preview flag added on
top of it by #12504 (shipped in v0.60.0). Unrelated changes that landed in the same files since then
are preserved: the t.Context() test modernization from #12523 and the current docs.radapp.io
architecture URL.

Reason for change

rad install kubernetes silently provisioning a default environment and recipe packs is undesirable
for anyone who intends to customize environments, namespaces, or recipe packs — notably the GitHub
Copilot app integration, where a default environment targeting the default Kubernetes namespace
conflicts with the intended setup.

Opinionated initialization belongs in rad init, where users expect an onboarding flow with defaults
preset. This restores a clean separation of responsibilities:

  • rad install kubernetes — install the control plane only.
  • rad init — install and/or initialize Radius with default resources and recipe packs.

Fixes #12827

How to test

Manual, against a clean cluster:

rad install kubernetes
rad group show default # expect: not found
rad env show default # expect: not found

rad init # still creates the default group, environment, and recipe pack
rad group show default # expect: exists
rad env show default # expect: exists

Also confirm  rad install kubernetes --preview  now reports  unknown flag: --preview , and that the
existing install flags ( --reinstall ,  --chart ,  --set ,  --set-file ,  --kubecontext ,
 --skip-contour-install , and the  --contour-*  flags) are unchanged.

File Summary of change
pkg/cli/cmd/install/kubernetes/kubernetes.go Removed createDefaultGroupAndEnvironment, ensureDefaultResourceGroup, ensureDefaultEnvironment, and ensureDefaultEnvironmentPreview, along with the --preview flag and the ConnectionFactory, KubernetesInterface, Preview, and RadiusCoreClientFactory runner fields. Run now returns after Helm.InstallRadius. Added help text stating the command installs the control plane only and pointing to rad init for defaults.
pkg/cli/cmd/install/kubernetes/kubernetes_test.go Removed mock expectations for default group/environment/recipe-pack creation. Each install test now asserts the full Output.Writes sequence exactly, so any reintroduced default-resource logging fails the test. Retains the t.Context() usage from #12523.
.github/extension/actions/restore-state/action.yml Updated a now-inaccurate comment claiming rad install kubernetes creates the default resource group. Behavior is unchanged — the action already creates the group explicitly.

Note for follow-up:
Check for docs update to reflect updated changes.

Signed-off-by: lakshmimsft <ljavadekar@microsoft.com>
@github-actions

Copy link
Copy Markdown

Dependency Review

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

Scanned Files

None

@lakshmimsft lakshmimsft added pr:breaking-change pr:important High-impact changes needing special attention during release and in release notes labels Aug 26, 2026
@codecov

codecov Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.97%. Comparing base (8966e59) to head (c56c02b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12829      +/-   ##
==========================================
- Coverage   60.02%   59.97%   -0.05%     
==========================================
  Files         776      776              
  Lines       46487    46410      -77     
==========================================
- Hits        27902    27835      -67     
+ Misses      18585    18575      -10     

☔ 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 Aug 26, 2026 •

Copy link
Copy Markdown

Unit Tests

    2 files  ± 0    459 suites  ±0   8m 11s ⏱️ +44s
6 518 tests  -  6  6 516 ✅  -  6  2 💤 ±0  0 ❌ ±0 
7 794 runs   - 12  7 792 ✅  - 12  2 💤 ±0  0 ❌ ±0 

Results for commit c56c02b. ± Comparison against base commit 8966e59.

This pull request removes 6 tests.
github.com/radius-project/radius/pkg/cli/cmd/install/kubernetes ‑ Test_Run/Failure:_default_environment_creation_fails
github.com/radius-project/radius/pkg/cli/cmd/install/kubernetes ‑ Test_Run/Failure:_default_resource_group_creation_fails
github.com/radius-project/radius/pkg/cli/cmd/install/kubernetes ‑ Test_Run/Success:_Install_with_--preview_creates_a_Radius.Core_environment
github.com/radius-project/radius/pkg/cli/cmd/install/kubernetes ‑ Test_Run/Success:_Install_with_no_--kubecontext_flag_passes_empty_context_through
github.com/radius-project/radius/pkg/cli/cmd/install/kubernetes ‑ Test_Run/Success:_Reinstall_with_--preview_leaves_an_existing_Radius.Core_environment_unchanged
github.com/radius-project/radius/pkg/cli/cmd/install/kubernetes ‑ Test_Validate/preview

♻️ This comment has been updated with latest results.

@lakshmimsft
lakshmimsft marked this pull request as ready for review August 26, 2026 16:14
@lakshmimsft
lakshmimsft requested a review from a team as a code owner August 26, 2026 16:14
Copilot AI lite review requested due to automatic review settings August 26, 2026 16:14
@lakshmimsft
lakshmimsft requested a review from a team as a code owner August 26, 2026 16:14

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

This PR reverts rad install kubernetes back to a barebones control-plane-only install by removing the post-install provisioning of the default resource group/environment (and associated recipe pack behavior) and by removing the now-purpose-less --preview flag.

Changes:

  • Removed default resource group/environment (and preview-path) creation from rad install kubernetes, and updated command help text accordingly.
  • Simplified the install runner and updated unit tests to drop default-resource provisioning expectations.
  • Updated the Copilot extension “restore state” action comment to reflect that rad install kubernetes no longer creates the default resource group.

Reviewed changes

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

File Description
pkg/cli/cmd/install/kubernetes/kubernetes.go Removes default group/environment provisioning and the --preview flag; Run now ends after Helm install and help text clarifies control-plane-only behavior.
pkg/cli/cmd/install/kubernetes/kubernetes_test.go Updates validation/run tests to match control-plane-only install behavior (drops default-resource creation assertions).
.github/extension/actions/restore-state/action.yml Fixes an inaccurate comment about rad install kubernetes creating the default resource group.

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

Comment thread pkg/cli/cmd/install/kubernetes/kubernetes_test.go
Comment thread .github/extension/actions/restore-state/action.yml Outdated
@lakshmimsft
lakshmimsft requested a review from a team August 26, 2026 16:29
sk593
sk593 previously approved these changes Aug 26, 2026
Comment thread pkg/cli/cmd/install/kubernetes/kubernetes.go Outdated
nithyatsu
nithyatsu previously approved these changes Aug 26, 2026
Signed-off-by: lakshmimsft <ljavadekar@microsoft.com>
@lakshmimsft
lakshmimsft dismissed stale reviews from nithyatsu and sk593 via c56c02b August 26, 2026 16:58
@lakshmimsft
lakshmimsft enabled auto-merge August 26, 2026 17:01
@radius-functional-tests

radius-functional-tests Bot commented Aug 26, 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 c56c02b
Unique ID funcc00a2fb62e
Image tag pr-funcc00a2fb62e
  • 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-funcc00a2fb62e
  • 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-funcc00a2fb62e
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-funcc00a2fb62e
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-funcc00a2fb62e
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-funcc00a2fb62e
  • 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 corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

@DariuszPorowski
DariuszPorowski merged commit 19376c3 into main Aug 26, 2026
86 of 87 checks passed
@DariuszPorowski
DariuszPorowski deleted the lakshmimsft/revert-install-kubernetes-defaults branch August 26, 2026 17:48
DariuszPorowski added a commit that referenced this pull request Aug 26, 2026
….1 (#12831)

Patch release `v0.60.1` for channel `0.60`.

## Backported PRs

Listed in cherry-pick (topological) order. **Gap filler** = not
requested for the patch, but included because it touched the same region
of a shared file between `release/0.60` and a requested commit. Without
it the cherry-pick has no common merge base and conflicts.

| # | Commit | PR | Role |
| --- | --- | --- | --- |
| 1 | `6882b5fdf` | #12640 | Requested |
| 2 | `af0443809` | #12721 | Requested |
| 3 | `7c6de043d` | #12733 | **Gap filler** —
`.github/workflows/codeql.yml` |
| 4 | `ca7b5a3e7` | #12728 | Requested |
| 5 | `2eac7c1f1` | #12702 | Requested |
| 6 | `b4ebe2f28` | #12751 | Requested |
| 7 | `e30a2594d` | #12727 | Requested |
| 8 | `3c7dfecd6` | #12769 | **Gap filler** —
`.github/workflows/codeql.yml` |
| 9 | `787b6ca1a` | #12765 | **Gap filler** — `build/test.mk` |
| 10 | `f84184955` | #12775 | Requested |
| 11 | `415d5b9c2` | #12779 | Requested |
| 12 | `a1d976013` | #12782 | Requested |
| 13 | `14a21bd0d` | #12786 | **Gap filler** — `build/test.mk` |
| 14 | `a87146c77` | #12764 | **Gap filler** — `build/test.mk` |
| 15 | `073ca3cfa` | #12758 | Requested |
| 16 | `5e1f94c13` | #12785 | **Gap filler** —
`pkg/cli/cmd/install/kubernetes/kubernetes.go` |
| 17 | `1fd650af5` | #12742 | Requested |
| 18 | `19376c3f3` | #12829 | Requested |

Five of the six gap fillers are CI/test-only. #12785 is not: it adds a
Helm `control-plane-readiness` Job, a `pre-upgrade
wait-for-control-plane` command, UCP readiness probes, and a
NetworkPolicy change. It is required for #12829 to apply.

## Validation

Full chain dry-run cherry-picked onto `release/0.60` with zero
conflicts. `go build ./...` clean; `pkg/cli/cmd/install/kubernetes`,
`cmd/pre-upgrade/cmd`, `pkg/cli/...`, `pkg/graph/...`, and
`test/validation` all pass.

---------

Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
DariuszPorowski pushed a commit that referenced this pull request Aug 26, 2026
…ll kubernetes (#12829)

## Summary
Reverts the default resource group and environment creation that `rad
install kubernetes` performed,
returning it to a barebones control-plane install. Also removes the
`--preview` flag from this command,
since its only effect was selecting the resource type (and default
recipe pack) for the default
environment that is no longer created.

After this change:

- `rad install kubernetes` installs the Radius control plane .
- No `default` resource group, no `default` environment, no default
recipe pack, and no environment
  targeting the `default` Kubernetes namespace.

This reverts the behavior introduced by #11870 (shipped in v0.59.0) and
the `--preview` flag added on
top of it by #12504 (shipped in v0.60.0). Unrelated changes that landed
in the same files since then
are preserved: the `t.Context()` test modernization from #12523 and the
current `docs.radapp.io`
architecture URL.

## Reason for change

`rad install kubernetes` silently provisioning a default environment and
recipe packs is undesirable
for anyone who intends to customize environments, namespaces, or recipe
packs — notably the GitHub
Copilot app integration, where a default environment targeting the
`default` Kubernetes namespace
conflicts with the intended setup.

Opinionated initialization belongs in `rad init`, where users expect an
onboarding flow with defaults
preset. This restores a clean separation of responsibilities:

- `rad install kubernetes` — install the control plane only.
- `rad init` — install and/or initialize Radius with default resources
and recipe packs.

Fixes #12827

## How to test
Manual, against a clean cluster:

rad install kubernetes
rad group show default   # expect: not found
rad env show default     # expect: not found

rad init # still creates the default group, environment, and recipe pack
rad group show default   # expect: exists
rad env show default     # expect: exists

Also confirm  rad install kubernetes --preview  now reports  unknown
flag: --preview , and that the
existing install flags ( --reinstall ,  --chart ,  --set ,  --set-file ,
 --kubecontext ,
 --skip-contour-install , and the  --contour-*  flags) are unchanged.

| File | Summary of change |
| ---- | ----------------- |
| `pkg/cli/cmd/install/kubernetes/kubernetes.go` | Removed
`createDefaultGroupAndEnvironment`, `ensureDefaultResourceGroup`,
`ensureDefaultEnvironment`, and `ensureDefaultEnvironmentPreview`, along
with the `--preview` flag and the `ConnectionFactory`,
`KubernetesInterface`, `Preview`, and `RadiusCoreClientFactory` runner
fields. `Run` now returns after `Helm.InstallRadius`. Added help text
stating the command installs the control plane only and pointing to `rad
init` for defaults. |
| `pkg/cli/cmd/install/kubernetes/kubernetes_test.go` | Removed mock
expectations for default group/environment/recipe-pack creation. Each
install test now asserts the full `Output.Writes` sequence exactly, so
any reintroduced default-resource logging fails the test. Retains the
`t.Context()` usage from #12523. |
| `.github/extension/actions/restore-state/action.yml` | Updated a
now-inaccurate comment claiming `rad install kubernetes` creates the
`default` resource group. Behavior is unchanged — the action already
creates the group explicitly. |

Note for follow-up:
Check for docs update to reflect updated changes.

---------

Signed-off-by: lakshmimsft <ljavadekar@microsoft.com>
(cherry picked from commit 19376c3)
Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
DariuszPorowski added a commit that referenced this pull request Aug 26, 2026
….1 (#12831)

Patch release `v0.60.1` for channel `0.60`.

## Backported PRs

Listed in cherry-pick (topological) order. **Gap filler** = not
requested for the patch, but included because it touched the same region
of a shared file between `release/0.60` and a requested commit. Without
it the cherry-pick has no common merge base and conflicts.

| # | Commit | PR | Role |
| --- | --- | --- | --- |
| 1 | `6882b5fdf` | #12640 | Requested |
| 2 | `af0443809` | #12721 | Requested |
| 3 | `7c6de043d` | #12733 | **Gap filler** —
`.github/workflows/codeql.yml` |
| 4 | `ca7b5a3e7` | #12728 | Requested |
| 5 | `2eac7c1f1` | #12702 | Requested |
| 6 | `b4ebe2f28` | #12751 | Requested |
| 7 | `e30a2594d` | #12727 | Requested |
| 8 | `3c7dfecd6` | #12769 | **Gap filler** —
`.github/workflows/codeql.yml` |
| 9 | `787b6ca1a` | #12765 | **Gap filler** — `build/test.mk` |
| 10 | `f84184955` | #12775 | Requested |
| 11 | `415d5b9c2` | #12779 | Requested |
| 12 | `a1d976013` | #12782 | Requested |
| 13 | `14a21bd0d` | #12786 | **Gap filler** — `build/test.mk` |
| 14 | `a87146c77` | #12764 | **Gap filler** — `build/test.mk` |
| 15 | `073ca3cfa` | #12758 | Requested |
| 16 | `5e1f94c13` | #12785 | **Gap filler** —
`pkg/cli/cmd/install/kubernetes/kubernetes.go` |
| 17 | `1fd650af5` | #12742 | Requested |
| 18 | `19376c3f3` | #12829 | Requested |

Five of the six gap fillers are CI/test-only. #12785 is not: it adds a
Helm `control-plane-readiness` Job, a `pre-upgrade
wait-for-control-plane` command, UCP readiness probes, and a
NetworkPolicy change. It is required for #12829 to apply.

## Validation

Full chain dry-run cherry-picked onto `release/0.60` with zero
conflicts. `go build ./...` clean; `pkg/cli/cmd/install/kubernetes`,
`cmd/pre-upgrade/cmd`, `pkg/cli/...`, `pkg/graph/...`, and
`test/validation` all pass.

---------

Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
(cherry picked from commit e5938bf)
Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
DariuszPorowski pushed a commit that referenced this pull request Aug 26, 2026
…ll kubernetes (#12829)

## Summary
Reverts the default resource group and environment creation that `rad
install kubernetes` performed,
returning it to a barebones control-plane install. Also removes the
`--preview` flag from this command,
since its only effect was selecting the resource type (and default
recipe pack) for the default
environment that is no longer created.

After this change:

- `rad install kubernetes` installs the Radius control plane .
- No `default` resource group, no `default` environment, no default
recipe pack, and no environment
  targeting the `default` Kubernetes namespace.

This reverts the behavior introduced by #11870 (shipped in v0.59.0) and
the `--preview` flag added on
top of it by #12504 (shipped in v0.60.0). Unrelated changes that landed
in the same files since then
are preserved: the `t.Context()` test modernization from #12523 and the
current `docs.radapp.io`
architecture URL.

## Reason for change

`rad install kubernetes` silently provisioning a default environment and
recipe packs is undesirable
for anyone who intends to customize environments, namespaces, or recipe
packs — notably the GitHub
Copilot app integration, where a default environment targeting the
`default` Kubernetes namespace
conflicts with the intended setup.

Opinionated initialization belongs in `rad init`, where users expect an
onboarding flow with defaults
preset. This restores a clean separation of responsibilities:

- `rad install kubernetes` — install the control plane only.
- `rad init` — install and/or initialize Radius with default resources
and recipe packs.

Fixes #12827

## How to test
Manual, against a clean cluster:

rad install kubernetes
rad group show default   # expect: not found
rad env show default     # expect: not found

rad init # still creates the default group, environment, and recipe pack
rad group show default   # expect: exists
rad env show default     # expect: exists

Also confirm  rad install kubernetes --preview  now reports  unknown
flag: --preview , and that the
existing install flags ( --reinstall ,  --chart ,  --set ,  --set-file ,
 --kubecontext ,
 --skip-contour-install , and the  --contour-*  flags) are unchanged.

| File | Summary of change |
| ---- | ----------------- |
| `pkg/cli/cmd/install/kubernetes/kubernetes.go` | Removed
`createDefaultGroupAndEnvironment`, `ensureDefaultResourceGroup`,
`ensureDefaultEnvironment`, and `ensureDefaultEnvironmentPreview`, along
with the `--preview` flag and the `ConnectionFactory`,
`KubernetesInterface`, `Preview`, and `RadiusCoreClientFactory` runner
fields. `Run` now returns after `Helm.InstallRadius`. Added help text
stating the command installs the control plane only and pointing to `rad
init` for defaults. |
| `pkg/cli/cmd/install/kubernetes/kubernetes_test.go` | Removed mock
expectations for default group/environment/recipe-pack creation. Each
install test now asserts the full `Output.Writes` sequence exactly, so
any reintroduced default-resource logging fails the test. Retains the
`t.Context()` usage from #12523. |
| `.github/extension/actions/restore-state/action.yml` | Updated a
now-inaccurate comment claiming `rad install kubernetes` creates the
`default` resource group. Behavior is unchanged — the action already
creates the group explicitly. |

Note for follow-up:
Check for docs update to reflect updated changes.

---------

Signed-off-by: lakshmimsft <ljavadekar@microsoft.com>
(cherry picked from commit 19376c3)
Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
DariuszPorowski added a commit that referenced this pull request Aug 26, 2026
….1 (#12831)

Patch release `v0.60.1` for channel `0.60`.

## Backported PRs

Listed in cherry-pick (topological) order. **Gap filler** = not
requested for the patch, but included because it touched the same region
of a shared file between `release/0.60` and a requested commit. Without
it the cherry-pick has no common merge base and conflicts.

| # | Commit | PR | Role |
| --- | --- | --- | --- |
| 1 | `6882b5fdf` | #12640 | Requested |
| 2 | `af0443809` | #12721 | Requested |
| 3 | `7c6de043d` | #12733 | **Gap filler** —
`.github/workflows/codeql.yml` |
| 4 | `ca7b5a3e7` | #12728 | Requested |
| 5 | `2eac7c1f1` | #12702 | Requested |
| 6 | `b4ebe2f28` | #12751 | Requested |
| 7 | `e30a2594d` | #12727 | Requested |
| 8 | `3c7dfecd6` | #12769 | **Gap filler** —
`.github/workflows/codeql.yml` |
| 9 | `787b6ca1a` | #12765 | **Gap filler** — `build/test.mk` |
| 10 | `f84184955` | #12775 | Requested |
| 11 | `415d5b9c2` | #12779 | Requested |
| 12 | `a1d976013` | #12782 | Requested |
| 13 | `14a21bd0d` | #12786 | **Gap filler** — `build/test.mk` |
| 14 | `a87146c77` | #12764 | **Gap filler** — `build/test.mk` |
| 15 | `073ca3cfa` | #12758 | Requested |
| 16 | `5e1f94c13` | #12785 | **Gap filler** —
`pkg/cli/cmd/install/kubernetes/kubernetes.go` |
| 17 | `1fd650af5` | #12742 | Requested |
| 18 | `19376c3f3` | #12829 | Requested |

Five of the six gap fillers are CI/test-only. #12785 is not: it adds a
Helm `control-plane-readiness` Job, a `pre-upgrade
wait-for-control-plane` command, UCP readiness probes, and a
NetworkPolicy change. It is required for #12829 to apply.

## Validation

Full chain dry-run cherry-picked onto `release/0.60` with zero
conflicts. `go build ./...` clean; `pkg/cli/cmd/install/kubernetes`,
`cmd/pre-upgrade/cmd`, `pkg/cli/...`, `pkg/graph/...`, and
`test/validation` all pass.

---------

Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
(cherry picked from commit e5938bf)
Signed-off-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
sk593 added a commit that referenced this pull request Aug 26, 2026
The repo-based deploy pipeline persists control-plane state at teardown via
rad shutdown, which runs under if: always() so a partially-applied deploy is
not lost. But it ran unconditionally: a workflow that failed before the
restore-state action's rad startup completed would still back up the
uninitialized control-plane databases and push them over the durable state
archive. Because rad startup restores that archive wholesale (pg_dump --clean
--if-exists), one such run corrupts state for every future run -- the archive
is replaced with blank state, restored on the next run, re-persisted, and so
on. This is what surfaced as a deterministic 'resource group "default" not
found' after #12829 stopped rad install kubernetes from re-seeding the group
server-side.

Gate persistence on a successful restore: restore-state writes a marker after
rad startup succeeds, and teardown skips rad shutdown when the marker is
absent. rad startup is still a legitimate no-op on the first run (empty
archive) but succeeds and writes the marker, so first-run seeding and
persistence after a later deploy failure both still happen; only runs that
never reached a successful startup are prevented from overwriting the archive.

Add a wiring test asserting the marker is written after rad startup and that
teardown gates rad shutdown on it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
pull Bot pushed a commit to TheTechOddBug/radius that referenced this pull request Aug 27, 2026
…shutdown (radius-project#12840)

## Description

The repo-based deploy pipeline (`run-rad-commands-azure.yml` /
`run-rad-commands-aws.yml`, and the `delete-*` workflows) restores
control-plane state at setup with `rad startup` and persists it at
teardown with `rad shutdown`. `rad startup` restores the previous run's
snapshot with `pg_dump --clean --if-exists` — a wholesale
drop-and-replace of the control-plane PostgreSQL databases, not a merge.

Two independent problems corrupted the shared state archive and made
deploys fail deterministically with `resource group "default" not
found`:

1. **A corrupt (group-less) archive never repaired itself.** After
radius-project#12829 stopped `rad install kubernetes` from re-seeding the `default`
group server-side, the pipeline created it *before* `rad startup`. Since
startup restores the databases wholesale, a group created before it is
dropped whenever the restored snapshot lacks the group — so once the
archive was group-less it stayed that way, and every deploy failed:

   ```
   21:43:55  rad group create default                 # created...
21:43:57 Restoring control-plane databases... # ...then dropped by the
wholesale restore
   21:44:21  State restored successfully.
21:44:22 rad deploy $ENV_BICEP -> NotFound: resource group
".../resourcegroups/default" not found
   ```

2. **A pre-startup failure overwrote the good archive with blank
state.** `rad shutdown` ran unconditionally under `if: always()`. A
workflow that failed *before* `rad startup` completed (setup, cluster
connect, OIDC, credential registration, or startup itself) still hit
teardown, backed up the uninitialized databases, and overwrote the
archive. The next run restored that blank state wholesale and
re-persisted it — self-perpetuating corruption.

## Fix

A two-part fix; neither half is sufficient alone.

**1. Create the `default` group *after* `rad startup` (self-heal).**
Moving `rad group create`/`switch` below the restore means the group is
(re)created on top of whatever the restore produced, so it is present
for the deploy and persisted by the next `rad shutdown`. A group-less
archive now heals itself on the next successful run. `rad startup` has
no resource-group dependency, so nothing needs the group earlier.

**2. Guard `rad shutdown` on a successful restore.** `restore-state`
exposes a `state-restored` output, set to `true` only after `rad
startup` succeeds. The workflow passes it into `teardown`'s
`state-restored` input; when it is not `true`, teardown skips `rad
shutdown` (emitting a `::warning::`) so a run that never reached startup
cannot overwrite the archive. This replaces the earlier `${RUNNER_TEMP}`
file marker with an explicit action output→input, so the dependency is
visible in the workflow YAML and fails safe if the steps are ever split
across jobs.

This preserves the behaviors we *do* want:

- **First-run seeding.** `rad startup` is a no-op on the first run
(empty archive) but still succeeds and sets the output, so `rad
shutdown` runs and seeds the archive.
- **Persist after a later failure.** If startup succeeded and a *later*
step fails (e.g. a partially-applied Terraform deploy), the output is
`true`, so `rad shutdown` still runs and that work is not lost.

The guard is pure workflow orchestration — it does **not** couple `rad
startup` and `rad shutdown` as commands.

### Also in this PR

- **`teardown`: `rad app list` → `rad app list --preview`.** The
pipeline deploys `Radius.Core` applications, but the teardown status
step queried the legacy `Applications.Core` plane and listed nothing.
`--preview` matches the surface the rest of the pipeline uses, and a
failed listing now surfaces a `::warning::` instead of being swallowed
by `|| true`.

## Type of change

- Bugfix

## Fixes

Fixes radius-project#12838

## Testing

- `.github/extension/actions/teardown/teardown_test.sh` (wired into
`build/test.mk` as `test-teardown`) extracts the actual `run:` blocks
from the `restore-state` and `teardown` composite actions and executes
them with stubbed `rad`/`git` (no cluster/CLI), asserting real behavior:
- `restore-state` sets `state-restored=true` on `$GITHUB_OUTPUT` after
`rad startup`, and creates the `default` group **after** startup (order
asserted from the invocation log).
- Negative path: when `rad startup` fails, the block exits non-zero and
never sets the output.
  - First run: a no-op `rad startup` still sets the output.
- `teardown` runs `rad shutdown` only when `state-restored == "true"`,
and otherwise skips with a `::warning::`.
- `teardown` lists apps via `rad app list --preview` and warns (does not
swallow) on failure.
- All four workflows wire `restore-state` → `teardown` within the same
job.
  Verified by mutation that each invariant, when broken, fails the test.
- `make test-teardown` and `make test-extension-action-shell-syntax`
pass; the test is `shellcheck`-clean.

## Follow-ups (out of scope)

Raised in review and intentionally deferred — neither is required to fix
radius-project#12838:

- radius-project#12847 — `rad shutdown` should refuse to persist a degenerate/empty
snapshot (defense-in-depth for control-plane degradation *after* a
successful startup).
- radius-project#12848 — add a `concurrency:` group to serialize workflows that share
the state archive.

## Notes

Example failing runs (before this fix):
https://github.com/sk593/aks-store-demo/actions/runs/33015265288,
https://github.com/sk593/aks-store-demo/actions/runs/33016468544

---------

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:important High-impact changes needing special attention during release and in release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Revert default environment and recipe-pack creation from rad install kubernetes

6 participants