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