From 82ed679d160135727b7bba3b6cf922c3ea008482 Mon Sep 17 00:00:00 2001 From: Asen Lekov Date: Mon, 19 Oct 2026 20:03:06 +0300 Subject: [PATCH] ci: trim JDK matrix, add gha layer cache, image smoke test and NDK variant - matrix.json: JDK 17/21/25/27 (LTS + latest), Node 22/24 - build.yml: gha cache per platform, 45 min timeouts, wider shellcheck, docker compose config, image smoke test on the default amd64 leg - deploy.yml: gha cache per platform, timeouts, publish runner-ndk for the default pair - check-sdk-updates.yml: App token so PR CI runs, auto-merge, LTS-aware JDK retention, fix stable platforms (empty ) being treated as previews Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/build.yml | 61 ++++++++++++--- .github/workflows/check-sdk-updates.yml | 100 +++++++++++++++--------- .github/workflows/deploy.yml | 65 ++++++++++----- matrix.json | 4 - tests/image-smoke.sh | 59 ++++++++++++++ 5 files changed, 219 insertions(+), 70 deletions(-) create mode 100755 tests/image-smoke.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d7f0f64..765efdb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,20 +13,42 @@ jobs: scripts: name: Shell scripts runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v7 - name: shellcheck - run: shellcheck -x pruner.sh tests/*.sh + run: | + set -euo pipefail + # nullglob: a pattern that matches nothing (e.g. hosts/*.sh) must + # drop out instead of being passed to shellcheck as a literal. + shopt -s nullglob + files=(*.sh hosts/*.sh tests/*.sh) + if [ "${#files[@]}" -eq 0 ]; then + echo "::error::No shell scripts found to check" + exit 1 + fi + shellcheck -x "${files[@]}" + + - name: docker compose config + run: | + set -euo pipefail + cp .env.example .env + docker compose config -q - name: tests run: | set -euo pipefail - for t in tests/*.sh; do bash "$t"; done + for t in tests/*.sh; do + # image-smoke.sh needs a built image; it runs in the build job. + [ "$(basename "$t")" = image-smoke.sh ] && continue + bash "$t" + done matrix: name: Generate build matrix runs-on: ubuntu-latest + timeout-minutes: 5 outputs: matrix: ${{ steps.generate.outputs.matrix }} steps: @@ -37,26 +59,29 @@ jobs: run: | set -euo pipefail # PR builds deliberately cover less than deploy.yml: the full - # java x node x arch product is ~28 images, which is far more than a - # dependency bump needs. Instead we cover every JDK against the - # default Node, every Node against the default JDK, and add a single - # arm64 build of the default pair so arch-specific breakage (e.g. the - # TARGETARCH-derived JAVA_HOME) is still caught before merge. + # java x node x arch product is far more than a dependency bump + # needs. Instead we cover every JDK against the default Node, every + # Node against the default JDK, and add a single arm64 build of the + # default pair so arch-specific breakage (e.g. the TARGETARCH-derived + # JAVA_HOME) is still caught before merge. The amd64 default pair + # also gets the image smoke test (smoke: true). MATRIX=$(jq -c ' .default_jdk as $dj | .default_node as $dn | ( [ .java_versions[] | {java_version: ., node_version: $dn} ] + [ .node_versions[] | {java_version: $dj, node_version: .} ] | unique ) as $combos | { include: - ( [ $combos[] | . + {platform: "linux/amd64", arch: "amd64", runner: "ubuntu-latest"} ] + ( [ $combos[] | . + {platform: "linux/amd64", arch: "amd64", runner: "ubuntu-latest", + smoke: (.java_version == $dj and .node_version == $dn)} ] + [ {java_version: $dj, node_version: $dn, - platform: "linux/arm64", arch: "arm64", runner: "ubuntu-24.04-arm"} ] ) }' matrix.json) - echo "matrix=${MATRIX}" >> $GITHUB_OUTPUT + platform: "linux/arm64", arch: "arm64", runner: "ubuntu-24.04-arm", smoke: false} ] ) }' matrix.json) + echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT" build: name: Build ${{ matrix.arch }} JDK ${{ matrix.java_version }} Node ${{ matrix.node_version }} needs: matrix runs-on: ${{ matrix.runner }} + timeout-minutes: 45 strategy: fail-fast: false matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} @@ -77,17 +102,26 @@ jobs: exit 1 fi - echo "runner_tag=${RUNNER_TAG}" >> $GITHUB_OUTPUT + echo "runner_tag=${RUNNER_TAG}" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 + # Layer cache lives in the GitHub Actions cache, one scope per platform so + # the amd64 and arm64 legs never overwrite each other. PR builds read and + # write it too; branch scoping keeps a PR from polluting main's cache. + # `load` is only set on the smoke leg: the other legs have nothing to run. - name: Build (no push) uses: docker/build-push-action@v7 with: context: . + target: runner platforms: ${{ matrix.platform }} push: false + load: ${{ matrix.smoke }} + tags: github-runner:smoke + cache-from: type=gha,scope=${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=${{ matrix.arch }} build-args: | VERSION=${{ steps.versions.outputs.runner_tag }} JAVA_VERSION=${{ matrix.java_version }} @@ -95,11 +129,16 @@ jobs: RUNNER_IMAGE_TAG=pr-${{ github.event.pull_request.number }} RUNNER_IMAGE_REVISION=${{ github.event.pull_request.head.sha }} + - name: Smoke test image + if: matrix.smoke + run: bash tests/image-smoke.sh github-runner:smoke "${{ matrix.java_version }}" "${{ matrix.node_version }}" + gate: name: All builds passed needs: [scripts, matrix, build] if: always() runs-on: ubuntu-latest + timeout-minutes: 5 steps: - name: Check that all required jobs succeeded run: | diff --git a/.github/workflows/check-sdk-updates.yml b/.github/workflows/check-sdk-updates.yml index fd3826b..94ae751 100644 --- a/.github/workflows/check-sdk-updates.yml +++ b/.github/workflows/check-sdk-updates.yml @@ -5,25 +5,41 @@ on: - cron: '0 9 * * 1' # Weekly on Monday at 9 AM UTC workflow_dispatch: +# Writes (branch push, PR, auto-merge) go through the GitHub App token minted +# below, not GITHUB_TOKEN: PRs opened with GITHUB_TOKEN never trigger +# build.yml, so their required checks would never report. permissions: - contents: write - pull-requests: write + contents: read jobs: check-updates: name: Check for updates runs-on: ubuntu-latest + timeout-minutes: 15 steps: + - name: Create GitHub App token + id: app-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + permission-contents: write + permission-pull-requests: write + - uses: actions/checkout@v7 + with: + token: ${{ steps.app-token.outputs.token }} - name: Check for new JDK versions id: jdk run: | - # Get available Temurin releases >= 17 + # Get available Temurin GA releases >= 17 RESPONSE=$(curl -sf https://api.adoptium.net/v3/info/available_releases || echo "") if [ -z "$RESPONSE" ]; then echo "Failed to fetch Adoptium releases API" - echo "has_new=false" >> $GITHUB_OUTPUT + echo "has_new=false" >> "$GITHUB_OUTPUT" exit 0 fi @@ -41,12 +57,12 @@ jobs: fi done - echo "new_versions=${NEW_VERSIONS}" >> $GITHUB_OUTPUT + echo "new_versions=${NEW_VERSIONS}" >> "$GITHUB_OUTPUT" if [ -n "$NEW_VERSIONS" ]; then - echo "has_new=true" >> $GITHUB_OUTPUT + echo "has_new=true" >> "$GITHUB_OUTPUT" echo "Found new JDK versions: $NEW_VERSIONS" else - echo "has_new=false" >> $GITHUB_OUTPUT + echo "has_new=false" >> "$GITHUB_OUTPUT" echo "No new JDK versions found" fi @@ -61,7 +77,7 @@ jobs: # which falsely includes long-EOL majors (10, 12, 14, 16, 18). if ! SCHEDULE=$(curl -sf https://raw.githubusercontent.com/nodejs/Release/main/schedule.json); then echo "Failed to fetch Node release schedule" - echo "has_new=false" >> $GITHUB_OUTPUT + echo "has_new=false" >> "$GITHUB_OUTPUT" exit 0 fi @@ -88,12 +104,12 @@ jobs: fi done - echo "new_versions=${NEW_VERSIONS}" >> $GITHUB_OUTPUT + echo "new_versions=${NEW_VERSIONS}" >> "$GITHUB_OUTPUT" if [ -n "$NEW_VERSIONS" ]; then - echo "has_new=true" >> $GITHUB_OUTPUT + echo "has_new=true" >> "$GITHUB_OUTPUT" echo "Found new Node LTS versions: $NEW_VERSIONS" else - echo "has_new=false" >> $GITHUB_OUTPUT + echo "has_new=false" >> "$GITHUB_OUTPUT" echo "No new Node LTS versions found" fi @@ -107,11 +123,12 @@ jobs: # are listed too), which then break the unattended Docker build when # sdkmanager demands the separate Android SDK Preview license. The manifest # carries reliable preview markers, so we parse it with a real XML parser - # and skip any package that is obsolete, carries a element, or - # uses the android-sdk-preview-license. + # and skip any package that is obsolete, carries a non-empty + # (stable platforms have an empty one), or uses the + # android-sdk-preview-license. if ! wget -q "https://dl.google.com/android/repository/repository2-3.xml" -O /tmp/android-repo.xml; then echo "Failed to download SDK repository manifest" - echo "updated=false" >> $GITHUB_OUTPUT + echo "updated=false" >> "$GITHUB_OUTPUT" exit 0 fi if ! SDK_VERSIONS=$(python3 - /tmp/android-repo.xml <<'PY' @@ -126,7 +143,10 @@ jobs: if pkg.get('obsolete') == 'true': return True for e in pkg.iter(): - if local(e.tag) == 'codename': + # Stable platforms carry an *empty* + # (e.g. android-37.0/37.1/37.2); previews name the next + # release there (DEV, CinnamonBun, ...). + if local(e.tag) == 'codename' and (e.text or '').strip(): return True if local(e.tag) == 'uses-license' and e.get('ref') == 'android-sdk-preview-license': return True @@ -159,7 +179,7 @@ jobs: PY ); then echo "Failed to parse SDK repository manifest" - echo "updated=false" >> $GITHUB_OUTPUT + echo "updated=false" >> "$GITHUB_OUTPUT" exit 0 fi eval "$SDK_VERSIONS" @@ -169,12 +189,14 @@ jobs: CURRENT_BUILD_TOOLS=$(grep '^ARG BUILD_TOOLS=' Dockerfile | cut -d= -f2) CURRENT_NDK=$(grep '^ARG NDK_VERSION=' Dockerfile | cut -d= -f2) - echo "latest_platform=${LATEST_PLATFORM}" >> $GITHUB_OUTPUT - echo "latest_build_tools=${LATEST_BUILD_TOOLS}" >> $GITHUB_OUTPUT - echo "latest_ndk=${LATEST_NDK}" >> $GITHUB_OUTPUT - echo "current_platform=${CURRENT_PLATFORM}" >> $GITHUB_OUTPUT - echo "current_build_tools=${CURRENT_BUILD_TOOLS}" >> $GITHUB_OUTPUT - echo "current_ndk=${CURRENT_NDK}" >> $GITHUB_OUTPUT + { + echo "latest_platform=${LATEST_PLATFORM}" + echo "latest_build_tools=${LATEST_BUILD_TOOLS}" + echo "latest_ndk=${LATEST_NDK}" + echo "current_platform=${CURRENT_PLATFORM}" + echo "current_build_tools=${CURRENT_BUILD_TOOLS}" + echo "current_ndk=${CURRENT_NDK}" + } >> "$GITHUB_OUTPUT" # Check if updates are needed UPDATED=false @@ -191,7 +213,7 @@ jobs: UPDATED=true fi - echo "updated=${UPDATED}" >> $GITHUB_OUTPUT + echo "updated=${UPDATED}" >> "$GITHUB_OUTPUT" echo "SDK check results:" echo " Platform: ${CURRENT_PLATFORM} -> ${LATEST_PLATFORM}" echo " Build tools: ${CURRENT_BUILD_TOOLS} -> ${LATEST_BUILD_TOOLS}" @@ -199,13 +221,23 @@ jobs: - name: Apply JDK updates if: steps.jdk.outputs.has_new == 'true' + env: + NEW_VERSIONS: ${{ steps.jdk.outputs.new_versions }} run: | - for v in ${{ steps.jdk.outputs.new_versions }}; do - jq --arg v "$v" '.java_versions += [$v] | .java_versions = (.java_versions | sort_by(tonumber))' matrix.json > tmp.json && mv tmp.json matrix.json + for v in $NEW_VERSIONS; do + jq --arg v "$v" '.java_versions += [$v]' matrix.json > tmp.json && mv tmp.json matrix.json done - # Update default to highest version - jq '.default_jdk = (.java_versions | sort_by(tonumber) | last)' matrix.json > tmp.json && mv tmp.json matrix.json + # Retention policy: keep the LTS lines (17, 21, 25, then one every + # two years: 29, 33, ...) plus the newest GA release, and drop any + # other non-LTS version once it is no longer the newest. The default + # is always the newest. + jq ' + def lts: . >= 17 and ((. - 17) % 4 == 0); + ([.java_versions[] | tonumber] | unique) as $all + | ($all | max) as $newest + | .java_versions = [ $all[] | select(. == $newest or lts) | tostring ] + | .default_jdk = (.java_versions | last)' matrix.json > tmp.json && mv tmp.json matrix.json echo "Updated matrix.json:" cat matrix.json @@ -238,7 +270,7 @@ jobs: - name: Create pull request if: steps.jdk.outputs.has_new == 'true' || steps.sdk.outputs.updated == 'true' || steps.node.outputs.has_new == 'true' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | BRANCH="automated/sdk-jdk-updates" @@ -260,7 +292,7 @@ jobs: MSG="$MSG SDK" fi MSG="$MSG versions" - git commit -m "$MSG" + git commit -m "chore(deps): $MSG" git push -f origin "$BRANCH" # Build PR body @@ -301,15 +333,13 @@ jobs: EXISTING=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number' 2>/dev/null || true) if [ -z "$EXISTING" ]; then gh pr create \ - --title "Update SDK/JDK/Node versions" \ + --title "chore(deps): update SDK/JDK/Node versions" \ --body-file /tmp/pr-body.txt \ --head "$BRANCH" else echo "PR #${EXISTING} already exists, updated with force push" fi - # No auto-merge on purpose: this PR is opened with GITHUB_TOKEN, and GitHub - # does not trigger workflows for PRs created that way. build.yml never runs, - # so the "All builds passed" check never reports and an auto-merge request - # would hang forever. Merge manually (which runs the builds), or add a - # fine-grained PAT and restore upstream's auto-merge step. + # The PR is opened with the App token, so build.yml runs and the + # "All builds passed" check reports; auto-merge waits for it. + gh pr merge --auto --squash "$BRANCH" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 18ee23c..8fb08bf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -12,6 +12,7 @@ jobs: matrix: name: Generate build matrix runs-on: ubuntu-latest + timeout-minutes: 5 outputs: build_matrix: ${{ steps.generate.outputs.build_matrix }} merge_matrix: ${{ steps.generate.outputs.merge_matrix }} @@ -22,24 +23,35 @@ jobs: id: generate run: | set -euo pipefail + # Every JDK x Node pair is published as the `runner` target. The + # default pair is additionally published as `runner-ndk` (the same + # image plus the NDK); it is a separate "variant" so its digests, + # cache scope and tags never mix with the standard image. ALL=$(jq -c ' .default_jdk as $dj | .default_node as $dn | [ .java_versions[] as $j | .node_versions[] as $n | { java_version: $j, node_version: $n, is_default_jdk: ($j == $dj), - is_default_node: ($n == $dn) } ] as $combos + is_default_node: ($n == $dn), + variant: "std", target: "runner", ndk: false, tag_suffix: "" } ] as $std + | ( [ $std[] | select(.is_default_jdk and .is_default_node) + | . + {variant: "ndk", target: "runner-ndk", ndk: true, tag_suffix: "-ndk"} ] ) as $ndk + | ( $std + $ndk ) as $combos | { build: { include: [ $combos[] as $c | - ($c + {platform: "linux/amd64", arch: "amd64", runner: "ubuntu-latest"}), - ($c + {platform: "linux/arm64", arch: "arm64", runner: "ubuntu-24.04-arm"}) ] }, + ($c + {platform: "linux/amd64", arch: "amd64", runner: "ubuntu-latest", + cache_scope: (if $c.ndk then "ndk-amd64" else "amd64" end)}), + ($c + {platform: "linux/arm64", arch: "arm64", runner: "ubuntu-24.04-arm", + cache_scope: (if $c.ndk then "ndk-arm64" else "arm64" end)}) ] }, merge: { include: $combos } }' matrix.json) - echo "build_matrix=$(jq -c .build <<< "$ALL")" >> $GITHUB_OUTPUT - echo "merge_matrix=$(jq -c .merge <<< "$ALL")" >> $GITHUB_OUTPUT + echo "build_matrix=$(jq -c .build <<< "$ALL")" >> "$GITHUB_OUTPUT" + echo "merge_matrix=$(jq -c .merge <<< "$ALL")" >> "$GITHUB_OUTPUT" build: - name: Build ${{ matrix.platform }} JDK ${{ matrix.java_version }} Node ${{ matrix.node_version }} + name: Build ${{ matrix.platform }} JDK ${{ matrix.java_version }} Node ${{ matrix.node_version }}${{ matrix.tag_suffix }} needs: matrix runs-on: ${{ matrix.runner }} + timeout-minutes: 45 strategy: fail-fast: false matrix: ${{ fromJson(needs.matrix.outputs.build_matrix) }} @@ -59,9 +71,11 @@ jobs: exit 1 fi - echo "runner_tag=${RUNNER_TAG}" >> $GITHUB_OUTPUT - echo "runner_version=${RUNNER_VERSION}" >> $GITHUB_OUTPUT - echo "compile_sdk=${COMPILE_SDK}" >> $GITHUB_OUTPUT + { + echo "runner_tag=${RUNNER_TAG}" + echo "runner_version=${RUNNER_VERSION}" + echo "compile_sdk=${COMPILE_SDK}" + } >> "$GITHUB_OUTPUT" - name: Login to GitHub Container Registry uses: docker/login-action@v4 @@ -82,14 +96,21 @@ jobs: with: images: ghcr.io/${{ github.repository_owner }}/github-runner tags: | - type=raw,value=${{ steps.versions.outputs.runner_version }}-jdk${{ matrix.java_version }}-sdk${{ steps.versions.outputs.compile_sdk }}-node${{ matrix.node_version }} + type=raw,value=${{ steps.versions.outputs.runner_version }}-jdk${{ matrix.java_version }}-sdk${{ steps.versions.outputs.compile_sdk }}-node${{ matrix.node_version }}${{ matrix.tag_suffix }} - name: Build and push by digest id: build uses: docker/build-push-action@v7 with: context: . + target: ${{ matrix.target }} platforms: ${{ matrix.platform }} + # Layer cache in the GitHub Actions cache, one scope per platform + # (the NDK variant keeps its own scope and reads the standard one). + cache-from: | + type=gha,scope=${{ matrix.arch }} + type=gha,scope=${{ matrix.cache_scope }} + cache-to: type=gha,mode=max,scope=${{ matrix.cache_scope }} # Disable SLSA provenance: it wraps the image in a per-registry # attestation index which produces unknown/unknown manifest entries # and an extra attestation manifest per arch. Nothing in this @@ -114,15 +135,16 @@ jobs: - name: Upload digest uses: actions/upload-artifact@v7 with: - name: digests-jdk${{ matrix.java_version }}-node${{ matrix.node_version }}-${{ matrix.arch }} + name: digests-${{ matrix.variant }}-jdk${{ matrix.java_version }}-node${{ matrix.node_version }}-${{ matrix.arch }} path: ${{ runner.temp }}/digests/* if-no-files-found: error retention-days: 1 merge: - name: Merge JDK ${{ matrix.java_version }} Node ${{ matrix.node_version }} + name: Merge JDK ${{ matrix.java_version }} Node ${{ matrix.node_version }}${{ matrix.tag_suffix }} needs: [matrix, build] runs-on: ubuntu-latest + timeout-minutes: 15 strategy: fail-fast: false matrix: ${{ fromJson(needs.matrix.outputs.merge_matrix) }} @@ -142,13 +164,13 @@ jobs: exit 1 fi - echo "runner_version=${RUNNER_VERSION}" >> $GITHUB_OUTPUT - echo "compile_sdk=${COMPILE_SDK}" >> $GITHUB_OUTPUT + echo "runner_version=${RUNNER_VERSION}" >> "$GITHUB_OUTPUT" + echo "compile_sdk=${COMPILE_SDK}" >> "$GITHUB_OUTPUT" - name: Download digests uses: actions/download-artifact@v8 with: - pattern: digests-jdk${{ matrix.java_version }}-node${{ matrix.node_version }}-* + pattern: digests-${{ matrix.variant }}-jdk${{ matrix.java_version }}-node${{ matrix.node_version }}-* merge-multiple: true path: ${{ runner.temp }}/digests @@ -168,11 +190,12 @@ jobs: with: images: ghcr.io/${{ github.repository_owner }}/github-runner tags: | - type=raw,value=jdk${{ matrix.java_version }},enable=${{ matrix.is_default_node }} - type=raw,value=node${{ matrix.node_version }},enable=${{ matrix.is_default_jdk }} - type=raw,value=jdk${{ matrix.java_version }}-node${{ matrix.node_version }} - type=raw,value=${{ steps.versions.outputs.runner_version }}-jdk${{ matrix.java_version }}-sdk${{ steps.versions.outputs.compile_sdk }}-node${{ matrix.node_version }} - type=raw,value=latest,enable=${{ matrix.is_default_jdk && matrix.is_default_node }} + type=raw,value=jdk${{ matrix.java_version }},enable=${{ !matrix.ndk && matrix.is_default_node }} + type=raw,value=node${{ matrix.node_version }},enable=${{ !matrix.ndk && matrix.is_default_jdk }} + type=raw,value=jdk${{ matrix.java_version }}-node${{ matrix.node_version }},enable=${{ !matrix.ndk }} + type=raw,value=${{ steps.versions.outputs.runner_version }}-jdk${{ matrix.java_version }}-sdk${{ steps.versions.outputs.compile_sdk }}-node${{ matrix.node_version }}${{ matrix.tag_suffix }} + type=raw,value=latest,enable=${{ !matrix.ndk && matrix.is_default_jdk && matrix.is_default_node }} + type=raw,value=ndk,enable=${{ matrix.ndk }} - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests @@ -183,6 +206,8 @@ jobs: TAGS=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") # Source: one per arch, by digest, from the GHCR push in the build job. SOURCES=$(printf "${IMAGE}@sha256:%s " *) + # TAGS and SOURCES are deliberately word-split into arguments. + # shellcheck disable=SC2086 docker buildx imagetools create $TAGS $SOURCES for tag in $(jq -cr '.tags[]' <<< "$DOCKER_METADATA_OUTPUT_JSON"); do diff --git a/matrix.json b/matrix.json index bf1fe20..3b68981 100644 --- a/matrix.json +++ b/matrix.json @@ -2,11 +2,7 @@ "java_versions": [ "17", "21", - "22", - "23", - "24", "25", - "26", "27" ], "default_jdk": "27", diff --git a/tests/image-smoke.sh b/tests/image-smoke.sh new file mode 100755 index 0000000..327478c --- /dev/null +++ b/tests/image-smoke.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Smoke test for a built runner image: the toolchain a job relies on must be +# present and runnable, with the entrypoint bypassed so no runner registers. +# bash tests/image-smoke.sh [expected-jdk-major] [expected-node-major] +# The check snippets are single-quoted on purpose: they expand inside the image. +# shellcheck disable=SC2016 +set -euo pipefail + +image="${1:?usage: tests/image-smoke.sh [jdk-major] [node-major]}" +want_jdk="${2:-}" +want_node="${3:-}" + +fails=0 +fail() { echo "FAIL: $*"; fails=$((fails + 1)); } +pass() { echo "ok: $*"; } +indent() { printf ' %s\n' "${1//$'\n'/$'\n '}"; } + +# in_image