Skip to content

ci: bump GH Actions to Node 24 runtimes #46

ci: bump GH Actions to Node 24 runtimes

ci: bump GH Actions to Node 24 runtimes #46

name: Build WASM Docker Image
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
name: shared :connectedAndroidDeviceTest
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Set up JDK
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v5
# Smoke-compile the test source set on the runner without an emulator.
# Fails fast on Gradle / source-set wiring issues before paying the
# ~5 min AVD boot. Task name comes from the new
# com.android.kotlin.multiplatform.library plugin (androidDeviceTest).
- name: Compile instrumented tests
run: ./gradlew :shared:compileAndroidDeviceTest --stacktrace
- name: AVD cache
id: avd-cache
uses: actions/cache@v5
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-api-34-x86_64-v1
- name: Create AVD and generate snapshot (cold)
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
target: default
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: echo "Generated AVD snapshot for caching."
- name: Run :shared:connectedAndroidDeviceTest
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
target: default
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew :shared:connectedAndroidDeviceTest --stacktrace
- name: Upload test reports
if: always()
uses: actions/upload-artifact@v5
with:
name: shared-android-test-report
path: |
shared/build/reports/androidTests/
shared/build/outputs/androidTest-results/
# Fast JVM run of every `commonTest` case (~30s after warm cache). Runs in
# parallel with `test` to give PR authors near-immediate feedback if a common
# test breaks, without paying the Android emulator boot. The Android job
# remains the deploy gate (`build-wasm-image needs: test`) — a flaky Skia/AWT
# failure on this job cannot, by itself, block a deploy.
desktop-test:
name: shared :desktopTest
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up JDK
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v5
- name: Run :shared:desktopTest
run: ./gradlew :shared:desktopTest --stacktrace
- name: Upload test reports
if: always()
uses: actions/upload-artifact@v5
with:
name: shared-desktop-test-report
path: |
shared/build/reports/tests/desktopTest/
shared/build/test-results/desktopTest/
# End-to-end slice against the published Octocon backend image
# (digest-pinned in shared/src/desktopIntegrationTest/.../BackendContainer.kt).
# Boots the image in Testcontainers, drives the OAuth-callback auth flow
# to obtain a real token, then exercises ApiInterfaceImpl through the
# Phoenix WebSocket + endpoint-proxy paths (LoadClient + CreateAlter).
#
# Not currently a deploy gate (build-wasm-image still needs only `test`).
# Treat as parity with desktop-test: fast PR feedback, surface failures
# via branch protection in the GH UI rather than via `needs:` here.
# Approximate cost on a cold runner: ~30 s image pull + ~5 s tests.
#
# Requirements satisfied implicitly on `ubuntu-latest`:
# - Docker daemon pre-installed and reachable on the default Unix socket.
# - Bridge-network container IPs (172.17.x.y) are directly routable from
# the host JVM, which BackendContainer.baseUrl depends on so the
# backend's WebSocket endpoint-proxy loopback resolves correctly.
integration-test:
name: shared :desktopIntegrationTest
runs-on: ubuntu-latest
permissions:
contents: read
# Only required if ghcr.io/azyyyyyy/interfold-api ever flips private;
# harmless when it stays public, so granted defensively.
packages: read
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up JDK
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v5
- name: Run :shared:desktopIntegrationTest
run: ./gradlew :shared:desktopIntegrationTest --stacktrace
- name: Upload test reports
if: always()
uses: actions/upload-artifact@v5
with:
name: shared-integration-test-report
path: |
shared/build/reports/tests/desktopIntegrationTest/
shared/build/test-results/desktopIntegrationTest/
build-wasm-image:
needs: test
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v5
with:
# Need full history so the compute-version step below can walk back
# through commits with `git log --grep=^ReleaseName:` — the marker
# is intentionally sticky across commits until re-declared.
fetch-depth: 0
# Central AppVersion knobs threaded into Dockerfile.wasm as build-args
# and re-injected as -PappVersion.* flags on the Gradle command inside.
# TAG -> the git tag on HEAD (e.g. "v1.3.2"); empty for
# rolling builds. Presence flips versionName from
# the build-id to the semver.
# RELEASE_NAME -> value of the most recent `ReleaseName: <name>`
# line reachable from HEAD (sticky across commits).
# run_number is passed straight from github.run_number below and
# forms the build-id date-runNumber pair.
- name: Compute app version inputs
id: appversion
run: |
set -euo pipefail
TAG=$(git describe --tags --exact-match HEAD 2>/dev/null || true)
RELEASE_NAME=$(git log --grep='^ReleaseName:' -1 --pretty=%B \
| sed -n 's/^ReleaseName:[[:space:]]*//p' \
| head -n1 || true)
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "release_name=$RELEASE_NAME" >> "$GITHUB_OUTPUT"
echo "Resolved tag='$TAG' release_name='$RELEASE_NAME' run_number='${{ github.run_number }}'"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/octocon-wasm
tags: |
type=ref,event=branch
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.wasm
push: true
# Multi-arch fan-out. Builder stage runs once on $BUILDPLATFORM
# (the GHA amd64 runner) — see Dockerfile.wasm header comment.
# Runtime stage is COPY-only, so no QEMU binfmt handler is needed.
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
APPVERSION_RUN_NUMBER=${{ github.run_number }}
APPVERSION_TAG=${{ steps.appversion.outputs.tag }}
APPVERSION_RELEASE_NAME=${{ steps.appversion.outputs.release_name }}
# Suppress the SBOM/provenance attestation manifests — they otherwise
# show up as `unknown/unknown` entries in the OCI index, which confuses
# the bootstrapper's manifest inspection.
provenance: false
sbom: false
cache-from: type=gha,scope=octocon-wasm
cache-to: type=gha,mode=max,scope=octocon-wasm