Disable Windows Defender real-time scanning during Behat runs - #267
Conversation
The functional test job spawns a large number of short-lived `wp` and `php` processes and writes many files per scenario. On the Windows runner, Defender's real-time scanning inspects every spawned process and file write, which makes the Behat suite run several times slower than the equivalent Linux job (e.g. ~84 minutes versus ~29 minutes for the same 262 scenarios on PHP 8.5 / WP trunk / SQLite). Disabling real-time monitoring for the duration of this ephemeral, throwaway runner removes that per-process tax and cuts the wall-clock time of the Windows job substantially. The step is guarded to the Windows runner and fails silently if the cmdlet is unavailable, so it is a no-op everywhere else.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Ooooh! And all this time I just thought that Windows runner is simply super slow by default. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/reusable-functional.yml:
- Around line 54-62: Update the “Disable Windows Defender real-time scanning”
workflow step to avoid leaving Defender disabled across checkout, dependency
installation, and tests. Prefer a temporary workspace or process exclusion
scoped to the Behat workload; if disabling real-time monitoring remains
necessary, add an always() cleanup step that re-enables it before the job ends.
- Around line 59-62: Update the “Disable Windows Defender real-time scanning”
step to use PowerShell error action Stop, wrap the Set-MpPreference invocation
in catch handling, and emit a warning when disabling fails. Preserve the
Windows-only condition and best-effort job continuation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f2029ff9-ab01-4df2-83f5-dcae0aa535bd
📒 Files selected for processing (1)
.github/workflows/reusable-functional.yml
| # The Behat suite spawns a large number of short-lived `wp`/`php` | ||
| # processes and writes many files per scenario. On the Windows runner, | ||
| # Defender's real-time scanning inspects each of these, which slows the | ||
| # run down by several times compared to Linux. Turning it off for the | ||
| # duration of this ephemeral job cuts the wall-clock time dramatically. | ||
| - name: Disable Windows Defender real-time scanning | ||
| if: ${{ startsWith(inputs.os, 'windows') }} | ||
| shell: pwsh | ||
| run: Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
git ls-files .github/workflows/reusable-functional.yml
wc -l .github/workflows/reusable-functional.yml
cat -n .github/workflows/reusable-functional.yml | sed -n '1,180p'Repository: wp-cli/.github
Length of output: 8320
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "Set-MpPreference|DisableRealtimeMonitoring|Defender|Add-MpPreference|ExclusionPath|ExclusionProcess" .github/workflowsRepository: wp-cli/.github
Length of output: 516
Avoid disabling Defender globally for the entire job.
This runs before checkout and dependency installation, so all later repo, Composer, and test code executes with real-time scanning off. Use a narrower workspace/process exclusion, or re-enable it in an always() cleanup step if this has to stay.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/reusable-functional.yml around lines 54 - 62, Update the
“Disable Windows Defender real-time scanning” workflow step to avoid leaving
Defender disabled across checkout, dependency installation, and tests. Prefer a
temporary workspace or process exclusion scoped to the Behat workload; if
disabling real-time monitoring remains necessary, add an always() cleanup step
that re-enables it before the job ends.
| - name: Disable Windows Defender real-time scanning | ||
| if: ${{ startsWith(inputs.os, 'windows') }} | ||
| shell: pwsh | ||
| run: Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== relevant snippet ==="
sed -n '1,140p' .github/workflows/reusable-functional.yml
echo
echo "=== search for Set-MpPreference and Defender mentions ==="
rg -n "Set-MpPreference|Defender|RealtimeMonitoring|ErrorAction SilentlyContinue" .github/workflows . -g '!**/node_modules/**' -g '!**/.git/**'Repository: wp-cli/.github
Length of output: 6148
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,140p' .github/workflows/reusable-functional.yml
printf '\n---\n'
rg -n "Set-MpPreference|Defender|RealtimeMonitoring|ErrorAction SilentlyContinue" .github/workflows . -g '!**/node_modules/**' -g '!**/.git/**'Repository: wp-cli/.github
Length of output: 6069
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,140p' .github/workflows/reusable-functional.yml
printf '\n---\n'
rg -n "Set-MpPreference|Defender|RealtimeMonitoring|ErrorAction SilentlyContinue" .github/workflows . -g '!**/node_modules/**' -g '!**/.git/**'Repository: wp-cli/.github
Length of output: 6069
Surface Defender-disable failures -ErrorAction SilentlyContinue can leave Defender enabled while the job still passes. Use -ErrorAction Stop and emit a warning in catch so the optimization remains best-effort but observable.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/reusable-functional.yml around lines 59 - 62, Update the
“Disable Windows Defender real-time scanning” step to use PowerShell error
action Stop, wrap the Set-MpPreference invocation in catch handling, and emit a
warning when disabling fails. Preserve the Windows-only condition and
best-effort job continuation.
What
Adds a single guarded step to the reusable functional-testing workflow that turns off Windows Defender real-time monitoring on the Windows runner before the rest of the job runs.
Why
The Behat suite spawns a large number of short-lived
wp/phpprocesses and writes many files per scenario. On the Windows runner, Defender's real-time scanning inspects every spawned process and every file write, which makes the functional job run several times slower than the equivalent Linux job.Measured on a recent
extension-commandPR run (PHP 8.5 / WP trunk / SQLite, same 262 scenarios):Setup (checkout, Chocolatey,
setup-php, Composer) accounts for only ~2 minutes; effectively all of the Windows overhead is the single-threaded Behat run, and the progression is uniform across scenarios rather than caused by one slow test. That points at per-process/per-file overhead, which is exactly what Defender's real-time scanning adds.Notes
-ErrorAction SilentlyContinue, so it is a harmless no-op on Linux/macOS and won't fail the job if the cmdlet is ever restricted.setup-php, and Composer benefit as well, not just Behat.continue-on-error, so this only changes how long the informational job takes, not whether it can block a PR.Verification
The
.githubrepo doesn't run functional tests against itself. To confirm the speedup, point a package'stesting.yml(or thereusable-workflow-testrepo) at this branch and compare the Windows job duration against amainrun.Summary by CodeRabbit