Skip to content

Commit ee2962a

Browse files
committed
ci: clean windows disk space in background
1 parent a153133 commit ee2962a

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ jobs:
223223
cd src/ci/citool
224224
CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=../../../build/citool cargo build
225225
226+
- name: wait for Windows disk cleanup to finish
227+
if: ${{ matrix.free_disk && startsWith(matrix.os, 'windows-') }}
228+
run: |
229+
python3 src/ci/scripts/free-disk-space-windows-wait.py
230+
226231
- name: run the build
227232
run: |
228233
set +e
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
Start freeing disk space on Windows in the background by launching
3+
the existing PowerShell cleanup script, while recording a PID file
4+
and redirecting logs, so later steps can wait for completion.
5+
"""
6+
7+
import os
8+
import sys
9+
import subprocess
10+
from pathlib import Path
11+
12+
13+
# Get the temporary directory set by GitHub Actions
14+
def get_temp_dir() -> Path:
15+
return Path(os.environ.get("RUNNER_TEMP"))
16+
17+
18+
def main() -> int:
19+
script_dir = Path(__file__).resolve().parent
20+
cleanup_script = script_dir / "free-disk-space-windows.ps1"
21+
if not cleanup_script.exists():
22+
print(f"::error file={__file__}::Cleanup script '{cleanup_script}' not found")
23+
return 1
24+
25+
temp_dir = get_temp_dir()
26+
pid_file = temp_dir / "free-disk-space.pid"
27+
log_file_path = temp_dir / "free-disk-space.log"
28+
29+
if pid_file.exists():
30+
print(f"::error file={__file__}::Pid file '{pid_file}' already exists")
31+
return 1
32+
33+
# Launch the PowerShell cleanup in the background and redirect logs
34+
try:
35+
with open(log_file_path, "w", encoding="utf-8") as log_file:
36+
proc = subprocess.Popen(
37+
[
38+
"pwsh",
39+
# Suppress PowerShell startup banner/logo for cleaner logs.
40+
"-NoLogo",
41+
# Don't load user/system profiles. Ensures a clean, predictable environment.
42+
"-NoProfile",
43+
# Disable interactive prompts. Required for CI to avoid hangs.
44+
"-NonInteractive",
45+
# Execute the specified script file (next argument).
46+
"-File",
47+
str(cleanup_script),
48+
],
49+
# Write child stdout to the log file
50+
stdout=log_file,
51+
# Merge stderr into stdout for a single, ordered log stream
52+
stderr=subprocess.STDOUT,
53+
)
54+
except FileNotFoundError:
55+
print("::error::pwsh not found on PATH; cannot start disk cleanup.")
56+
return 1
57+
58+
pid_file.write_text(str(proc.pid))
59+
print(
60+
f"::notice file={__file__}::Started free-disk-space cleanup in background. "
61+
f"pid={proc.pid}; log_file: {log_file_path}; pid_file: {pid_file}"
62+
)
63+
return 0
64+
65+
66+
if __name__ == "__main__":
67+
sys.exit(main())
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Wait for the background Windows disk cleanup process started by
3+
free-disk-space-windows-start.py, then print the full log.
4+
"""
5+
6+
import os
7+
import sys
8+
import time
9+
import ctypes
10+
from pathlib import Path
11+
12+
13+
# Get the temporary directory set by GitHub Actions
14+
def get_temp_dir() -> Path:
15+
return Path(os.environ.get("RUNNER_TEMP"))
16+
17+
18+
def is_process_running(pid: int) -> bool:
19+
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 # Sufficient for GetExitCodeProcess
20+
processHandle = ctypes.windll.kernel32.OpenProcess(
21+
PROCESS_QUERY_LIMITED_INFORMATION, 0, pid
22+
)
23+
if processHandle == 0:
24+
# Could be not running or we don't have sufficient rights to check
25+
return False
26+
else:
27+
ctypes.windll.kernel32.CloseHandle(processHandle)
28+
return True
29+
30+
31+
def main() -> int:
32+
temp_dir = get_temp_dir()
33+
pid_file = temp_dir / "free-disk-space.pid"
34+
log_file = temp_dir / "free-disk-space.log"
35+
36+
if not pid_file.exists():
37+
print("::notice::No background free-disk-space process to wait for.")
38+
return 0
39+
40+
try:
41+
pid = int(pid_file.read_text().strip().splitlines()[0])
42+
except Exception:
43+
# Delete the file if it exists
44+
pid_file.unlink(missing_ok=True)
45+
return 0
46+
47+
# Poll until process exits
48+
while is_process_running(pid):
49+
time.sleep(3)
50+
51+
# Delete the file if it exists
52+
pid_file.unlink(missing_ok=True)
53+
54+
if log_file.exists():
55+
print("free-disk-space logs:")
56+
# Print entire log; replace undecodable bytes to avoid exceptions.
57+
try:
58+
with open(log_file, "r", encoding="utf-8", errors="replace") as f:
59+
print(f.read())
60+
except Exception as e:
61+
print(f"::warning::Failed to read log file '{log_file}': {e}")
62+
return 0
63+
64+
65+
if __name__ == "__main__":
66+
sys.exit(main())

src/ci/scripts/free-disk-space.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -euo pipefail
44
script_dir=$(dirname "$0")
55

66
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
7-
pwsh $script_dir/free-disk-space-windows.ps1
7+
python3 "$script_dir/free-disk-space-windows-start.py"
88
else
99
$script_dir/free-disk-space-linux.sh
1010
fi

0 commit comments

Comments
 (0)