ci: clean windows disk space in background
This commit is contained in:
parent
a1531335fe
commit
75b7d24a98
5 changed files with 184 additions and 1 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
|
@ -223,6 +223,11 @@ jobs:
|
|||
cd src/ci/citool
|
||||
CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=../../../build/citool cargo build
|
||||
|
||||
- name: wait for Windows disk cleanup to finish
|
||||
if: ${{ matrix.free_disk && startsWith(matrix.os, 'windows-') }}
|
||||
run: |
|
||||
python3 src/ci/scripts/free-disk-space-windows-wait.py
|
||||
|
||||
- name: run the build
|
||||
run: |
|
||||
set +e
|
||||
|
|
|
|||
72
src/ci/scripts/free-disk-space-windows-start.py
Normal file
72
src/ci/scripts/free-disk-space-windows-start.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
"""
|
||||
Start freeing disk space on Windows in the background by launching
|
||||
the PowerShell cleanup script, and recording the PID in a file,
|
||||
so later steps can wait for completion.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from free_disk_space_windows_util import get_pid_file, get_log_file, run_main
|
||||
|
||||
|
||||
def get_cleanup_script() -> Path:
|
||||
script_dir = Path(__file__).resolve().parent
|
||||
cleanup_script = script_dir / "free-disk-space-windows.ps1"
|
||||
if not cleanup_script.exists():
|
||||
raise Exception(f"Cleanup script '{cleanup_script}' not found")
|
||||
return cleanup_script
|
||||
|
||||
|
||||
def write_pid(pid: int):
|
||||
pid_file = get_pid_file()
|
||||
if pid_file.exists():
|
||||
raise Exception(f"Pid file '{pid_file}' already exists")
|
||||
pid_file.write_text(str(pid))
|
||||
print(f"wrote pid {pid} in file {pid_file}")
|
||||
|
||||
|
||||
def launch_cleanup_process():
|
||||
cleanup_script = get_cleanup_script()
|
||||
log_file_path = get_log_file()
|
||||
# Launch the PowerShell cleanup in the background and redirect logs.
|
||||
try:
|
||||
with open(log_file_path, "w", encoding="utf-8") as log_file:
|
||||
proc = subprocess.Popen(
|
||||
[
|
||||
"pwsh",
|
||||
# Suppress PowerShell startup banner/logo for cleaner logs.
|
||||
"-NoLogo",
|
||||
# Don't load user/system profiles. Ensures a clean, predictable environment.
|
||||
"-NoProfile",
|
||||
# Disable interactive prompts. Required for CI to avoid hangs.
|
||||
"-NonInteractive",
|
||||
# Execute the specified script file (next argument).
|
||||
"-File",
|
||||
str(cleanup_script),
|
||||
],
|
||||
# Write child stdout to the log file.
|
||||
stdout=log_file,
|
||||
# Merge stderr into stdout for a single, ordered log stream.
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
print(
|
||||
f"Started free-disk-space cleanup in background. "
|
||||
f"pid={proc.pid}; log_file={log_file_path}"
|
||||
)
|
||||
return proc
|
||||
except FileNotFoundError as e:
|
||||
raise Exception("pwsh not found on PATH; cannot start disk cleanup.") from e
|
||||
|
||||
|
||||
def main() -> int:
|
||||
proc = launch_cleanup_process()
|
||||
|
||||
# Write pid of the process to a file, so that later steps can read it and wait
|
||||
# until the process completes.
|
||||
write_pid(proc.pid)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_main(main)
|
||||
77
src/ci/scripts/free-disk-space-windows-wait.py
Normal file
77
src/ci/scripts/free-disk-space-windows-wait.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
"""
|
||||
Wait for the background Windows disk cleanup process.
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import time
|
||||
from free_disk_space_windows_util import get_pid_file, get_log_file, run_main
|
||||
|
||||
|
||||
def is_process_running(pid: int) -> bool:
|
||||
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
|
||||
processHandle = ctypes.windll.kernel32.OpenProcess(
|
||||
PROCESS_QUERY_LIMITED_INFORMATION, 0, pid
|
||||
)
|
||||
if processHandle == 0:
|
||||
# The process is not running.
|
||||
# If you don't have the sufficient rights to check if a process is running,
|
||||
# zero is also returned. But in GitHub Actions we have these rights.
|
||||
return False
|
||||
else:
|
||||
ctypes.windll.kernel32.CloseHandle(processHandle)
|
||||
return True
|
||||
|
||||
|
||||
def print_logs():
|
||||
"""Print the logs from the cleanup script."""
|
||||
log_file = get_log_file()
|
||||
if log_file.exists():
|
||||
print("free-disk-space logs:")
|
||||
# Print entire log; replace undecodable bytes to avoid exceptions.
|
||||
try:
|
||||
with open(log_file, "r", encoding="utf-8", errors="replace") as f:
|
||||
print(f.read())
|
||||
except Exception as e:
|
||||
raise Exception(f"Failed to read log file '{log_file}'") from e
|
||||
else:
|
||||
print(f"::warning::Log file '{log_file}' not found")
|
||||
|
||||
|
||||
def read_pid_from_file() -> int:
|
||||
"""Read the PID from the pid file."""
|
||||
|
||||
pid_file = get_pid_file()
|
||||
if not pid_file.exists():
|
||||
raise Exception(
|
||||
f"No background free-disk-space process to wait for: pid file {pid_file} not found"
|
||||
)
|
||||
|
||||
pid_file_content = pid_file.read_text().strip()
|
||||
|
||||
# Delete the file if it exists
|
||||
pid_file.unlink(missing_ok=True)
|
||||
|
||||
try:
|
||||
# Read the first line and convert to int.
|
||||
pid = int(pid_file_content.splitlines()[0])
|
||||
return pid
|
||||
except Exception as e:
|
||||
raise Exception(
|
||||
f"Error while parsing the pid file with content '{pid_file_content!r}'"
|
||||
) from e
|
||||
|
||||
|
||||
def main() -> int:
|
||||
pid = read_pid_from_file()
|
||||
|
||||
# Poll until process exits
|
||||
while is_process_running(pid):
|
||||
time.sleep(3)
|
||||
|
||||
print_logs()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_main(main)
|
||||
|
|
@ -4,7 +4,7 @@ set -euo pipefail
|
|||
script_dir=$(dirname "$0")
|
||||
|
||||
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
|
||||
pwsh $script_dir/free-disk-space-windows.ps1
|
||||
python3 "$script_dir/free-disk-space-windows-start.py"
|
||||
else
|
||||
$script_dir/free-disk-space-linux.sh
|
||||
fi
|
||||
|
|
|
|||
29
src/ci/scripts/free_disk_space_windows_util.py
Normal file
29
src/ci/scripts/free_disk_space_windows_util.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
"""
|
||||
Utilities for Windows disk space cleanup scripts.
|
||||
"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
|
||||
def get_temp_dir() -> Path:
|
||||
"""Get the temporary directory set by GitHub Actions."""
|
||||
return Path(os.environ.get("RUNNER_TEMP"))
|
||||
|
||||
|
||||
def get_pid_file() -> Path:
|
||||
return get_temp_dir() / "free-disk-space.pid"
|
||||
|
||||
|
||||
def get_log_file() -> Path:
|
||||
return get_temp_dir() / "free-disk-space.log"
|
||||
|
||||
|
||||
def run_main(main_fn):
|
||||
exit_code = 1
|
||||
try:
|
||||
exit_code = main_fn()
|
||||
except Exception as e:
|
||||
print(f"::error::{e}")
|
||||
sys.exit(exit_code)
|
||||
Loading…
Add table
Add a link
Reference in a new issue