Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions .github/actions/prerelease-setup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Pre-Release Setup

Shared setup for the `loft-sh/loft-enterprise` pre-release workflow
(`.github/workflows/prerelease-checks.yaml`). Replaces ~100 lines of
duplicated setup steps that lived inline in both the `prerelease-vcluster`
and `prerelease-aicloud` jobs.

The action performs, in order:

1. Free disk space (`jlumbroso/free-disk-space@v1.3.1`).
2. Checkout the calling repo (`actions/checkout@v6`).
3. Install Go (`actions/setup-go@v6`, `go-version-file: go.mod`, cache on).
4. Install `kubectl` (`azure/setup-kubectl@v5`).
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
standalone vCluster version.
9. 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
(`run-ginkgo`) remain in the calling workflow.

## Inputs

<!-- AUTO-DOC-INPUT:START - Do not remove or modify this section -->

| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
|-------------------------------------|--------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| github-token | string | true | | GitHub token with contents:read on loft-sh/loft-enterprise. <br>Required because the platform release resolvers <br>call the GitHub API for a <br>private repo; unauthenticated calls return 404. <br>Pass ${{ github.token }} from a <br>job whose permissions grant contents:read. |
| platform-base-version | string | false | | Platform version for the initial install <br>(e.g. 4.9.0). Empty leaves the output empty; <br>the consumer wires its own default <br>into the test step. |
| platform-rc-version | string | false | | Platform RC version for upgrade (e.g. 4.10.0-alpha.6). <br>Empty resolves to the latest pre-release <br>of loft-sh/loft-enterprise. |
| role-session-name | string | true | | AWS STS role-session-name. Each consumer job <br>passes a distinct value (e.g. prerelease-vcluster-<run-id>, prerelease-aicloud-<run-id>). |
| standalone-vcluster-upgrade-version | string | true | | vCluster version to upgrade standalone to <br>(e.g. 0.35.0-alpha.7). Must differ from the resolved <br>base version. |
| standalone-vcluster-version | string | false | | vCluster version to install for standalone <br>(e.g. 0.34.0). Empty resolves to the latest <br>GitHub release of loft-sh/vcluster. |

<!-- AUTO-DOC-INPUT:END -->

Inputs accept versions with or without a leading `v`; the action strips
the `v` before validating against the semver regex
`^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$`.

## Outputs

<!-- AUTO-DOC-OUTPUT:START - Do not remove or modify this section -->

| OUTPUT | TYPE | DESCRIPTION |
|-------------------------------------|--------|--------------------------------------------------------------------------------------|
| platform-base-version | string | Validated platform base version (no leading v). Empty <br>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). |

<!-- AUTO-DOC-OUTPUT:END -->

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.

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.

## Permissions

The calling job must declare:

```yaml
permissions:
contents: read
id-token: write
```

`id-token: write` is required for the OIDC `assume-role` exchange.

## Usage

