Skip to content

Commit 2434d72

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

File tree

4 files changed

+134
-1
lines changed

4 files changed

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