diff --git a/.circleci/config.yml b/.circleci/config.yml index 51724a800..91bfabdbc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ orbs: defaults: &defaults docker: - - image: cimg/node:24.0.0 + - image: cimg/node:24.15.0 environment: TERM: xterm QUICK_BUILD: true @@ -421,7 +421,7 @@ jobs: -o Acquire::Retries=3 \ -o Acquire::http::Timeout=20 \ -o Acquire::https::Timeout=20 - sudo apt-get install -y xvfb libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 + sudo apt-get install -y xvfb libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2t64 libxtst6 - run: name: Start Xvfb command: Xvfb :99 -screen 0 1920x1080x24 & diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index c40721168..a6f0e620a 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -27,7 +27,7 @@ jobs: - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version: 24 + node-version: 24.15.0 cache: pnpm - name: Configure git for private repos diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index f7de41b8b..3395b6495 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [24] + node-version: [24.15.0] steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: @@ -133,7 +133,7 @@ jobs: - name: Run Playwright tests run: | export NODE_OPTIONS="--max_old_space_size=10192" - pnpm run test:e2e:coverage + bash .scripts/ci/with-nashua-lock.sh pnpm run test:e2e:coverage # ── Common: collect test results and coverage ─────────────────────── - name: Create directory of test results diff --git a/.node-version b/.node-version index a45fd52cc..5bf4400f2 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -24 +24.15.0 diff --git a/.scripts/ci/with-nashua-lock.sh b/.scripts/ci/with-nashua-lock.sh new file mode 100644 index 000000000..620596f6c --- /dev/null +++ b/.scripts/ci/with-nashua-lock.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# +# Run a command while holding the nashua Playwright mutex. +# +# Only one Playwright run may execute at a time on the shared nashua self-hosted +# runner — across THIS repo (OHIF) AND the cornerstone3D repo. GitHub's +# `concurrency:` is scoped per-repository and cannot coordinate across the two +# orgs, so the mutex lives on the box's filesystem. +# +# This is OHIF's own copy (the script can't be shared across separate repos). It +# MUST use the SAME lock path as cornerstone3D's copy (NASHUA_LOCK_FILE default +# below) — if the paths differ, the mutex silently does nothing. +# +# flock holds the lock via fd 9 and it releases automatically when the wrapped +# command exits — including on job cancel / timeout / SIGKILL — so there are no +# stale locks to clean up. +# +# Usage: .scripts/ci/with-nashua-lock.sh [args...] + +# Strict mode: -e abort on any unhandled command failure, -u treat use of an +# unset variable as an error, -o pipefail make a pipeline fail if ANY stage +# fails (not just the last). Catches mistakes early instead of pressing on. +set -euo pipefail + +LOCK="${NASHUA_LOCK_FILE:-/var/tmp/nashua-playwright.lock}" # MUST match cornerstone3D's copy +LOCK_WAIT="${NASHUA_LOCK_WAIT:-5400}" # max seconds to wait + +# Guard: a command to wrap is required. With no arguments there is nothing to +# run, so print usage and exit instead of silently grabbing and releasing the +# lock for no reason (which would mask a mis-wired workflow step). +if [ "$#" -eq 0 ]; then + echo "usage: $0 [args...]" >&2 + exit 2 +fi + +# Open the lock file on fd 9 (read-write, create if missing, never truncate). +exec 9<>"$LOCK" || { echo "::error::cannot open lock file $LOCK"; exit 1; } + +# Try instantly; if busy, report who holds it, then block up to LOCK_WAIT. +if ! flock -n 9; then + echo "nashua Playwright runner busy — held by: $(cat "${LOCK}.info" 2>/dev/null || echo unknown). Waiting up to ${LOCK_WAIT}s…" + if ! flock -w "$LOCK_WAIT" 9; then + echo "::error::Timed out after ${LOCK_WAIT}s waiting for the nashua Playwright lock" + exit 1 + fi +fi + +# Record the current holder for other jobs' "held by" message (best-effort). +echo "${GITHUB_REPOSITORY:-local}#${GITHUB_RUN_ID:-0} @ $(date -u +%FT%TZ 2>/dev/null || true)" > "${LOCK}.info" 2>/dev/null || true +echo "✅ Acquired nashua Playwright lock ($LOCK); running: $*" + +# Replace the shell with the command. fd 9 is inherited (not close-on-exec), so +# the lock is held for the whole command and released when it exits. +exec "$@" diff --git a/Dockerfile b/Dockerfile index a8c321b9d..ac63036ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ # Stage 1: Build the application # docker build -t ohif/viewer:latest . # Copy Files -FROM node:24-slim as builder +FROM node:24.15.0-slim as builder RUN apt-get update && apt-get install -y --no-install-recommends build-essential python3 \ && rm -rf /var/lib/apt/lists/* diff --git a/netlify.toml b/netlify.toml index 72b92d988..c577d740f 100644 --- a/netlify.toml +++ b/netlify.toml @@ -15,7 +15,7 @@ [build.environment] # If 'production', `pnpm install` does not install devDependencies NODE_ENV = "development" - NODE_VERSION = "24" + NODE_VERSION = "24.15.0" [[headers]] for = "/*" diff --git a/playwright.config.ts b/playwright.config.ts index f0822fd8f..d5fbde163 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, retries: process.env.CI ? 1 : 0, maxFailures: process.env.CI ? 10 : undefined, - workers: process.env.CI ? 8 : undefined, + workers: process.env.CI ? 18 : undefined, snapshotPathTemplate: './tests/screenshots{/projectName}/{testFilePath}/{arg}{ext}', outputDir: './tests/test-results', reporter: [['html', { outputFolder: './tests/playwright-report' }]],