|
74 | 74 | codex_plugin: ${{ steps.filter.outputs.codex_plugin }} |
75 | 75 | gcp_beginframe: ${{ steps.filter.outputs.gcp_beginframe }} |
76 | 76 | studio: ${{ steps.filter.outputs.studio }} |
| 77 | + edit_accuracy: ${{ steps.filter.outputs.edit_accuracy }} |
77 | 78 | steps: |
78 | 79 | # Force git-based change detection instead of the pull_request REST API. |
79 | 80 | # The API path can fail the whole workflow on transient listFiles |
@@ -158,6 +159,38 @@ jobs: |
158 | 159 | - "packages/studio-server/**" |
159 | 160 | - "bun.lock" |
160 | 161 | - ".github/workflows/ci.yml" |
| 162 | + edit_accuracy: |
| 163 | + - "packages/studio/src/**" |
| 164 | + - "packages/studio-server/src/**" |
| 165 | + - "packages/core/src/**" |
| 166 | + - "packages/core/scripts/**" |
| 167 | + - "packages/cli/src/**" |
| 168 | + - "packages/player/src/**" |
| 169 | + - "packages/parsers/src/**" |
| 170 | + - "packages/producer/src/**" |
| 171 | + - "packages/engine/src/**" |
| 172 | + - "packages/lint/src/**" |
| 173 | + - "packages/sdk/src/**" |
| 174 | + - "packages/studio/index.html" |
| 175 | + - "packages/studio/vite.config.ts" |
| 176 | + - "packages/studio/public/**" |
| 177 | + - "packages/cli/scripts/**" |
| 178 | + - "packages/cli/tsup.config.ts" |
| 179 | + - "packages/studio/package.json" |
| 180 | + - "packages/cli/package.json" |
| 181 | + - "packages/core/package.json" |
| 182 | + - "packages/producer/package.json" |
| 183 | + - "packages/engine/package.json" |
| 184 | + - "packages/parsers/package.json" |
| 185 | + - "packages/lint/package.json" |
| 186 | + - "packages/sdk/package.json" |
| 187 | + - "packages/studio-server/package.json" |
| 188 | + - "packages/player/package.json" |
| 189 | + - "packages/*/package-subpaths.json" |
| 190 | + - "scripts/package-subpaths.mjs" |
| 191 | + - "packages/studio/tests/e2e/edit-accuracy/**" |
| 192 | + - "bun.lock" |
| 193 | + - ".github/workflows/ci.yml" |
161 | 194 | gcp_beginframe: |
162 | 195 | - "packages/gcp-cloud-run/Dockerfile" |
163 | 196 | - "packages/aws-lambda/scripts/probe-beginframe.ts" |
@@ -216,6 +249,14 @@ jobs: |
216 | 249 | - run: bash scripts/ci/install-workspace-dependencies.sh |
217 | 250 | - run: bun run build |
218 | 251 | - run: bun run verify:packed-manifests |
| 252 | + - name: Share the built CLI with the edit accuracy shards |
| 253 | + if: github.event_name == 'pull_request' && needs.changes.outputs.edit_accuracy == 'true' |
| 254 | + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 |
| 255 | + with: |
| 256 | + name: edit-accuracy-cli |
| 257 | + path: packages/cli/dist |
| 258 | + if-no-files-found: error |
| 259 | + retention-days: 1 |
219 | 260 |
|
220 | 261 | lint: |
221 | 262 | name: Lint |
@@ -924,6 +965,117 @@ jobs: |
924 | 965 | /tmp/studio-open-counts.json |
925 | 966 | if-no-files-found: error |
926 | 967 |
|
| 968 | + # Manual editing accuracy in the built Studio, gated against the base branch's baseline.json. |
| 969 | + studio-edit-accuracy: |
| 970 | + name: "Studio: edit accuracy (${{ matrix.shard }}/8)" |
| 971 | + needs: [changes, build] |
| 972 | + if: github.event_name == 'pull_request' && needs.changes.outputs.edit_accuracy == 'true' |
| 973 | + runs-on: ubuntu-latest |
| 974 | + timeout-minutes: 45 |
| 975 | + strategy: |
| 976 | + fail-fast: false |
| 977 | + matrix: |
| 978 | + shard: [1, 2, 3, 4, 5, 6, 7, 8] |
| 979 | + steps: |
| 980 | + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
| 981 | + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 |
| 982 | + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 |
| 983 | + with: |
| 984 | + node-version: 22 |
| 985 | + - uses: ./.github/actions/prepare-ffmpeg-bin |
| 986 | + - run: bash scripts/ci/install-workspace-dependencies.sh |
| 987 | + # The bench imports producer and engine source, which need core's generated runtime files. |
| 988 | + - run: bun run --cwd packages/core build |
| 989 | + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 |
| 990 | + with: |
| 991 | + name: edit-accuracy-cli |
| 992 | + path: packages/cli/dist |
| 993 | + # Studio and the producer both run in the engine's pinned headless shell. |
| 994 | + - run: node packages/cli/dist/cli.js browser ensure |
| 995 | + - name: Read the base branch's edit accuracy baseline |
| 996 | + env: |
| 997 | + BASE_REF: ${{ github.base_ref }} |
| 998 | + run: | |
| 999 | + git fetch --no-tags --depth=1 origin "$BASE_REF" |
| 1000 | + if ! git show FETCH_HEAD:packages/studio/tests/e2e/edit-accuracy/baseline.json > /tmp/base-edit-accuracy.json; then |
| 1001 | + echo '{"cases":{}}' > /tmp/base-edit-accuracy.json |
| 1002 | + echo "The base branch has no edit accuracy baseline yet" |
| 1003 | + fi |
| 1004 | + - name: Run this shard, then re-run twice each case whose verdict differs from the base branch |
| 1005 | + run: | |
| 1006 | + set -euo pipefail |
| 1007 | + bench() { bun run --cwd packages/studio test:edit-accuracy -- --grid full --jobs 2 "$@"; } |
| 1008 | + bench --shard "${{ matrix.shard }}/8" --out /tmp/edit-accuracy/run1 |
| 1009 | + mapfile -t FLIPPED < <(node packages/studio/tests/e2e/edit-accuracy/ratchet.mjs flipped \ |
| 1010 | + /tmp/base-edit-accuracy.json /tmp/edit-accuracy/run1/results.json) |
| 1011 | + if (( ${#FLIPPED[@]} > 0 )); then |
| 1012 | + FILTER="^($(IFS='|'; echo "${FLIPPED[*]}"))$" |
| 1013 | + for run in 2 3; do bench --filter "$FILTER" --rerun --out "/tmp/edit-accuracy/run${run}"; done |
| 1014 | + fi |
| 1015 | + - name: Upload shard evidence |
| 1016 | + if: always() |
| 1017 | + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 |
| 1018 | + with: |
| 1019 | + name: edit-accuracy-shard-${{ matrix.shard }} |
| 1020 | + path: /tmp/edit-accuracy |
| 1021 | + if-no-files-found: error |
| 1022 | + |
| 1023 | + studio-edit-accuracy-gate: |
| 1024 | + name: "Studio: edit accuracy gate" |
| 1025 | + needs: [changes, studio-edit-accuracy] |
| 1026 | + if: ${{ !cancelled() && github.event_name == 'pull_request' && needs.changes.outputs.edit_accuracy == 'true' }} |
| 1027 | + runs-on: ubuntu-latest |
| 1028 | + timeout-minutes: 5 |
| 1029 | + permissions: |
| 1030 | + contents: read |
| 1031 | + pull-requests: write |
| 1032 | + steps: |
| 1033 | + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
| 1034 | + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 |
| 1035 | + with: |
| 1036 | + node-version: 22 |
| 1037 | + - name: Read the base branch's edit accuracy baseline |
| 1038 | + env: |
| 1039 | + BASE_REF: ${{ github.base_ref }} |
| 1040 | + run: | |
| 1041 | + git fetch --no-tags --depth=1 origin "$BASE_REF" |
| 1042 | + if ! git show FETCH_HEAD:packages/studio/tests/e2e/edit-accuracy/baseline.json > /tmp/base-edit-accuracy.json; then |
| 1043 | + echo '{"cases":{}}' > /tmp/base-edit-accuracy.json |
| 1044 | + echo "The base branch has no edit accuracy baseline yet" |
| 1045 | + fi |
| 1046 | + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 |
| 1047 | + with: |
| 1048 | + pattern: edit-accuracy-shard-* |
| 1049 | + path: /tmp/edit-accuracy-shards |
| 1050 | + - name: Compare every run with the base branch |
| 1051 | + id: gate |
| 1052 | + # Smoothness is reported, not gated; a case fails only if it fails 2 of its 3 runs. |
| 1053 | + run: | |
| 1054 | + set +e |
| 1055 | + mapfile -t RESULTS < <(find /tmp/edit-accuracy-shards -name results.json | sort) |
| 1056 | + node packages/studio/tests/e2e/edit-accuracy/ratchet.mjs gate /tmp/base-edit-accuracy.json \ |
| 1057 | + packages/studio/tests/e2e/edit-accuracy/baseline.json /tmp/edit-accuracy-gate "${RESULTS[@]}" |
| 1058 | + echo "exit_code=$?" >> "$GITHUB_OUTPUT" |
| 1059 | + cat /tmp/edit-accuracy-gate/comment.md >> "$GITHUB_STEP_SUMMARY" || true |
| 1060 | + - name: Post sticky comment |
| 1061 | + # Fork PRs get a read-only token; the gate below still fires. |
| 1062 | + continue-on-error: true |
| 1063 | + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4 |
| 1064 | + with: |
| 1065 | + header: edit-accuracy |
| 1066 | + path: /tmp/edit-accuracy-gate/comment.md |
| 1067 | + - name: Upload the gate report and a baseline.json to bank |
| 1068 | + if: always() |
| 1069 | + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 |
| 1070 | + with: |
| 1071 | + name: edit-accuracy-gate |
| 1072 | + path: /tmp/edit-accuracy-gate |
| 1073 | + - name: Fail if the gate failed |
| 1074 | + if: steps.gate.outputs.exit_code != '0' |
| 1075 | + run: | |
| 1076 | + echo "::error::Edit accuracy fell against the base branch; see the PR comment." |
| 1077 | + exit 1 |
| 1078 | +
|
927 | 1079 | smoke-global-install: |
928 | 1080 | name: "Smoke: global install" |
929 | 1081 | needs: [changes, build] |
|
0 commit comments