|
50 | 50 | SYSTEM_ENABLEANALYTICS: "false" |
51 | 51 | steps: |
52 | 52 | - name: Harden Runner |
53 | | - uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 |
| 53 | + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 |
54 | 54 | with: |
55 | 55 | egress-policy: audit |
56 | 56 | - name: Checkout repository |
@@ -295,3 +295,70 @@ jobs: |
295 | 295 | name: playwright-report-enterprise-${{ github.run_id }} |
296 | 296 | path: frontend/playwright-report/ |
297 | 297 | retention-days: 7 |
| 298 | + |
| 299 | + # Multi-node regression: builds + seeds the clustered stack (testing/compose/docker-compose-multinode.yml) |
| 300 | + # and runs behave features/multinode. Licence-gated, so it runs after the Playwright job (not in parallel). |
| 301 | + multinode-e2e: |
| 302 | + needs: [pick, playwright-e2e-enterprise] |
| 303 | + # Nightly cron + manual dispatch only (heavy build), fork-gated for the licence secret. |
| 304 | + if: >- |
| 305 | + always() && needs.pick.outputs.is_fork != 'true' |
| 306 | + && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') |
| 307 | + runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }} |
| 308 | + timeout-minutes: 60 |
| 309 | + env: |
| 310 | + PREMIUM_KEY: ${{ secrets.PREMIUM_KEY_ENTERPRISE }} |
| 311 | + PREMIUM_ENABLED: "true" |
| 312 | + SYSTEM_ENABLEANALYTICS: "false" |
| 313 | + DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} |
| 314 | + MN_COMPOSE: docker-compose-multinode.yml |
| 315 | + steps: |
| 316 | + - name: Harden Runner |
| 317 | + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 |
| 318 | + with: |
| 319 | + egress-policy: audit |
| 320 | + - name: Checkout repository |
| 321 | + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| 322 | + - name: Set up Python |
| 323 | + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 |
| 324 | + with: |
| 325 | + python-version: "3.12" |
| 326 | + cache: "pip" |
| 327 | + cache-dependency-path: ./testing/cucumber/requirements.txt |
| 328 | + - name: Install behave test deps |
| 329 | + run: | |
| 330 | + pip install --require-hashes --only-binary=:all: -r ./testing/cucumber/requirements.txt |
| 331 | + - name: Build the multi-node image |
| 332 | + working-directory: testing/compose |
| 333 | + run: docker compose -f "$MN_COMPOSE" build |
| 334 | + - name: Bring up the cluster and wait for both nodes healthy |
| 335 | + working-directory: testing/compose |
| 336 | + run: | |
| 337 | + docker compose -f "$MN_COMPOSE" up -d |
| 338 | + for i in $(seq 1 90); do |
| 339 | + h1=$(docker inspect -f '{{.State.Health.Status}}' multinode-stirling-1 2>/dev/null || echo starting) |
| 340 | + h2=$(docker inspect -f '{{.State.Health.Status}}' multinode-stirling-2 2>/dev/null || echo starting) |
| 341 | + if [ "$h1" = healthy ] && [ "$h2" = healthy ]; then echo "both nodes healthy"; exit 0; fi |
| 342 | + sleep 5 |
| 343 | + done |
| 344 | + echo "::error::nodes did not become healthy" |
| 345 | + docker compose -f "$MN_COMPOSE" logs --tail=200 stirling-1 stirling-2 |
| 346 | + exit 1 |
| 347 | + - name: Seed the cluster (teams, users, S3 connection, policy) |
| 348 | + working-directory: testing/compose |
| 349 | + run: docker compose -f "$MN_COMPOSE" --profile seed run --rm seed |
| 350 | + - name: Run multi-node regression (implemented guarantees) |
| 351 | + working-directory: testing/cucumber |
| 352 | + # -e overrides behave.ini's exclusion of features/multinode; ~@known_gap skips any tracked-gap scenarios. |
| 353 | + run: python -m behave features/multinode -e "features/enterprise" --tags="~@known_gap ~@destructive" --no-capture -f plain |
| 354 | + - name: Run multi-node failover (destructive) |
| 355 | + working-directory: testing/cucumber |
| 356 | + run: python -m behave features/multinode -e "features/enterprise" --tags="@destructive ~@known_gap" --no-capture -f plain |
| 357 | + - name: Dump node logs on failure |
| 358 | + if: failure() |
| 359 | + working-directory: testing/compose |
| 360 | + run: docker compose -f "$MN_COMPOSE" logs --tail=400 stirling-1 stirling-2 |
| 361 | + - name: Tear down |
| 362 | + if: always() |
| 363 | + working-directory: testing/compose |
| 364 | + run: docker compose -f "$MN_COMPOSE" --profile seed down -v --remove-orphans |
0 commit comments