-
Notifications
You must be signed in to change notification settings - Fork 127
CI: automate dynamic e2e test for kapp-controller against latest & minimum supported kubernetes releases #1832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
himsngh
wants to merge
1
commit into
carvel-dev:develop
Choose a base branch
from
himsngh:nightly-build-automation
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| name: Nightly Build Kind Images | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '30 20 * * *' | ||
| workflow_dispatch: | ||
|
Comment on lines
+3
to
+6
|
||
|
|
||
| env: | ||
| REGISTRY: ghcr.io | ||
|
|
||
| jobs: | ||
| resolve-versions: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
| outputs: | ||
| matrix: ${{ steps.set-matrix.outputs.matrix }} | ||
| timestamp: ${{ steps.get-date.outputs.timestamp }} | ||
| steps: | ||
| - name: Get Date Timestamp | ||
| id: get-date | ||
| run: echo "timestamp=$(date +'%Y%m%d')" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Resolve Kubernetes Versions | ||
| id: set-matrix | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| echo "Fetching upstream Kubernetes branches..." | ||
| BRANCHES=$(git ls-remote --heads https://github.com/kubernetes/kubernetes.git \ | ||
| | awk '{print $2}' | grep -Eo 'release-1\.[0-9]+$' | sort -V) | ||
|
|
||
| if [[ -z "$BRANCHES" ]]; then | ||
| echo "::error::Failed to fetch Kubernetes branches." | ||
| exit 1 | ||
| fi | ||
|
|
||
| LATEST_BRANCH=$(echo "$BRANCHES" | tail -n 1) | ||
| MIN_BRANCH=$(echo "$BRANCHES" | tail -n 4 | head -n 1) | ||
|
|
||
| echo "Resolved -> Latest: $LATEST_BRANCH | Min (N-3): $MIN_BRANCH" | ||
|
|
||
| MATRIX_JSON=$(jq -nc \ | ||
| --arg latest "$LATEST_BRANCH" \ | ||
| --arg min "$MIN_BRANCH" \ | ||
| '{"k8s_branch": [$latest, $min]}') | ||
|
himsngh marked this conversation as resolved.
|
||
|
|
||
| echo "matrix=$MATRIX_JSON" >> "$GITHUB_OUTPUT" | ||
|
|
||
| build-and-push: | ||
| needs: resolve-versions | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 90 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJson(needs.resolve-versions.outputs.matrix) }} | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| steps: | ||
| - name: Free Disk Space | ||
| run: | | ||
| docker system prune -af --volumes || true | ||
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android || true | ||
|
|
||
| - name: Setup Environment Variables | ||
| run: | | ||
| set -euo pipefail | ||
| OWNER_LC=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') | ||
| echo "IMAGE_BASE=${{ env.REGISTRY }}/${OWNER_LC}/kindest-node" >> "$GITHUB_ENV" | ||
|
|
||
| BRANCH_SHA=$(git ls-remote https://github.com/kubernetes/kubernetes.git refs/heads/${{ matrix.k8s_branch }} | awk '{print $1}' | cut -c1-7) | ||
| echo "BRANCH_SHA=$BRANCH_SHA" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Login to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Check GHCR for Cached Build | ||
| id: check-cache | ||
| run: | | ||
| set -euo pipefail | ||
| TIMESTAMP="${{ needs.resolve-versions.outputs.timestamp }}" | ||
|
|
||
| CACHE_IMAGE="${{ env.IMAGE_BASE }}:${{ matrix.k8s_branch }}-${{ env.BRANCH_SHA }}" | ||
| DAILY_IMAGE="${{ env.IMAGE_BASE }}:${{ matrix.k8s_branch }}-${TIMESTAMP}" | ||
|
|
||
| echo "CACHE_IMAGE=$CACHE_IMAGE" >> "$GITHUB_ENV" | ||
| echo "DAILY_IMAGE=$DAILY_IMAGE" >> "$GITHUB_ENV" | ||
|
|
||
| export DOCKER_CLI_EXPERIMENTAL=enabled | ||
| if docker manifest inspect "$CACHE_IMAGE" > /dev/null 2>&1; then | ||
| echo "Cache Hit! Image already exists: $CACHE_IMAGE" | ||
| echo "skip_build=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "Cache Miss. Proceeding with source build." | ||
| echo "skip_build=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - name: Checkout Kubernetes | ||
| if: steps.check-cache.outputs.skip_build == 'false' | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| repository: kubernetes/kubernetes | ||
| ref: ${{ matrix.k8s_branch }} | ||
| path: kubernetes | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Checkout Kind | ||
| if: steps.check-cache.outputs.skip_build == 'false' | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| repository: kubernetes-sigs/kind | ||
| path: kind | ||
|
|
||
| - name: Install Go | ||
| if: steps.check-cache.outputs.skip_build == 'false' | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: '1.24' | ||
|
|
||
| - name: Build and Push (Cache Miss) | ||
| if: steps.check-cache.outputs.skip_build == 'false' | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How are we caching it? Is the CLN tag or version itself is the tag here?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, can we include main/master here as well? |
||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| set -euo pipefail | ||
| /usr/local/bin/kind build node-image --type=source "$PWD/kubernetes" --image "${{ env.CACHE_IMAGE }}" | ||
|
|
||
|
Comment on lines
+124
to
+131
|
||
| echo "Re-authenticating to GHCR to prevent session timeout..." | ||
| echo "$GH_TOKEN" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | ||
|
|
||
| docker push "${{ env.CACHE_IMAGE }}" | ||
|
|
||
| docker tag "${{ env.CACHE_IMAGE }}" "${{ env.DAILY_IMAGE }}" | ||
| docker push "${{ env.DAILY_IMAGE }}" | ||
|
|
||
| - name: Retag Existing Build (Cache Hit) | ||
| if: steps.check-cache.outputs.skip_build == 'true' | ||
| run: | | ||
| set -euo pipefail | ||
| docker pull "${{ env.CACHE_IMAGE }}" | ||
| docker tag "${{ env.CACHE_IMAGE }}" "${{ env.DAILY_IMAGE }}" | ||
| docker push "${{ env.DAILY_IMAGE }}" | ||
|
|
||
| trigger-tests: | ||
| needs: [resolve-versions, build-and-push] | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 10 | ||
| if: success() | ||
| permissions: | ||
| actions: write | ||
| contents: read | ||
| steps: | ||
| - name: Checkout Code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Trigger Downstream E2E Tests | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| TIMESTAMP: ${{ needs.resolve-versions.outputs.timestamp }} | ||
| WORKFLOW_BRANCH: ${{ github.ref_name }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| ALL_TAGS=$(git ls-remote --tags --refs https://github.com/carvel-dev/kapp-controller.git \ | ||
| | awk -F/ '{print $3}' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V) | ||
|
|
||
| MINORS=$(echo "$ALL_TAGS" | cut -d. -f1,2 | uniq | tail -n 2) | ||
|
|
||
| DYNAMIC_TAGS="" | ||
| for minor in $MINORS; do | ||
| LATEST_PATCH=$(echo "$ALL_TAGS" | grep "^${minor}\." | tail -n 1) | ||
| DYNAMIC_TAGS="$DYNAMIC_TAGS $LATEST_PATCH" | ||
| done | ||
|
|
||
| for tag in $DYNAMIC_TAGS; do | ||
| echo "Dispatching E2E test for kapp-controller: $tag" | ||
|
|
||
| gh workflow run nightly-e2e.yml \ | ||
| --ref "$WORKFLOW_BRANCH" \ | ||
| -f image_timestamp="$TIMESTAMP" \ | ||
| -f kapp_ctrl_ref="$tag" \ | ||
| -f registry_user="${{ github.repository_owner }}" | ||
|
Comment on lines
+182
to
+186
|
||
|
|
||
| sleep 3 | ||
| done | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| name: Nightly E2E Tests | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| image_timestamp: | ||
| description: 'Timestamp of the Kind image to use (YYYYMMDD)' | ||
| required: true | ||
| kapp_ctrl_ref: | ||
| description: 'Git ref to test' | ||
| required: true | ||
| default: 'develop' | ||
| registry_user: | ||
| description: 'User to pull image from' | ||
| required: false | ||
| default: 'carvel-dev' | ||
|
|
||
| jobs: | ||
| resolve-versions: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| outputs: | ||
| matrix: ${{ steps.set-matrix.outputs.matrix }} | ||
| steps: | ||
| - name: Resolve Kubernetes Versions | ||
| id: set-matrix | ||
| run: | | ||
| set -euo pipefail | ||
| # Recalculating the matrix locally to avoid passing complex JSON arrays through GH API string inputs. | ||
| BRANCHES=$(git ls-remote --heads https://github.com/kubernetes/kubernetes.git \ | ||
| | awk '{print $2}' | grep -Eo 'release-1\.[0-9]+$' | sort -V) | ||
|
|
||
| LATEST_BRANCH=$(echo "$BRANCHES" | tail -n 1) | ||
| MIN_BRANCH=$(echo "$BRANCHES" | tail -n 4 | head -n 1) | ||
|
|
||
|
Comment on lines
+30
to
+35
|
||
| MATRIX_JSON=$(jq -nc \ | ||
| --arg latest "$LATEST_BRANCH" \ | ||
| --arg min "$MIN_BRANCH" \ | ||
| '{"k8s_version": [$latest, $min]}') | ||
|
|
||
| echo "matrix=$MATRIX_JSON" >> "$GITHUB_OUTPUT" | ||
|
|
||
| e2e-tests: | ||
| needs: resolve-versions | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
|
Comment on lines
+43
to
+46
|
||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJson(needs.resolve-versions.outputs.matrix) }} | ||
| steps: | ||
| - name: Setup Environment Variables | ||
| run: | | ||
| set -euo pipefail | ||
| RAW_USER="${{ inputs.registry_user || github.repository_owner }}" | ||
| USER_LC=$(echo "$RAW_USER" | tr '[:upper:]' '[:lower:]') | ||
|
|
||
| TIMESTAMP="${{ inputs.image_timestamp }}" | ||
| TAG="${{ matrix.k8s_version }}-${TIMESTAMP}" | ||
| FULL_IMAGE="ghcr.io/${USER_LC}/kindest-node:$TAG" | ||
|
|
||
| echo "FULL_IMAGE=$FULL_IMAGE" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Checkout Kapp-Controller | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| # Clones the fork/branch first. Target refs/tags are fetched manually below. | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Fetch Upstream Tags | ||
| run: | | ||
| set -euo pipefail | ||
| echo "Adding upstream remote..." | ||
| git remote add upstream https://github.com/carvel-dev/kapp-controller.git || true | ||
|
|
||
| echo "Fetching upstream tags..." | ||
| git fetch upstream --tags | ||
|
|
||
| TARGET_REF="${{ inputs.kapp_ctrl_ref || 'develop' }}" | ||
| echo "Checking out target ref: $TARGET_REF" | ||
|
|
||
| # Safely checks out upstream tags or falls back to the fork's local branch | ||
| git checkout "$TARGET_REF" | ||
|
|
||
| - name: Setup Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version-file: 'go.mod' | ||
|
|
||
| - name: Login to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Verify Image Existence (Pre-flight Check) | ||
| run: | | ||
| set -euo pipefail | ||
| echo "Verifying image exists in GHCR: ${{ env.FULL_IMAGE }}" | ||
| export DOCKER_CLI_EXPERIMENTAL=enabled | ||
| if ! docker manifest inspect "${{ env.FULL_IMAGE }}" > /dev/null 2>&1; then | ||
| echo "::error::Image ${{ env.FULL_IMAGE }} does not exist. Halting cluster creation." | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Create Kind Cluster | ||
| run: | | ||
| set -euo pipefail | ||
| echo "Bootstrapping cluster using verified image: ${{ env.FULL_IMAGE }}" | ||
| /usr/local/bin/kind create cluster --image "${{ env.FULL_IMAGE }}" --name kinder --wait 1m | ||
|
|
||
| /usr/local/bin/kind get kubeconfig --name kinder > kubeconfig.yaml | ||
| echo "KUBECONFIG=$PWD/kubeconfig.yaml" >> "$GITHUB_ENV" | ||
|
Comment on lines
+106
to
+113
|
||
|
|
||
| - name: Install Dependencies | ||
| run: ./hack/install-deps.sh | ||
|
|
||
| - name: Build, Load and Deploy Kapp-Controller | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| VERSION="${{ inputs.kapp_ctrl_ref || 'develop' }}" | ||
| VERSION=${VERSION#v} | ||
| if [[ "$VERSION" == "develop" || "$VERSION" == "HEAD" ]]; then | ||
| VERSION="0.100.0+develop" | ||
| fi | ||
|
|
||
| echo "Injecting Build Version: $VERSION" | ||
| sed -i "s|function get_kappctrl_ver() {|function get_kappctrl_ver() { echo \"$VERSION\"; return; |g" hack/version-util.sh | ||
|
|
||
|
Comment on lines
+128
to
+130
|
||
| echo "Compiling manifests..." | ||
| ytt -f config/config -f config/values-schema.yml -f config-dev -v dev.version="$VERSION" | kbld -f- > kbld.out 2> kbldmeta.out | ||
|
|
||
| echo "Extracting image from kbld metadata..." | ||
| BUILT_IMAGE=$(awk '/final: kapp-controller ->/ {print $NF}' kbldmeta.out | tail -n 1) | ||
|
|
||
| if [[ -z "$BUILT_IMAGE" ]]; then | ||
| echo "::error::Failed to extract built image from kbld output." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Loading $BUILT_IMAGE into kind..." | ||
| /usr/local/bin/kind load docker-image "$BUILT_IMAGE" --name kinder | ||
|
|
||
| echo "Deploying to cluster..." | ||
| kapp deploy -a kc -f kbld.out -c -y | ||
|
|
||
| - name: Install Secretgen Controller | ||
| run: | | ||
| set -euo pipefail | ||
| export KAPPCTRL_E2E_SECRETGEN_CONTROLLER=true | ||
| source ./hack/secretgen-controller.sh | ||
| deploy_secretgen-controller | ||
|
|
||
| - name: Run E2E Tests | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p tmp | ||
| KAPPCTRL_E2E_NAMESPACE=kappctrl-test eval './hack/test-e2e.sh' | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can reduce the frequency here, release branches are not actively developed.
Or can we magically skip if TOT of release branch hasn't changed?