refactor(artifacts): harmonize Windows to Linux raw-file collection
Windows produced an intermediate C:\CI\output\artifacts.zip that upload-artifact then re-zipped (zip-in-zip), while Linux deposited raw files. Make both paths consistent: the build stages raw outputs into a collect dir; collect zips it only as a transport archive, fetches, and extracts into the host artifact dir; actions/upload-artifact produces the single final archive. - _windows_build: param artifact_zip -> output_dir; stage raw files (in-place when source IS the collect dir, else wipe+copy), no Compress-Archive; absolute artifact-source resolved. - _windows_collect: zip guest dir as transport, fetch, extract (mirror _linux_collect); guest_path is now the collect directory. - job.py / build_run CLI: pass output_dir; rename --guest-artifact-zip -> --guest-output-dir. - Tests updated for the raw-file contract. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ import json
|
||||
import shlex
|
||||
import tarfile
|
||||
import tempfile
|
||||
import zipfile
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
@@ -133,19 +134,44 @@ def _windows_collect(
|
||||
include_logs: bool,
|
||||
) -> None:
|
||||
cred = KeyringCredentialStore().get(credential_target)
|
||||
remote_zip = "C:\\CI\\ci-artifacts-transfer.zip"
|
||||
with WinRmTransport(ip_address, cred.username, cred.password) as t:
|
||||
# Verify artifact exists.
|
||||
# guest_path is the collect directory (raw build outputs).
|
||||
# Verify it exists and is non-empty.
|
||||
probe = t.run(
|
||||
f"if (Test-Path {_ps_quote(guest_path)}) {{ 'OK' }} else {{ 'MISSING' }}",
|
||||
f"if ((Test-Path {_ps_quote(guest_path)}) -and "
|
||||
f"(Get-ChildItem -Force -- {_ps_quote(guest_path)})) "
|
||||
f"{{ 'OK' }} else {{ 'MISSING' }}",
|
||||
check=False,
|
||||
)
|
||||
if "MISSING" in probe.stdout:
|
||||
raise click.ClickException(f"artifact not found in guest: {guest_path}")
|
||||
raise click.ClickException(
|
||||
f"artifact not found or empty in guest: {guest_path}"
|
||||
)
|
||||
|
||||
artifact_name = Path(guest_path).name
|
||||
host_dest = host_dir / artifact_name
|
||||
click.echo(f"[artifacts collect] fetching {artifact_name}")
|
||||
t.fetch(guest_path, str(host_dest))
|
||||
# Zip the directory contents as a single transport file, fetch,
|
||||
# extract into host_dir. Mirrors the Linux tar flow so both OSes
|
||||
# deposit raw files; the final single archive is produced by
|
||||
# actions/upload-artifact (no zip-in-zip).
|
||||
t.run(
|
||||
f"if (Test-Path {_ps_quote(remote_zip)}) "
|
||||
f"{{ Remove-Item {_ps_quote(remote_zip)} -Force }}; "
|
||||
f"Compress-Archive -Path (Join-Path {_ps_quote(guest_path)} '*') "
|
||||
f"-DestinationPath {_ps_quote(remote_zip)} -Force"
|
||||
)
|
||||
click.echo(f"[artifacts collect] fetching artifacts from {guest_path}")
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
local_zip = Path(td) / "artifacts.zip"
|
||||
t.fetch(remote_zip, str(local_zip))
|
||||
with zipfile.ZipFile(local_zip) as zf:
|
||||
zf.extractall(host_dir)
|
||||
finally:
|
||||
t.run(
|
||||
f"Remove-Item {_ps_quote(remote_zip)} -Force "
|
||||
f"-ErrorAction SilentlyContinue",
|
||||
check=False,
|
||||
)
|
||||
|
||||
if include_logs:
|
||||
# List log files in the build dir and fetch each one.
|
||||
@@ -169,9 +195,9 @@ def _windows_collect(
|
||||
err=True,
|
||||
)
|
||||
|
||||
if not host_dest.is_file() or host_dest.stat().st_size == 0:
|
||||
if not any(host_dir.iterdir()):
|
||||
raise click.ClickException(
|
||||
f"artifact missing or empty after fetch: {host_dest}"
|
||||
f"no artifacts after collect from guest: {guest_path}"
|
||||
)
|
||||
|
||||
|
||||
@@ -190,7 +216,7 @@ def _windows_collect(
|
||||
"--guest-artifact-path",
|
||||
"guest_artifact_path",
|
||||
required=True,
|
||||
help="Guest path: file (Windows) or directory (Linux).",
|
||||
help="Guest collect directory (Windows and Linux).",
|
||||
)
|
||||
@click.option(
|
||||
"--host-artifact-dir",
|
||||
|
||||
Reference in New Issue
Block a user