Allow Odoo target replacement to repair failed lanes #3342
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 | |
| pull_request: | |
| permissions: | |
| contents: read | |
| jobs: | |
| static_checks: | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Run Ruff | |
| run: uv run --extra dev ruff check . | |
| - name: Run mypy | |
| run: uv run --extra dev mypy control_plane tests | |
| - name: Audit Python dependencies | |
| run: | | |
| # PyJWT is only used for GitHub OIDC RS256 verification; this | |
| # disputed advisory has no fixed release and concerns app-chosen | |
| # weak symmetric keys. | |
| uv run --with pip-audit pip-audit --ignore-vuln PYSEC-2025-183 | |
| static_checks_fork: | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name != github.repository | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Run Ruff | |
| run: uv run --extra dev ruff check . | |
| - name: Run mypy | |
| run: uv run --extra dev mypy control_plane tests | |
| - name: Audit Python dependencies | |
| run: | | |
| # PyJWT is only used for GitHub OIDC RS256 verification; this | |
| # disputed advisory has no fixed release and concerns app-chosen | |
| # weak symmetric keys. | |
| uv run --with pip-audit pip-audit --ignore-vuln PYSEC-2025-183 | |
| container_scan: | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| permissions: | |
| contents: read | |
| packages: read | |
| env: | |
| LAUNCHPLANE_CI_IMAGE_TAG: >- | |
| launchplane-ci:${{ github.run_id }}-${{ github.run_attempt }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Docker Buildx | |
| id: buildx | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 | |
| with: | |
| name: launchplane-ci-${{ github.run_id }}-${{ github.run_attempt }} | |
| - name: Log in to GHCR for build cache | |
| uses: docker/login-action@06fb636fac595d6fb4b28a5dfcb21a6f5091859c # v4.5.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| - name: Build runtime image | |
| uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 | |
| with: | |
| builder: ${{ steps.buildx.outputs.name }} | |
| context: . | |
| load: true | |
| tags: ${{ env.LAUNCHPLANE_CI_IMAGE_TAG }} | |
| cache-from: >- | |
| type=gha,scope=launchplane-ci | |
| cache-to: >- | |
| type=gha,scope=launchplane-ci,mode=max | |
| - name: Restore Trivy cache | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ runner.temp }}/trivy-cache | |
| key: ${{ runner.os }}-trivy-${{ github.run_id }} | |
| restore-keys: | | |
| ${{ runner.os }}-trivy- | |
| - name: Scan runtime image | |
| env: | |
| LAUNCHPLANE_TRIVY_CACHE_DIR: ${{ runner.temp }}/trivy-cache | |
| run: | | |
| mkdir -p "$LAUNCHPLANE_TRIVY_CACHE_DIR" | |
| docker run --rm \ | |
| -v /var/run/docker.sock:/var/run/docker.sock \ | |
| -v "${LAUNCHPLANE_TRIVY_CACHE_DIR}:/root/.cache" \ | |
| ghcr.io/aquasecurity/trivy:0.70.0@sha256:be1190afcb28352bfddc4ddeb71470835d16462af68d310f9f4bca710961a41e \ | |
| image \ | |
| --scanners vulnerability \ | |
| --ignore-unfixed \ | |
| --severity HIGH,CRITICAL \ | |
| --exit-code 1 \ | |
| "$LAUNCHPLANE_CI_IMAGE_TAG" | |
| - name: Remove scanned runtime image | |
| if: always() | |
| run: docker image rm "$LAUNCHPLANE_CI_IMAGE_TAG" || true | |
| container_scan_fork: | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name != github.repository | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| env: | |
| LAUNCHPLANE_CI_IMAGE_TAG: >- | |
| launchplane-ci:${{ github.run_id }}-${{ github.run_attempt }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Docker Buildx | |
| id: buildx | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 | |
| with: | |
| name: launchplane-ci-${{ github.run_id }}-${{ github.run_attempt }} | |
| - name: Build runtime image | |
| uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 | |
| with: | |
| builder: ${{ steps.buildx.outputs.name }} | |
| context: . | |
| load: true | |
| tags: ${{ env.LAUNCHPLANE_CI_IMAGE_TAG }} | |
| cache-from: >- | |
| type=gha,scope=launchplane-ci | |
| - name: Restore Trivy cache | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ runner.temp }}/trivy-cache | |
| key: ${{ runner.os }}-trivy-${{ github.run_id }} | |
| restore-keys: | | |
| ${{ runner.os }}-trivy- | |
| - name: Scan runtime image | |
| env: | |
| LAUNCHPLANE_TRIVY_CACHE_DIR: ${{ runner.temp }}/trivy-cache | |
| run: | | |
| mkdir -p "$LAUNCHPLANE_TRIVY_CACHE_DIR" | |
| docker run --rm \ | |
| -v /var/run/docker.sock:/var/run/docker.sock \ | |
| -v "${LAUNCHPLANE_TRIVY_CACHE_DIR}:/root/.cache" \ | |
| ghcr.io/aquasecurity/trivy:0.70.0@sha256:be1190afcb28352bfddc4ddeb71470835d16462af68d310f9f4bca710961a41e \ | |
| image \ | |
| --scanners vulnerability \ | |
| --ignore-unfixed \ | |
| --severity HIGH,CRITICAL \ | |
| --exit-code 1 \ | |
| "$LAUNCHPLANE_CI_IMAGE_TAG" | |
| - name: Remove scanned runtime image | |
| if: always() | |
| run: docker image rm "$LAUNCHPLANE_CI_IMAGE_TAG" || true | |
| frontend_validate: | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "22" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Enable pnpm | |
| run: | | |
| corepack enable | |
| corepack prepare pnpm@10.10.0 --activate | |
| - name: Resolve pnpm store path | |
| id: pnpm-store | |
| run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" | |
| - name: Restore pnpm store | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.pnpm-store.outputs.path }} | |
| key: >- | |
| ${{ runner.os }}-node-22-pnpm-${{ hashFiles('frontend/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node-22-pnpm- | |
| - name: Install frontend dependencies | |
| run: pnpm --dir frontend install --frozen-lockfile | |
| - name: Validate frontend | |
| run: pnpm --dir frontend validate | |
| frontend_validate_fork: | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name != github.repository | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "22" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Enable pnpm | |
| run: | | |
| corepack enable | |
| corepack prepare pnpm@10.10.0 --activate | |
| - name: Resolve pnpm store path | |
| id: pnpm-store | |
| run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" | |
| - name: Restore pnpm store | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.pnpm-store.outputs.path }} | |
| key: >- | |
| ${{ runner.os }}-node-22-pnpm-${{ hashFiles('frontend/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node-22-pnpm- | |
| - name: Install frontend dependencies | |
| run: pnpm --dir frontend install --frozen-lockfile | |
| - name: Validate frontend | |
| run: pnpm --dir frontend validate | |
| frontend_browser_smoke: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "22" | |
| - name: Enable pnpm | |
| run: | | |
| corepack enable | |
| corepack prepare pnpm@10.10.0 --activate | |
| - name: Resolve pnpm store path | |
| id: pnpm-store | |
| run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" | |
| - name: Restore pnpm store | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.pnpm-store.outputs.path }} | |
| key: >- | |
| ${{ runner.os }}-node-22-pnpm-${{ hashFiles('frontend/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node-22-pnpm- | |
| - name: Install frontend dependencies | |
| run: pnpm --dir frontend install --frozen-lockfile | |
| - name: Install Chromium | |
| run: pnpm --dir frontend exec playwright install --with-deps chromium | |
| - name: Run browser smoke | |
| run: pnpm --dir frontend test:browser | |
| - name: Upload browser evidence | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: browser-smoke-${{ github.run_attempt }} | |
| path: tmp/browser-smoke | |
| if-no-files-found: error | |
| retention-days: 14 | |
| test_timing_snapshot: | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| env: | |
| UNITTEST_TIMINGS_CACHE: .ci-cache/unittest-timings/history.json | |
| steps: | |
| - name: Restore unittest timings | |
| uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ env.UNITTEST_TIMINGS_CACHE }} | |
| key: >- | |
| ${{ runner.os }}-python-3.13-unittest-timings-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} | |
| restore-keys: | | |
| ${{ runner.os }}-python-3.13-unittest-timings-${{ github.ref_name }}-${{ github.run_id }}- | |
| ${{ runner.os }}-python-3.13-unittest-timings-${{ github.ref_name }}- | |
| ${{ runner.os }}-python-3.13-unittest-timings- | |
| - name: Freeze unittest timing snapshot | |
| run: | | |
| set -euo pipefail | |
| snapshot_directory="${RUNNER_TEMP}/unittest-timing-snapshot" | |
| mkdir -p "${snapshot_directory}" | |
| if [ -f "${UNITTEST_TIMINGS_CACHE}" ]; then | |
| cp "${UNITTEST_TIMINGS_CACHE}" "${snapshot_directory}/history.json" | |
| fi | |
| printf '%s:%s\n' "${GITHUB_RUN_ID}" "${GITHUB_RUN_ATTEMPT}" \ | |
| > "${snapshot_directory}/snapshot-id" | |
| - name: Upload unittest timing snapshot | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: unittest-timing-snapshot | |
| path: ${{ runner.temp }}/unittest-timing-snapshot | |
| if-no-files-found: error | |
| overwrite: true | |
| retention-days: 30 | |
| test_shards: | |
| needs: test_timing_snapshot | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| name: test_shard (${{ matrix.shard_index }}) | |
| env: | |
| UNITTEST_SHARD_COUNT: "12" | |
| UNITTEST_MAX_TESTS_PER_TARGET: "20" | |
| UNITTEST_MAX_SECONDS_PER_TARGET: "30" | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Download unittest timing snapshot | |
| # v7 downloads one named artifact; the following v8 step needs merge-multiple. | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: unittest-timing-snapshot | |
| path: ${{ runner.temp }}/unittest-timing-snapshot | |
| - name: Show unit test shard plan | |
| run: >- | |
| uv run --extra dev launchplane ci unittest-shard plan | |
| --shard-count "${UNITTEST_SHARD_COUNT}" | |
| --timings-file "${RUNNER_TEMP}/unittest-timing-snapshot/history.json" | |
| --max-tests-per-target "${UNITTEST_MAX_TESTS_PER_TARGET}" | |
| --max-seconds-per-target "${UNITTEST_MAX_SECONDS_PER_TARGET}" | |
| - name: Run unit test shard | |
| run: >- | |
| uv run --extra dev launchplane ci unittest-shard run | |
| --shard-count "${UNITTEST_SHARD_COUNT}" | |
| --shard-index ${{ matrix.shard_index }} | |
| --timings-file "${RUNNER_TEMP}/unittest-timing-snapshot/history.json" | |
| --max-tests-per-target "${UNITTEST_MAX_TESTS_PER_TARGET}" | |
| --max-seconds-per-target "${UNITTEST_MAX_SECONDS_PER_TARGET}" | |
| --timings-output "${RUNNER_TEMP}/unittest-timings/shard-${{ matrix.shard_index }}.json" | |
| - name: Upload unittest timings | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: unittest-timings-${{ matrix.shard_index }} | |
| path: ${{ runner.temp }}/unittest-timings/shard-${{ matrix.shard_index }}.json | |
| if-no-files-found: error | |
| overwrite: true | |
| retention-days: 30 | |
| test: | |
| needs: [test_timing_snapshot, test_shards] | |
| if: >- | |
| always() && | |
| (github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository) | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| env: | |
| UNITTEST_TIMINGS_CACHE: .ci-cache/unittest-timings/history.json | |
| UNITTEST_SHARD_COUNT: "12" | |
| UNITTEST_MAX_TESTS_PER_TARGET: "20" | |
| UNITTEST_MAX_SECONDS_PER_TARGET: "30" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Require successful test shards | |
| run: | | |
| if [ "${{ needs.test_timing_snapshot.result }}" != "success" ]; then | |
| echo "test_timing_snapshot result: ${{ needs.test_timing_snapshot.result }}" >&2 | |
| exit 1 | |
| fi | |
| if [ "${{ needs.test_shards.result }}" != "success" ]; then | |
| echo "test_shards result: ${{ needs.test_shards.result }}" >&2 | |
| exit 1 | |
| fi | |
| - name: Download unittest timing snapshot | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: unittest-timing-snapshot | |
| path: ${{ runner.temp }}/unittest-timing-snapshot | |
| - name: Download unittest timings | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: unittest-timings-* | |
| path: ${{ runner.temp }}/unittest-timings | |
| merge-multiple: true | |
| - name: Aggregate unittest timings | |
| run: >- | |
| uv run --extra dev launchplane ci unittest-shard aggregate | |
| --shard-count "${UNITTEST_SHARD_COUNT}" | |
| --results-dir "${RUNNER_TEMP}/unittest-timings" | |
| --timings-file "${RUNNER_TEMP}/unittest-timing-snapshot/history.json" | |
| --max-tests-per-target "${UNITTEST_MAX_TESTS_PER_TARGET}" | |
| --max-seconds-per-target "${UNITTEST_MAX_SECONDS_PER_TARGET}" | |
| --timings-output "${UNITTEST_TIMINGS_CACHE}" | |
| - name: Save unittest timings | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ env.UNITTEST_TIMINGS_CACHE }} | |
| key: >- | |
| ${{ runner.os }}-python-3.13-unittest-timings-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} | |
| test_fork: | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name != github.repository | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Run unit tests | |
| run: uv run --extra dev python -m unittest | |
| postgres_integration: | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: | |
| - self-hosted | |
| - ${{ vars.LAUNCHPLANE_RUNNER_LABEL }} | |
| services: | |
| postgres: | |
| image: postgres:17@sha256:0af65001d05296a2ead57ac4a6412433d8913d1bb5d0c88435a7d1e1ee5cb04b | |
| env: | |
| POSTGRES_USER: launchplane_test | |
| POSTGRES_DB: launchplane_root | |
| POSTGRES_HOST_AUTH_METHOD: trust | |
| ports: | |
| - "127.0.0.1::5432" | |
| options: >- | |
| --health-cmd "pg_isready -U launchplane_test -d launchplane_root" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: uv.lock | |
| - name: Install Python | |
| run: uv python install 3.13 | |
| - name: Run PostgreSQL integration tests | |
| env: | |
| LAUNCHPLANE_TEST_POSTGRES_URL: >- | |
| postgresql+psycopg://launchplane_test@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/launchplane_root | |
| run: uv run --extra dev launchplane ci postgres-integration | |
| ci_gate: | |
| name: ci-gate | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| needs: | |
| - static_checks | |
| - static_checks_fork | |
| - container_scan | |
| - container_scan_fork | |
| - frontend_validate | |
| - frontend_validate_fork | |
| - frontend_browser_smoke | |
| - test | |
| - test_fork | |
| - postgres_integration | |
| if: always() && github.event_name == 'pull_request' | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Require successful CI path | |
| env: | |
| BASE_REPOSITORY: ${{ github.repository }} | |
| HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }} | |
| STATIC_CHECKS_RESULT: ${{ needs.static_checks.result }} | |
| STATIC_CHECKS_FORK_RESULT: ${{ needs.static_checks_fork.result }} | |
| CONTAINER_SCAN_RESULT: ${{ needs.container_scan.result }} | |
| CONTAINER_SCAN_FORK_RESULT: ${{ needs.container_scan_fork.result }} | |
| FRONTEND_VALIDATE_RESULT: ${{ needs.frontend_validate.result }} | |
| FRONTEND_VALIDATE_FORK_RESULT: ${{ needs.frontend_validate_fork.result }} | |
| FRONTEND_BROWSER_SMOKE_RESULT: ${{ needs.frontend_browser_smoke.result }} | |
| TEST_RESULT: ${{ needs.test.result }} | |
| TEST_FORK_RESULT: ${{ needs.test_fork.result }} | |
| POSTGRES_INTEGRATION_RESULT: ${{ needs.postgres_integration.result }} | |
| run: | | |
| set -euo pipefail | |
| require_success() { | |
| check_name="$1" | |
| check_result="$2" | |
| if [ "${check_result}" != "success" ]; then | |
| echo "${check_name} concluded with: ${check_result}" >&2 | |
| exit 1 | |
| fi | |
| } | |
| if [ "${HEAD_REPOSITORY}" = "${BASE_REPOSITORY}" ]; then | |
| require_success static_checks "${STATIC_CHECKS_RESULT}" | |
| require_success container_scan "${CONTAINER_SCAN_RESULT}" | |
| require_success frontend_validate "${FRONTEND_VALIDATE_RESULT}" | |
| require_success frontend_browser_smoke "${FRONTEND_BROWSER_SMOKE_RESULT}" | |
| require_success test "${TEST_RESULT}" | |
| require_success postgres_integration "${POSTGRES_INTEGRATION_RESULT}" | |
| else | |
| require_success static_checks_fork "${STATIC_CHECKS_FORK_RESULT}" | |
| require_success container_scan_fork "${CONTAINER_SCAN_FORK_RESULT}" | |
| require_success frontend_validate_fork "${FRONTEND_VALIDATE_FORK_RESULT}" | |
| require_success frontend_browser_smoke "${FRONTEND_BROWSER_SMOKE_RESULT}" | |
| require_success test_fork "${TEST_FORK_RESULT}" | |
| fi |