name: Playwright Tests on: pull_request: branches: [master, release/*] workflow_dispatch: inputs: cs3d_ref: description: >- CS3D branch (e.g. main, origin:feat/foo) or version (e.g. 4.18.2, 4.19+, 4.x). Only used when ohif-integration label is present or via workflow_dispatch. required: false default: '4.19+' permissions: contents: read pull-requests: read issues: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: playwright-tests: timeout-minutes: 120 runs-on: [self-hosted, nashua] strategy: fail-fast: false matrix: node-version: [24] steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} # No `cache: pnpm`: this is a self-hosted runner with a persistent # pnpm store on local disk. The Actions cache doesn't preserve the # pnpm self-install's links faithfully, dropping pnpm/dist/worker.js # and breaking `pnpm install` with MODULE_NOT_FOUND. # Install pnpm via Corepack instead of pnpm/action-setup. The action's # self-installer is a JS action run under the runner's bundled # externals/node{version} and derives the `npm` path from that runtime — which # on this self-hosted runner is corrupted (Cannot find module # '../lib/cli.js'), so it dies regardless of `standalone:true`. Corepack # ships inside the Node that setup-node just installed, reads the pinned # `packageManager` (pnpm@11.5.2) from package.json, and fetches pnpm via # Node's own https — it never invokes the npm CLI. - name: Enable Corepack (pnpm) shell: bash run: | corepack enable corepack prepare --activate # ── CS3D integration: detect label and ref type ────────────────────── - name: Check for CS3D integration label id: cs3d-check run: bash .scripts/ci/cs3d-check-integration.sh env: GH_TOKEN: ${{ github.token }} EVENT_NAME: ${{ github.event_name }} CS3D_REF_INPUT: ${{ github.event.inputs.cs3d_ref || '4.19+' }} REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} - name: Detect CS3D ref type id: cs3d-ref if: steps.cs3d-check.outputs.enabled == 'true' run: | REF="${CS3D_REF}" if [[ "$REF" =~ ^[0-9]+\.[0-9x]+\+?(\.[0-9x]+)?(-[a-zA-Z0-9._]+)?$ ]]; then echo "type=version" >> "$GITHUB_OUTPUT" RESOLVED=$(node .scripts/cs3d-resolve-version.mjs "$REF") echo "version=$RESOLVED" >> "$GITHUB_OUTPUT" echo "::notice::CS3D version: $REF -> $RESOLVED" else echo "type=branch" >> "$GITHUB_OUTPUT" echo "::notice::CS3D branch: $REF" fi env: CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }} # ── CS3D branch path: clone and build before OHIF install ─────────── - name: Clone CS3D if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch' run: | REF="${CS3D_REF}" if [[ "$REF" == *:* ]]; then REPO="https://github.com/${REF%%:*}/cornerstone3D.git" BRANCH="${REF#*:}" else REPO="https://github.com/cornerstonejs/cornerstone3D.git" BRANCH="$REF" fi echo "::notice::Cloning CS3D from $REPO branch $BRANCH" git clone --depth 1 --branch "$BRANCH" "$REPO" libs/@cornerstonejs env: CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }} - name: Install & Build CS3D if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch' working-directory: libs/@cornerstonejs run: pnpm install --frozen-lockfile && pnpm run build:esm # ── Common: install OHIF dependencies ─────────────────────────────── - name: Install dependencies run: pnpm install --frozen-lockfile # ── CS3D branch path: link packages after OHIF install ────────────── - name: Link CS3D packages if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch' working-directory: libs/@cornerstonejs run: node scripts/link-ohif-cornerstone-node-modules.mjs "$GITHUB_WORKSPACE" # ── CS3D version path: update versions after OHIF install ─────────── - name: Set CS3D version if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'version' run: | node .scripts/cs3d-set-version.mjs "${CS3D_VERSION}" pnpm install --no-frozen-lockfile env: CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }} # ── Common: run tests ─────────────────────────────────────────────── - name: Install Playwright browsers # Only chromium is used (see playwright.config.ts and tests/globalSetup.ts); # firefox/webkit projects are commented out. Scoping the install to chromium # avoids downloading + dep-validating browsers we never launch (the WebKit # validation is what surfaces the "missing libwoff1/libflite1/..." error on # hosts without those libs). run: npx playwright install chromium - name: Run Playwright tests run: | export NODE_OPTIONS="--max_old_space_size=10192" pnpm run test:e2e:coverage # ── Common: collect test results and coverage ─────────────────────── - name: Create directory of test results if: ${{ !cancelled() }} run: | mkdir -p packaged-test-results cp -r ./tests/test-results packaged-test-results/ || true cp -r ./tests/playwright-report packaged-test-results/ || true - name: Upload directory of test results artifact if: ${{ !cancelled() }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: playwright-results path: packaged-test-results/ retention-days: 5 - name: create the coverage report run: | pnpm exec nyc report --reporter=lcov --reporter=text - name: Upload the coverage report to GitHub Actions Artifacts if: ${{ !cancelled() }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage-report-pr path: coverage retention-days: 3 # ── CS3D: build and deploy preview to Netlify ─────────────────────── - name: Log build context (OHIF/CS3D branch and version for build diagnosis) if: steps.cs3d-check.outputs.enabled == 'true' run: | if [[ "$CS3D_REF_TYPE" == "branch" ]]; then echo "::notice::Build type: ohif-downstream | OHIF: ${{ github.repository }}@${{ github.ref }} (${{ github.sha }}) | CS3D: branch ${{ steps.cs3d-check.outputs.cs3d_ref }}" else echo "::notice::Build type: ohif-upstream | OHIF: ${{ github.repository }}@${{ github.ref }} (${{ github.sha }}) | CS3D: version ${{ steps.cs3d-ref.outputs.version }}" fi node .scripts/log-build-context.mjs env: BUILD_TYPE: ${{ steps.cs3d-ref.outputs.type == 'branch' && 'ohif-downstream' || 'ohif-upstream' }} CS3D_REF_TYPE: ${{ steps.cs3d-ref.outputs.type }} - name: Build OHIF viewer (CS3D preview) if: steps.cs3d-check.outputs.enabled == 'true' run: pnpm run build:ci - name: Deploy CS3D preview to Netlify if: steps.cs3d-check.outputs.enabled == 'true' run: | RESULT=$(npx netlify-cli deploy --dir=platform/app/dist --alias="cs3d-pr-${PR_NUM}" --json --filter=@ohif/app) || { echo "::error::Netlify deploy command failed" exit 1 } URL=$(echo "$RESULT" | jq -r '.deploy_url') if [[ -z "$URL" || "$URL" == "null" ]]; then echo "::error::Netlify deploy did not return a valid URL" echo "$RESULT" exit 1 fi echo "::notice::CS3D preview deployed: $URL" env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} PR_NUM: ${{ github.event.pull_request.number || 'manual' }} # ── CS3D: log results ─────────────────────────────────────────────── - name: Log CS3D build used if: steps.cs3d-check.outputs.enabled == 'true' run: | if [[ "$CS3D_REF_TYPE" == "branch" ]]; then echo "::notice::CS3D integration PASSED with branch ${CS3D_REF} (linked from libs/@cornerstonejs)" else echo "::notice::CS3D integration PASSED with @cornerstonejs/*@${CS3D_VERSION}" fi env: CS3D_REF_TYPE: ${{ steps.cs3d-ref.outputs.type }} CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }} CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }} # ── Separate job: block merge when using a CS3D branch ───────────── cs3d-branch-merge-guard: name: 'CS3D Branch Merge Guard' runs-on: ubuntu-latest timeout-minutes: 5 steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Check for CS3D branch usage run: bash .scripts/ci/cs3d-branch-merge-guard.sh env: GH_TOKEN: ${{ github.token }} EVENT_NAME: ${{ github.event_name }} CS3D_REF_INPUT: ${{ github.event.inputs.cs3d_ref || '4.19+' }} REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }}