diff --git a/.github/actions/prerelease-setup/README.md b/.github/actions/prerelease-setup/README.md
index 881a80a..fb47160 100644
--- a/.github/actions/prerelease-setup/README.md
+++ b/.github/actions/prerelease-setup/README.md
@@ -14,11 +14,22 @@ The action performs, in order:
5. Install `helm` (`azure/setup-helm@v5`).
6. AWS Login via OIDC (`aws-actions/configure-aws-credentials@v6`,
`role-to-assume: arn:aws:iam::084374023943:role/e2e-test-executor`,
- `aws-region: us-west-2`, `role-duration-seconds: 6300`).
-7. Resolve and validate the four version inputs (see below).
-8. Download the `vcluster` CLI binary that matches the resolved base
+ `aws-region: us-west-2`, `role-duration-seconds: 6300`). The action
+ exports `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` /
+ `AWS_SESSION_TOKEN` to `$GITHUB_ENV` by default, so consumer steps
+ reading them as `env.AWS_*` resolve as expected.
+7. Resolve and validate the four version inputs (see below). Empty
+ inputs fall back to "latest" via the GitHub API: latest release for
+ `standalone-vcluster-version` and `platform-base-version`; latest
+ pre-release for `standalone-vcluster-upgrade-version` and
+ `platform-rc-version`.
+8. Verify the resolved vCluster releases publish the assets the
+ downstream test relies on (`install-standalone.sh` for base + upgrade,
+ `vcluster-linux-amd64` for upgrade). Fails fast before any EC2 / VCI
+ provisioning if an asset is missing.
+9. Download the `vcluster` CLI binary that matches the resolved base
standalone vCluster version.
-9. Verify `kubectl`, `helm`, and `vcluster` are on `$PATH`.
+10. Verify `kubectl`, `helm`, and `vcluster` are on `$PATH`.
The action is intended for the two pre-release jobs only. AI Cloud's EC2
provisioning (`aws-test-infra`) and the Ginkgo test execution
@@ -31,10 +42,10 @@ provisioning (`aws-test-infra`) and the Ginkgo test execution
| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
|-------------------------------------|--------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| github-token | string | true | | GitHub token with contents:read on loft-sh/loft-enterprise.
Required because the platform release resolvers
call the GitHub API for a
private repo; unauthenticated calls return 404.
Pass ${{ github.token }} from a
job whose permissions grant contents:read. |
-| platform-base-version | string | false | | Platform version for the initial install
(e.g. 4.9.0). Empty leaves the output empty;
the consumer wires its own default
into the test step. |
+| platform-base-version | string | false | | Platform version for the initial install
(e.g. 4.9.0). Empty resolves to the latest
stable release of loft-sh/loft-enterprise. |
| platform-rc-version | string | false | | Platform RC version for upgrade (e.g. 4.10.0-alpha.6).
Empty resolves to the latest pre-release
of loft-sh/loft-enterprise. |
| role-session-name | string | true | | AWS STS role-session-name. Each consumer job
passes a distinct value (e.g. prerelease-vcluster-, prerelease-aicloud-). |
-| standalone-vcluster-upgrade-version | string | true | | vCluster version to upgrade standalone to
(e.g. 0.35.0-alpha.7). Must differ from the resolved
base version. |
+| standalone-vcluster-upgrade-version | string | false | | vCluster version to upgrade standalone to
(e.g. 0.35.0-alpha.7). Empty resolves to the latest
vCluster pre-release. Must differ from the
resolved base version. |
| standalone-vcluster-version | string | false | | vCluster version to install for standalone
(e.g. 0.34.0). Empty resolves to the latest
GitHub release of loft-sh/vcluster. |
@@ -47,26 +58,26 @@ the `v` before validating against the semver regex
-| OUTPUT | TYPE | DESCRIPTION |
-|-------------------------------------|--------|--------------------------------------------------------------------------------------|
-| platform-base-version | string | Validated platform base version (no leading v). Empty
when the input was empty. |
-| platform-rc-version | string | Resolved platform RC version (no leading v). |
-| standalone-vcluster-upgrade-version | string | Validated standalone vCluster upgrade version (no leading v). |
-| standalone-vcluster-version | string | Resolved standalone vCluster version (no leading v). |
+| OUTPUT | TYPE | DESCRIPTION |
+|-------------------------------------|--------|---------------------------------------------------------------|
+| platform-base-version | string | Resolved platform base version (no leading v). |
+| platform-rc-version | string | Resolved platform RC version (no leading v). |
+| standalone-vcluster-upgrade-version | string | Resolved standalone vCluster upgrade version (no leading v). |
+| standalone-vcluster-version | string | Resolved standalone vCluster version (no leading v). |
-Outputs are written to `$GITHUB_OUTPUT` only. The consumer wires them to
-its downstream test step via an `env:` block (see Usage below). This
-matches the convention of `aws-test-infra` and avoids the
-`github-env` zizmor finding that comes with mirroring values into
-`$GITHUB_ENV` from a composite step.
+Resolved versions are written to **both** `$GITHUB_OUTPUT` and
+`$GITHUB_ENV` (mirrored as `STANDALONE_VCLUSTER_VERSION`,
+`STANDALONE_VCLUSTER_UPGRADE_VERSION`, `PLATFORM_BASE_VERSION`,
+`PLATFORM_RC_VERSION`, and `DEFAULT_VCLUSTER_CHART_VERSION`). The env
+mirror lets consumer steps (Summarize, Run pre-release …) keep reading
+them as env vars exactly as in the pre-extraction inlined workflow.
-The OIDC step exports `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and
-`AWS_SESSION_TOKEN` to the environment via
-`aws-actions/configure-aws-credentials`. These propagate to subsequent
-steps in the calling job through the standard action mechanism, so the
-consumer does not need to wire them explicitly.
+`aws-actions/configure-aws-credentials` exports
+`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`
+to `$GITHUB_ENV` by default. Consumer `env:` blocks referencing
+`env.AWS_*` (e.g. the `run-ginkgo` step) resolve as expected.
## Permissions
@@ -97,7 +108,7 @@ jobs:
steps:
- name: Pre-release setup
id: setup
- uses: loft-sh/github-actions/.github/actions/prerelease-setup@prerelease-setup/v1
+ uses: loft-sh/github-actions/.github/actions/prerelease-setup@prerelease-setup/v1.1
with:
role-session-name: prerelease-vcluster-${{ github.run_id }}
github-token: ${{ github.token }}
@@ -115,16 +126,16 @@ jobs:
procs: "1"
additional-ginkgo-flags: "-v"
env:
- STANDALONE_VCLUSTER_VERSION: ${{ steps.setup.outputs.standalone-vcluster-version }}
- DEFAULT_VCLUSTER_CHART_VERSION: ${{ steps.setup.outputs.standalone-vcluster-version }}
- STANDALONE_VCLUSTER_UPGRADE_VERSION: ${{ steps.setup.outputs.standalone-vcluster-upgrade-version }}
- PLATFORM_BASE_VERSION: ${{ steps.setup.outputs.platform-base-version }}
- PLATFORM_RC_VERSION: ${{ steps.setup.outputs.platform-rc-version }}
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }}
```
+The version env vars (`STANDALONE_VCLUSTER_VERSION`,
+`DEFAULT_VCLUSTER_CHART_VERSION`, etc.) flow into `run-ginkgo`
+automatically via the `$GITHUB_ENV` mirror — the consumer does not need
+to re-pass them.
+
The AI Cloud job is identical apart from a different `role-session-name`,
the addition of `VCI_K8S_VERSION` / `VCI_K8S_UPGRADE_VERSION` (kept at
the workflow `env:` block in the consumer, not passed through this
diff --git a/.github/actions/prerelease-setup/action.yml b/.github/actions/prerelease-setup/action.yml
index e5a5fcc..1044973 100644
--- a/.github/actions/prerelease-setup/action.yml
+++ b/.github/actions/prerelease-setup/action.yml
@@ -1,5 +1,5 @@
name: 'Pre-Release Setup'
-description: 'Shared setup for the loft-enterprise pre-release vCluster + AI Cloud workflow jobs: free disk, checkout, install Go/kubectl/helm/vCluster CLI, AWS Login, and resolve+validate the four version inputs (standalone vCluster base+upgrade, platform base+RC) including "latest" fallback resolvers.'
+description: 'Shared setup for the loft-enterprise pre-release vCluster + AI Cloud workflow jobs: free disk, checkout, install Go/kubectl/helm/vCluster CLI, AWS Login, and resolve+validate the four version inputs (standalone vCluster base+upgrade, platform base+RC) including "latest release" / "latest pre-release" fallbacks. Resolved versions are also verified against the matching release assets so a missing artifact fails fast before downstream provisioning.'
inputs:
role-session-name:
@@ -13,10 +13,11 @@ inputs:
required: false
default: ''
standalone-vcluster-upgrade-version:
- description: 'vCluster version to upgrade standalone to (e.g. 0.35.0-alpha.7). Must differ from the resolved base version.'
- required: true
+ description: 'vCluster version to upgrade standalone to (e.g. 0.35.0-alpha.7). Empty resolves to the latest vCluster pre-release. Must differ from the resolved base version.'
+ required: false
+ default: ''
platform-base-version:
- description: 'Platform version for the initial install (e.g. 4.9.0). Empty leaves the output empty; the consumer wires its own default into the test step.'
+ description: 'Platform version for the initial install (e.g. 4.9.0). Empty resolves to the latest stable release of loft-sh/loft-enterprise.'
required: false
default: ''
platform-rc-version:
@@ -29,10 +30,10 @@ outputs:
description: 'Resolved standalone vCluster version (no leading v).'
value: ${{ steps.resolve.outputs.standalone-vcluster-version }}
standalone-vcluster-upgrade-version:
- description: 'Validated standalone vCluster upgrade version (no leading v).'
+ description: 'Resolved standalone vCluster upgrade version (no leading v).'
value: ${{ steps.resolve.outputs.standalone-vcluster-upgrade-version }}
platform-base-version:
- description: 'Validated platform base version (no leading v). Empty when the input was empty.'
+ description: 'Resolved platform base version (no leading v).'
value: ${{ steps.resolve.outputs.platform-base-version }}
platform-rc-version:
description: 'Resolved platform RC version (no leading v).'
@@ -99,8 +100,24 @@ runs:
echo "Resolved vCluster version: $VERSION"
UP="${STANDALONE_VCLUSTER_UPGRADE_VERSION_INPUT#v}"
+ if [ -z "$UP" ]; then
+ # Empty = latest vCluster pre-release (alpha/rc). Mirrors the platform RC resolver below.
+ UP=$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/repos/loft-sh/vcluster/releases \
+ | jq -r '[.[] | select(.prerelease == true and .draft == false)][0].tag_name')
+ [ -n "$UP" ] && [ "$UP" != "null" ] || { echo "no vCluster pre-release found in loft-sh/vcluster"; exit 1; }
+ UP="${UP#v}"
+ echo "Resolved latest vCluster pre-release: $UP"
+ fi
[[ "$UP" =~ $VERSION_RE ]] || { echo "invalid standalone-vcluster-upgrade-version: $UP"; exit 1; }
[ "$UP" != "$VERSION" ] || { echo "standalone-vcluster-upgrade-version must differ from base ($VERSION)"; exit 1; }
+ # Reject an older-branch pre-release (e.g. base=0.34.1, latest pre-release=0.33.5-rc.1):
+ # `sort -V` puts the higher semver last, so the upgrade target must equal that tail.
+ # `sort -V` ranks a pre-release AFTER its release (4.9.0-alpha.1 > 4.9.0), the opposite
+ # of semver. Map the semver '-' separator to '~', which sort -V treats as lower than
+ # everything, so 4.9.0~alpha.1 < 4.9.0 as semver requires.
+ VS="${VERSION/-/\~}"; US="${UP/-/\~}"
+ [ "$(printf '%s\n%s\n' "$VS" "$US" | sort -V | tail -n1)" = "$US" ] \
+ || { echo "standalone-vcluster-upgrade-version ($UP) is not newer than base ($VERSION)"; exit 1; }
RC="${PLATFORM_RC_VERSION_INPUT#v}"
if [ -z "$RC" ]; then
@@ -116,10 +133,21 @@ runs:
[[ "$RC" =~ $VERSION_RE ]] || { echo "invalid platform-rc-version: $RC"; exit 1; }
BASE="${PLATFORM_BASE_VERSION_INPUT#v}"
- if [ -n "$BASE" ]; then
- [[ "$BASE" =~ $VERSION_RE ]] || { echo "invalid platform-base-version: $BASE"; exit 1; }
- [ "$BASE" != "$RC" ] || { echo "platform-base-version must differ from platform-rc-version"; exit 1; }
+ if [ -z "$BASE" ]; then
+ # Empty = latest stable platform release. /releases/latest excludes pre-releases,
+ # so this pins the same version `vcluster platform start` would otherwise pick.
+ BASE=$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/repos/loft-sh/loft-enterprise/releases/latest | jq -r .tag_name)
+ [ -n "$BASE" ] && [ "$BASE" != "null" ] || { echo "no platform release found in loft-sh/loft-enterprise"; exit 1; }
+ BASE="${BASE#v}"
+ echo "Resolved latest platform release: $BASE"
fi
+ [[ "$BASE" =~ $VERSION_RE ]] || { echo "invalid platform-base-version: $BASE"; exit 1; }
+ [ "$BASE" != "$RC" ] || { echo "platform-base-version must differ from platform-rc-version"; exit 1; }
+ # Same older-branch-pre-release guard as for vCluster: RC must be strictly newer than BASE.
+ # See the '~' note above: map the semver '-' to '~' so the pre-release sorts before its release.
+ BS="${BASE/-/\~}"; RS="${RC/-/\~}"
+ [ "$(printf '%s\n%s\n' "$BS" "$RS" | sort -V | tail -n1)" = "$RS" ] \
+ || { echo "platform-rc-version ($RC) is not newer than platform-base-version ($BASE)"; exit 1; }
{
echo "standalone-vcluster-version=$VERSION"
@@ -127,6 +155,32 @@ runs:
echo "platform-rc-version=$RC"
echo "platform-base-version=$BASE"
} >> "$GITHUB_OUTPUT"
+ # Mirror resolved versions to $GITHUB_ENV so consumer steps (Summarize,
+ # Run pre-release …) can keep reading them as env vars exactly as in the
+ # pre-extraction inlined workflow. DEFAULT_VCLUSTER_CHART_VERSION is the
+ # name the helm-chart-install code path expects; preserve it.
+ {
+ echo "STANDALONE_VCLUSTER_VERSION=$VERSION"
+ echo "STANDALONE_VCLUSTER_UPGRADE_VERSION=$UP"
+ echo "PLATFORM_BASE_VERSION=$BASE"
+ echo "PLATFORM_RC_VERSION=$RC"
+ echo "DEFAULT_VCLUSTER_CHART_VERSION=$VERSION"
+ } >> "$GITHUB_ENV"
+
+ - name: Verify release assets
+ shell: bash
+ env:
+ STANDALONE_VCLUSTER_VERSION: ${{ steps.resolve.outputs.standalone-vcluster-version }}
+ STANDALONE_VCLUSTER_UPGRADE_VERSION: ${{ steps.resolve.outputs.standalone-vcluster-upgrade-version }}
+ run: |
+ set -euo pipefail
+ # install-standalone.sh comes from a separate vcluster-pro workflow, so a vCluster
+ # pre-release can lack it; fail before downstream provisioning (e.g. EC2) is attempted.
+ check_asset() { curl -sfIL -o /dev/null "$1" || { echo "::error::missing release asset: $1"; exit 1; }; }
+ rel="https://github.com/loft-sh/vcluster/releases/download"
+ check_asset "${rel}/v${STANDALONE_VCLUSTER_VERSION}/install-standalone.sh"
+ check_asset "${rel}/v${STANDALONE_VCLUSTER_UPGRADE_VERSION}/install-standalone.sh"
+ check_asset "${rel}/v${STANDALONE_VCLUSTER_UPGRADE_VERSION}/vcluster-linux-amd64"
- name: Setup vCluster CLI (matches base standalone version)
shell: bash