diff --git a/.github/scripts/tests/lockfile-refresh-workflows.test.mjs b/.github/scripts/tests/lockfile-refresh-workflows.test.mjs index 52fef1f698..7c19cf2cb9 100644 --- a/.github/scripts/tests/lockfile-refresh-workflows.test.mjs +++ b/.github/scripts/tests/lockfile-refresh-workflows.test.mjs @@ -17,6 +17,7 @@ test('lockfile repair workflows resolve dependencies instead of updating metadat assert.ok(repairCommands.length > 0, `${workflow} must contain a lockfile repair command`); for (const command of repairCommands) { + assert.match(command, /--resolution-only/); assert.match(command, /--ignore-scripts/); assert.doesNotMatch(command, /--lockfile-only/); } diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5fb9f7e600..793568d0b5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -87,7 +87,7 @@ jobs: - name: Refresh lockfile for Docker build context run: | set -euo pipefail - pnpm install --ignore-scripts --no-frozen-lockfile + pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile changed="$(git status --porcelain)" if [ -z "$changed" ]; then @@ -281,7 +281,7 @@ jobs: - name: Refresh lockfile for Docker build context run: | set -euo pipefail - pnpm install --ignore-scripts --no-frozen-lockfile + pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile changed="$(git status --porcelain)" if [ -z "$changed" ]; then diff --git a/.github/workflows/pr-trusted.yml b/.github/workflows/pr-trusted.yml index edbe655136..cc04e18fc4 100644 --- a/.github/workflows/pr-trusted.yml +++ b/.github/workflows/pr-trusted.yml @@ -346,7 +346,7 @@ jobs: id: regen_lockfile run: | cp pnpm-lock.yaml "$RUNNER_TEMP/pnpm-lock.before.yaml" - pnpm install --ignore-scripts --no-frozen-lockfile + pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile if cmp -s "$RUNNER_TEMP/pnpm-lock.before.yaml" pnpm-lock.yaml; then echo "regenerated=0" >> "$GITHUB_OUTPUT" else diff --git a/.github/workflows/refresh-lockfile.yml b/.github/workflows/refresh-lockfile.yml index 039d21970e..df9bd7abef 100644 --- a/.github/workflows/refresh-lockfile.yml +++ b/.github/workflows/refresh-lockfile.yml @@ -35,7 +35,7 @@ jobs: cache: pnpm - name: Refresh pnpm lockfile - run: pnpm install --ignore-scripts --no-frozen-lockfile + run: pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile - name: Fail on unexpected file changes run: | diff --git a/.github/workflows/runner-full-stack-e2e.yml b/.github/workflows/runner-full-stack-e2e.yml index 9c45df4479..1150d96d54 100644 --- a/.github/workflows/runner-full-stack-e2e.yml +++ b/.github/workflows/runner-full-stack-e2e.yml @@ -923,6 +923,21 @@ jobs: test -x "$chrome_path" google-chrome --version + - name: Install Playwright FFmpeg on AWS runner + if: needs.authorize.outputs.playwright_channel == 'chrome' + run: | + set -euo pipefail + for attempt in 1 2 3; do + if pnpm exec playwright install ffmpeg; then + exit 0 + fi + if [ "$attempt" -eq 3 ]; then + echo "Playwright FFmpeg installation failed after $attempt attempts." >&2 + exit 1 + fi + sleep "$((attempt * 10))" + done + - name: Install Chromium headless shell on GitHub-hosted fallback if: needs.authorize.outputs.playwright_channel != 'chrome' run: | diff --git a/scripts/__tests__/e2e-shard.test.mjs b/scripts/__tests__/e2e-shard.test.mjs index 691c0b6cc1..ae56c9c411 100644 --- a/scripts/__tests__/e2e-shard.test.mjs +++ b/scripts/__tests__/e2e-shard.test.mjs @@ -306,8 +306,8 @@ test("the trusted PR workflow regenerates stale stacked lockfiles", () => { ); assert.match( workflow, - /pnpm install --ignore-scripts --no-frozen-lockfile/, - "the policy job must resolve the complete merge tree instead of only updating lockfile metadata", + /pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile/, + "the policy job must resolve the complete merge tree without rewriting platform metadata", ); assert.match( workflow, diff --git a/tests/runner-e2e/workflow-security.test.ts b/tests/runner-e2e/workflow-security.test.ts index ee46454dd1..93623e2d24 100644 --- a/tests/runner-e2e/workflow-security.test.ts +++ b/tests/runner-e2e/workflow-security.test.ts @@ -266,10 +266,30 @@ describe("public repository paid workflow security", () => { const daytonaPluginPreparation = paidJob.indexOf( "Prepare bundled Daytona plugin without dependency lifecycle scripts", ); + const awsFfmpegInstall = paidJob.indexOf( + "- name: Install Playwright FFmpeg on AWS runner", + ); + const hostedChromiumInstall = paidJob.indexOf( + "- name: Install Chromium headless shell on GitHub-hosted fallback", + ); const paidExecution = paidJob.indexOf("- name: Run paid cell"); expect(paidInstall).toBeGreaterThan(0); expect(daytonaPluginPreparation).toBeGreaterThan(paidInstall); + expect(awsFfmpegInstall).toBeGreaterThan(daytonaPluginPreparation); + expect(hostedChromiumInstall).toBeGreaterThan(awsFfmpegInstall); + expect(paidExecution).toBeGreaterThan(awsFfmpegInstall); expect(paidExecution).toBeGreaterThan(daytonaPluginPreparation); + const awsFfmpegStep = paidJob.slice( + awsFfmpegInstall, + hostedChromiumInstall, + ); + expect(awsFfmpegStep).toContain( + "if: needs.authorize.outputs.playwright_channel == 'chrome'", + ); + expect(awsFfmpegStep).toContain("pnpm exec playwright install ffmpeg"); + expect(awsFfmpegStep).not.toMatch( + /(?:OPENAI|ANTHROPIC|OPENROUTER|DAYTONA)_API_KEY/, + ); const preparedBeforeProviderAccess = paidJob.slice( daytonaPluginPreparation, paidExecution,