Repository: denoland/deno
Pull request: ci: skip deno-core-test when no relevant files changed

## Summary
- Add a change detection step in `pre_build` that checks if any files in `denoCorePackageDirs` (`libs/core`, `libs/serde_v8`, etc.), `Cargo.lock`, or `Cargo.toml` were modified
- Gate the `deno-core-test` job on the new `skip_deno_core_test` output, skipping it when no relevant files changed
- Clone step in `pre_build` now runs for all PRs (not just draft) to support the change detection

## Test plan
- [ ] Verify `ci.yml` is correctly regenerated (`deno run --check --allow-write=. --allow-read=. .github/workflows/ci.generate.ts`)
- [ ] Confirm `deno-core-test` is skipped on a PR that doesn't touch `libs/` or `Cargo.*`
- [ ] Confirm `deno-core-test` still runs on a PR that modifies files in `libs/core`
- [ ] Confirm `deno-core-test` still runs on pushes to main/tags (no PR context, so `skip_deno_core_test` is empty)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Changed files:
filename: .github/workflows/ci.generate.ts
patch: @@ -477,15 +477,29 @@ const preBuildCheckStep = step({
   outputs: ["skip_build"] as const,
 });
 
+const denoCoreChangesCheckStep = step({
+  id: "deno_core_changes",
+  run: [
+    `DENO_CORE_CHANGED=$(git diff --name-only \${{ github.event.pull_request.base.sha }}..HEAD | grep -qE '^(${
+      denoCorePackageDirs.join("|")
+    })/|^Cargo\\.lock$|^Cargo\\.toml$' && echo true || echo false)`,
+    `echo "Deno core changed: $DENO_CORE_CHANGED"`,
+    `echo "skip_deno_core_test=$([ "$DENO_CORE_CHANGED" = "false" ] && echo true || echo false)" >> $GITHUB_OUTPUT`,
+  ],
+  outputs: ["skip_deno_core_test"] as const,
+});
+
 const preBuildJob = job("pre_build", {
   name: "pre-build",
   runsOn: "ubuntu-latest",
-  steps: step.if(conditions.isDraftPr())(
+  steps: step.if(isPr)(
     cloneRepoStep,
-    preBuildCheckStep,
+    step.if(conditions.isDraftPr())(preBuildCheckStep),
+    denoCoreChangesCheckStep,
   ),
   outputs: {
     skip_build: preBuildCheckStep.outputs.skip_build,
+    skip_deno_core_test: denoCoreChangesCheckStep.outputs.skip_deno_core_test,
   },
 });
 
@@ -1524,7 +1538,8 @@ const denoCoreTestCacheSteps = createCacheSteps({
 const denoCoreTestJob = job("deno-core-test", {
   name: `deno_core test linux-x86_64`,
   needs: [preBuildJob],
-  if: preBuildJob.outputs.skip_build.notEquals("true"),
+  if: preBuildJob.outputs.skip_build.notEquals("true")
+    .and(preBuildJob.outputs.skip_deno_core_test.notEquals("true")),
   runsOn: denoCoreTestProfile.runner,
   timeoutMinutes: 60,
   defaults: {

filename: .github/workflows/ci.yml
patch: @@ -25,24 +25,31 @@ jobs:
     runs-on: ubuntu-latest
     outputs:
       skip_build: '${{ steps.check.outputs.skip_build }}'
+      skip_deno_core_test: '${{ steps.deno_core_changes.outputs.skip_deno_core_test }}'
     steps:
       - name: Configure git
-        if: github.event.pull_request.draft == true
+        if: github.event_name == 'pull_request'
         run: |-
           git config --global core.symlinks true
           git config --global fetch.parallel 32
       - name: Clone repository
         uses: actions/checkout@v6
-        if: github.event.pull_request.draft == true
+        if: github.event_name == 'pull_request'
         with:
           fetch-depth: 5
           submodules: false
       - id: check
-        if: 'github.event.pull_request.draft == true && !contains(github.event.pull_request.labels.*.name, ''ci-draft'')'
+        if: 'github.event_name == ''pull_request'' && github.event.pull_request.draft == true && !contains(github.event.pull_request.labels.*.name, ''ci-draft'')'
         run: |-
           GIT_MESSAGE=$(git log --format=%s -n 1 ${{github.event.after}})
           echo Commit message: $GIT_MESSAGE
           echo $GIT_MESSAGE | grep '\[ci\]' || (echo 'Exiting due to draft PR. Commit with [ci] to bypass or add the ci-draft label.' ; echo 'skip_build=true' >> $GITHUB_OUTPUT)
+      - id: deno_core_changes
+        if: github.event_name == 'pull_request'
+        run: |-
+          DENO_CORE_CHANGED=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..HEAD | grep -qE '^(libs/core_testing|libs/core|libs/core/examples/snapshot|libs/dcore|libs/ops|libs/ops/compile_test_runner|libs/serde_v8)/|^Cargo\.lock$|^Cargo\.toml$' && echo true || echo false)
+          echo "Deno core changed: $DENO_CORE_CHANGED"
+          echo "skip_deno_core_test=$([ "$DENO_CORE_CHANGED" = "false" ] && echo true || echo false)" >> $GITHUB_OUTPUT
   bench:
     name: bench release linux-x86_64
     needs:
@@ -5671,7 +5678,7 @@ jobs:
     name: deno_core test linux-x86_64
     needs:
       - pre_build
-    if: needs.pre_build.outputs.skip_build != 'true'
+    if: needs.pre_build.outputs.skip_build != 'true' && needs.pre_build.outputs.skip_deno_core_test != 'true'
     runs-on: ubuntu-24.04
     timeout-minutes: 60
     defaults: