operator: make v1alpha1 CRD lifecycle executable #476
Workflow file for this run
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
| name: CI | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| changes: | |
| name: changes | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| outputs: | |
| continuity: ${{ steps.classify.outputs.continuity }} | |
| cluster: ${{ steps.classify.outputs.cluster }} | |
| official_omp_gate0: ${{ steps.classify.outputs.official_omp_gate0 }} | |
| tooling: ${{ steps.classify.outputs.tooling }} | |
| android_debug: ${{ steps.classify.outputs.android_debug }} | |
| flutter: ${{ steps.classify.outputs.flutter }} | |
| flutter_android: ${{ steps.classify.outputs.flutter_android }} | |
| flutter_apple: ${{ steps.classify.outputs.flutter_apple }} | |
| steps: | |
| - name: Check out source and base history | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| - name: Test path classification | |
| run: node --test scripts/ci-paths.test.mjs | |
| - name: Classify affected CI legs | |
| id: classify | |
| shell: bash | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| set -euo pipefail | |
| if [[ "$EVENT_NAME" != pull_request ]]; then | |
| node scripts/ci-paths.mjs --all >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| [[ "$BASE_SHA" =~ ^[0-9a-f]{40}$ ]] | |
| [[ "$HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] | |
| git diff --name-only -z "$BASE_SHA...$HEAD_SHA" | node scripts/ci-paths.mjs >> "$GITHUB_OUTPUT" | |
| core: | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 25 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install Bun for the T4 host packages | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.3.14 | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Install browser for end-to-end tests | |
| run: pnpm exec playwright install --with-deps chromium | |
| - name: Check source and types | |
| run: pnpm check:release && pnpm check:provenance && pnpm lint && pnpm --filter '!@t4-code/flutter' -r typecheck | |
| - name: Run tests | |
| run: pnpm --filter '!@t4-code/flutter' -r test | |
| - name: Build all workspaces | |
| run: pnpm --filter '!@t4-code/flutter' -r build | |
| - name: Run built-app end-to-end tests | |
| run: pnpm test:e2e | |
| - name: Check packaging contract | |
| run: pnpm test:packaging | |
| legacy-bridge-continuity: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.continuity == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Check out exact T4 source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha || github.sha }} | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.3.14 | |
| - name: Install continuity prerequisites | |
| run: sudo apt-get update && sudo apt-get install --yes expect | |
| - name: Install T4 dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Resolve pinned OMP authority source | |
| id: authority | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| source_repository="$(jq -er '.sourceRepository' provenance/omp-host-migration.json)" | |
| test "$source_repository" = "https://github.com/lyc-aon/oh-my-pi" | |
| sha="$(jq -er '.inputs.operationsContinuity' provenance/omp-host-migration.json)" | |
| [[ "$sha" =~ ^[0-9a-f]{40}$ ]] | |
| echo "repository=lyc-aon/oh-my-pi" >> "$GITHUB_OUTPUT" | |
| echo "sha=$sha" >> "$GITHUB_OUTPUT" | |
| - name: Check out pinned OMP authority source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| repository: ${{ steps.authority.outputs.repository }} | |
| ref: ${{ steps.authority.outputs.sha }} | |
| path: .continuity/omp | |
| - name: Install OMP authority dependencies | |
| working-directory: .continuity/omp | |
| run: bun install --frozen-lockfile | |
| - name: Build OMP native addon | |
| working-directory: .continuity/omp | |
| run: bun run build:native | |
| - name: Run legacy bridge continuity gate | |
| env: | |
| T4_OMP_SOURCE_DIR: ${{ github.workspace }}/.continuity/omp | |
| run: pnpm test:legacy-bridge-continuity | |
| - name: Upload continuity evidence | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: legacy-bridge-continuity-${{ github.run_id }} | |
| path: artifacts/legacy-bridge-continuity/ | |
| if-no-files-found: error | |
| retention-days: 14 | |
| official-omp-gate0: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.official_omp_gate0 == 'true' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux-x64 | |
| runner: ubuntu-24.04 | |
| - platform: linux-arm64 | |
| runner: ubuntu-24.04-arm | |
| - platform: darwin-arm64 | |
| runner: macos-15 | |
| name: official-omp-gate0 (${{ matrix.platform }}) | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Check out exact T4 source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha || github.sha }} | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| - name: Install Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.3.14 | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Prove the pinned unmodified official OMP runtime | |
| run: pnpm --filter @t4-code/host-service verify:official-omp-lifecycle | |
| - name: Prove the packaged T4 host against official OMP | |
| run: pnpm --filter @t4-code/host-daemon verify:official-omp-packaged | |
| - name: Upload official OMP Gate 0 evidence | |
| if: ${{ success() }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: official-omp-gate0-${{ matrix.platform }}-${{ github.run_id }} | |
| path: | | |
| artifacts/official-omp-gate0/${{ matrix.platform }}.json | |
| artifacts/official-omp-packaged-host/${{ matrix.platform }}.json | |
| if-no-files-found: error | |
| retention-days: 14 | |
| cluster: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.cluster == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 25 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.3.14 | |
| - name: Install Go | |
| uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 | |
| with: | |
| go-version: "1.25.5" | |
| cache-dependency-path: packages/cluster-operator/go.sum | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Install pinned Helm | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| curl -fsSLo /tmp/helm.tar.gz https://get.helm.sh/helm-v3.19.0-linux-amd64.tar.gz | |
| echo "a7f81ce08007091b86d8bd696eb4d86b8d0f2e1b9f6c714be62f82f96a594496 /tmp/helm.tar.gz" | sha256sum -c - | |
| tar -xzf /tmp/helm.tar.gz -C /tmp | |
| sudo install -m 0755 /tmp/linux-amd64/helm /usr/local/bin/helm | |
| - name: Run cluster CI proof contracts | |
| run: pnpm test:cluster:ci | |
| - name: Run cluster server tests | |
| run: pnpm --filter @t4-code/cluster-server test | |
| - name: Typecheck cluster server | |
| run: pnpm --filter @t4-code/cluster-server typecheck | |
| - name: Run cluster protocol contracts | |
| run: | | |
| pnpm --filter @t4-code/host-wire exec bun test test/cluster-operator.test.ts | |
| pnpm --filter @t4-code/host-service exec bun test test/cluster-default-off.test.ts | |
| - name: Run operator tests | |
| working-directory: packages/cluster-operator | |
| env: | |
| GOFLAGS: -mod=readonly | |
| run: go test ./... | |
| - name: Lint cluster chart | |
| run: helm lint deploy/charts/t4-cluster | |
| tooling: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.tooling == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 25 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Run tooling regression tests | |
| run: pnpm test:tooling | |
| android-debug: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.android_debug == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 35 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install Java | |
| uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| cache: gradle | |
| - name: Install Android SDK | |
| uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3 | |
| - name: Install pinned Android platform and build tools | |
| run: sdkmanager --install "platforms;android-36" "build-tools;36.0.0" | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build web application | |
| run: pnpm build:web | |
| - name: Verify unsigned Android debug application | |
| run: pnpm --filter @t4-code/mobile check:android:debug | |
| flutter: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.flutter == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install Flutter | |
| uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 | |
| with: | |
| flutter-version: 3.44.6 | |
| channel: stable | |
| cache: true | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Check Flutter source | |
| run: pnpm check:flutter | |
| - name: Run Flutter tests with coverage gate | |
| run: pnpm --filter @t4-code/flutter test:coverage | |
| - name: Build Flutter web application | |
| run: pnpm build:flutter:web | |
| flutter-android: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.flutter_android == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 35 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install Java | |
| uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| cache: gradle | |
| - name: Install Flutter | |
| uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 | |
| with: | |
| flutter-version: 3.44.6 | |
| channel: stable | |
| cache: true | |
| - name: Build Flutter Android application | |
| working-directory: apps/flutter | |
| run: flutter build apk --debug | |
| - name: Run Flutter Android native tests | |
| working-directory: apps/flutter/android | |
| run: ./gradlew app:testDebugUnitTest | |
| - name: Enable Android emulator acceleration | |
| run: sudo chmod 666 /dev/kvm | |
| - name: Run Flutter Android device smoke test | |
| uses: ReactiveCircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2 | |
| with: | |
| api-level: 35 | |
| arch: x86_64 | |
| profile: pixel_6 | |
| script: cd apps/flutter && flutter test integration_test/app_smoke_test.dart -d emulator-5554 | |
| flutter-apple: | |
| needs: changes | |
| if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.flutter_apple == 'true' }} | |
| runs-on: macos-15 | |
| timeout-minutes: 40 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install Flutter | |
| uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 | |
| with: | |
| flutter-version: 3.44.6 | |
| channel: stable | |
| cache: true | |
| - name: Build Flutter iOS simulator application | |
| working-directory: apps/flutter | |
| run: flutter build ios --simulator --debug | |
| - name: Run Flutter iOS launch smoke test | |
| working-directory: apps/flutter | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| DEVICE_ID="$(xcrun simctl list devices available -j | python3 -c 'import json,sys; data=json.load(sys.stdin); print(next(device["udid"] for devices in data["devices"].values() for device in devices if device["name"].startswith("iPhone")))')" | |
| BUNDLE_ID="com.lycaonsolutions.t4code" | |
| xcrun simctl boot "$DEVICE_ID" 2>/dev/null || true | |
| xcrun simctl bootstatus "$DEVICE_ID" -b | |
| xcrun simctl install "$DEVICE_ID" build/ios/iphonesimulator/Runner.app | |
| trap 'xcrun simctl terminate "$DEVICE_ID" "$BUNDLE_ID" 2>/dev/null || true' EXIT | |
| launch_output="$(xcrun simctl launch --terminate-running-process "$DEVICE_ID" "$BUNDLE_ID")" | |
| app_pid="$(sed -nE 's/^.*: ([0-9]+)$/\1/p' <<<"$launch_output" | tail -n 1)" | |
| [[ "$app_pid" =~ ^[0-9]+$ ]] | |
| sleep 5 | |
| kill -0 "$app_pid" | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| with: | |
| version: 11.10.0 | |
| - name: Install Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 24.13.1 | |
| cache: pnpm | |
| - name: Install Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.3.14 | |
| - name: Install T4 dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build standalone T4 host for Flutter macOS | |
| run: pnpm build:host | |
| - name: Build Flutter macOS application | |
| working-directory: apps/flutter | |
| run: flutter build macos --debug | |
| - name: Verify bundled Flutter macOS host | |
| run: test -x apps/flutter/build/macos/Build/Products/Debug/t4code.app/Contents/Resources/runtime/t4-host | |
| - name: Run Flutter macOS native tests | |
| working-directory: apps/flutter/macos | |
| run: xcodebuild test -workspace Runner.xcworkspace -scheme Runner -configuration Debug -destination 'platform=macOS' CODE_SIGNING_ALLOWED=NO | |
| verify: | |
| name: verify | |
| if: ${{ always() }} | |
| needs: [changes, core, legacy-bridge-continuity, official-omp-gate0, cluster, tooling, android-debug, flutter, flutter-android, flutter-apple] | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Require every selected CI leg | |
| shell: bash | |
| env: | |
| CHANGES_RESULT: ${{ needs.changes.result }} | |
| CORE_RESULT: ${{ needs.core.result }} | |
| CONTINUITY_RESULT: ${{ needs.legacy-bridge-continuity.result }} | |
| OFFICIAL_OMP_GATE0_RESULT: ${{ needs.official-omp-gate0.result }} | |
| CLUSTER_RESULT: ${{ needs.cluster.result }} | |
| TOOLING_RESULT: ${{ needs.tooling.result }} | |
| ANDROID_RESULT: ${{ needs.android-debug.result }} | |
| FLUTTER_RESULT: ${{ needs.flutter.result }} | |
| FLUTTER_ANDROID_RESULT: ${{ needs.flutter-android.result }} | |
| FLUTTER_APPLE_RESULT: ${{ needs.flutter-apple.result }} | |
| run: | | |
| set -euo pipefail | |
| test "$CHANGES_RESULT" = success | |
| test "$CORE_RESULT" = success | |
| for result in \ | |
| "$CONTINUITY_RESULT" \ | |
| "$OFFICIAL_OMP_GATE0_RESULT" \ | |
| "$CLUSTER_RESULT" \ | |
| "$TOOLING_RESULT" \ | |
| "$ANDROID_RESULT" \ | |
| "$FLUTTER_RESULT" \ | |
| "$FLUTTER_ANDROID_RESULT" \ | |
| "$FLUTTER_APPLE_RESULT" | |
| do | |
| case "$result" in | |
| success|skipped) ;; | |
| *) exit 1 ;; | |
| esac | |
| done |