```yaml
jobs:
prerelease-vcluster:
runs-on: ubuntu-latest
timeout-minutes: 90
permissions:
contents: read
id-token: write
env:
STANDALONE_VCLUSTER_UPGRADE_VERSION: ${{ inputs.standalone_vcluster_upgrade_version || github.event.client_payload.standalone_vcluster_upgrade_version }}
PLATFORM_BASE_VERSION: ${{ inputs.platform_base_version || github.event.client_payload.platform_base_version }}
PLATFORM_RC_VERSION: ${{ inputs.platform_rc_version || github.event.client_payload.platform_rc_version }}
steps:
- name: Pre-release setup
id: setup
uses: loft-sh/github-actions/.github/actions/prerelease-setup@prerelease-setup/v1
with:
role-session-name: prerelease-vcluster-${{ github.run_id }}
github-token: ${{ github.token }}
standalone-vcluster-version: ${{ inputs.standalone_vcluster_version || github.event.client_payload.standalone_vcluster_version }}
standalone-vcluster-upgrade-version: ${{ env.STANDALONE_VCLUSTER_UPGRADE_VERSION }}
platform-base-version: ${{ env.PLATFORM_BASE_VERSION }}
platform-rc-version: ${{ env.PLATFORM_RC_VERSION }}

- name: Run pre-release vCluster checks
uses: loft-sh/github-actions/.github/actions/run-ginkgo@run-ginkgo/v1
with:
test-dir: e2e/prerelease/vcluster
ginkgo-label: prerelease-upgrade
timeout: 80m
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 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
action), and the surrounding `aws-test-infra` provision/cleanup steps
that are specific to that job.

## Notes

- The two `vci-k8s-*` inputs called out in the original ticket scope are
intentionally not part of this action. They are not produced or
validated by any of the setup steps, and they are already available to
the consumer at the workflow `env:` level. Adding them as
pass-through-only inputs would be dead code.
159 changes: 159 additions & 0 deletions .github/actions/prerelease-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
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.'

inputs:
role-session-name:
description: 'AWS STS role-session-name. Each consumer job passes a distinct value (e.g. prerelease-vcluster-<run-id>, prerelease-aicloud-<run-id>).'
required: true
github-token:
description: '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.'
required: true
standalone-vcluster-version:
description: 'vCluster version to install for standalone (e.g. 0.34.0). Empty resolves to the latest GitHub release of loft-sh/vcluster.'
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
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.'
required: false
default: ''
platform-rc-version:
description: 'Platform RC version for upgrade (e.g. 4.10.0-alpha.6). Empty resolves to the latest pre-release of loft-sh/loft-enterprise.'
required: false
default: ''

outputs:
standalone-vcluster-version:
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).'
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.'
value: ${{ steps.resolve.outputs.platform-base-version }}
platform-rc-version:
description: 'Resolved platform RC version (no leading v).'
value: ${{ steps.resolve.outputs.platform-rc-version }}

runs:
using: 'composite'
steps:
- name: Free disk space
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
Comment thread
sowmyav27 marked this conversation as resolved.
with:
tool-cache: false

- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# The test code only reads from the working tree (go build, ginkgo
# discovery). No subsequent push/fetch needs the embedded token, so
# we drop it from the .git/config to satisfy zizmor[artipacked].
persist-credentials: false

- name: Setup Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: go.mod
cache: true

- name: Setup kubectl
uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d # v5.1.0

- name: Setup helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0

- name: AWS Login
uses: aws-actions/configure-aws-credentials@99214aa6889fcddfa57764031d71add364327e59 # v6.1.3
with:
role-to-assume: arn:aws:iam::084374023943:role/e2e-test-executor
role-session-name: ${{ inputs.role-session-name }}
aws-region: us-west-2
role-duration-seconds: 6300

- name: Resolve and validate versions
id: resolve
shell: bash
env:
STANDALONE_VCLUSTER_VERSION_INPUT: ${{ inputs.standalone-vcluster-version }}
STANDALONE_VCLUSTER_UPGRADE_VERSION_INPUT: ${{ inputs.standalone-vcluster-upgrade-version }}
PLATFORM_BASE_VERSION_INPUT: ${{ inputs.platform-base-version }}
PLATFORM_RC_VERSION_INPUT: ${{ inputs.platform-rc-version }}
GH_TOKEN: ${{ inputs.github-token }}
run: |
Comment thread
sowmyav27 marked this conversation as resolved.
set -euo pipefail
# Accept inputs with or without a leading `v`; normalize to no-v before exporting.
VERSION_RE='^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'

VERSION="$STANDALONE_VCLUSTER_VERSION_INPUT"
if [ -z "$VERSION" ]; then
# vcluster is public but unauthenticated calls share the runner IP's 60/hr rate limit.
# Pass the token to bump the budget to 1000/hr per token and avoid intermittent 403s.
VERSION=$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/repos/loft-sh/vcluster/releases/latest | jq -r .tag_name)
fi
VERSION="${VERSION#v}"
[[ "$VERSION" =~ $VERSION_RE ]] || { echo "invalid standalone-vcluster-version: $VERSION"; exit 1; }
echo "Resolved vCluster version: $VERSION"

UP="${STANDALONE_VCLUSTER_UPGRADE_VERSION_INPUT#v}"
[[ "$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; }

RC="${PLATFORM_RC_VERSION_INPUT#v}"
if [ -z "$RC" ]; then
# GitHub's /releases/latest excludes pre-releases, so list /releases and filter on `prerelease == true`.
# The list is newest-first by created_at, so `[0]` after filter = latest pre-release.
# loft-enterprise is private — unauthenticated requests return 404, so the token is required.
RC=$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/repos/loft-sh/loft-enterprise/releases \
| jq -r '[.[] | select(.prerelease == true and .draft == false)][0].tag_name')
[ -n "$RC" ] && [ "$RC" != "null" ] || { echo "no platform pre-release found in loft-sh/loft-enterprise"; exit 1; }
RC="${RC#v}"
echo "Resolved latest platform pre-release: $RC"
fi
[[ "$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; }
fi

{
echo "standalone-vcluster-version=$VERSION"
echo "standalone-vcluster-upgrade-version=$UP"
echo "platform-rc-version=$RC"
echo "platform-base-version=$BASE"
} >> "$GITHUB_OUTPUT"

- name: Setup vCluster CLI (matches base standalone version)
shell: bash
env:
STANDALONE_VCLUSTER_VERSION: ${{ steps.resolve.outputs.standalone-vcluster-version }}
run: |
set -euo pipefail
# Initial CLI matches the base standalone vCluster — used by the
# initial `vcluster platform start` in BeforeSuite. The test swaps
# this binary to the upgrade-target CLI before the platform upgrade
# spec runs.
URL="https://github.com/loft-sh/vcluster/releases/download/v${STANDALONE_VCLUSTER_VERSION}/vcluster-linux-amd64"
sudo curl -fL "${URL}" -o /usr/local/bin/vcluster
sudo chmod +x /usr/local/bin/vcluster
vcluster --version

- name: Verify required CLIs
shell: bash
run: |
set -e
echo "kubectl: $(command -v kubectl)"
kubectl version --client
echo "helm: $(command -v helm)"
helm version
echo "vcluster: $(command -v vcluster)"
vcluster --version

branding:
icon: 'package'
color: 'orange'