fix(build): Linux artifact staging — absolute source + don't wipe output
Two bugs made the Linux smoke "succeed" with an empty artifact: - artifact_source was always joined as workdir + '/' + src, so an absolute source (/opt/ci/output) became /opt/ci/build//opt/ci/output and was never found — only a non-fatal WARNING was logged. - `rm -rf output_dir` ran unconditionally; when the build writes directly into the collect dir (the smoke case: output == source), it deleted the build output before collection. Resolve absolute vs workdir-relative; when the source is the output dir, collect in place without wiping; a missing/empty source is now a hard failure instead of a silent empty artifact. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -180,17 +180,40 @@ def _linux_build(
|
|||||||
click.echo("[build run] artifact packaging skipped (--skip-artifact).")
|
click.echo("[build run] artifact packaging skipped (--skip-artifact).")
|
||||||
return
|
return
|
||||||
|
|
||||||
t.run(f"rm -rf {_sh_quote(output_dir)} && mkdir -p {_sh_quote(output_dir)}")
|
# Resolve the artifact source: absolute path as-is, else relative
|
||||||
|
# to the build workdir. (artifact_source may be absolute, e.g.
|
||||||
|
# /opt/ci/output; the old `workdir + '/' + src` produced
|
||||||
|
# /opt/ci/build//opt/ci/output and silently found nothing.)
|
||||||
src = artifact_source or "dist"
|
src = artifact_source or "dist"
|
||||||
cp_cmd = (
|
srcpath = src.rstrip("/") if src.startswith("/") else workdir.rstrip("/") + "/" + src
|
||||||
f"if [ -d {_sh_quote(workdir + '/' + src)} ]; then "
|
out = output_dir.rstrip("/")
|
||||||
f"cp -r {_sh_quote(workdir + '/' + src + '/.')} {_sh_quote(output_dir + '/')}; "
|
|
||||||
f"elif [ -e {_sh_quote(workdir + '/' + src)} ]; then "
|
if srcpath == out or srcpath.startswith(out + "/"):
|
||||||
f"cp {_sh_quote(workdir + '/' + src)} {_sh_quote(output_dir + '/')}; "
|
# The build wrote directly into the collect dir; do NOT wipe it
|
||||||
f"else echo '[build run] WARNING: artifact source not found: {src}' >&2; fi"
|
# (that deleted the build output) and nothing to copy. Fail
|
||||||
)
|
# loudly if it is missing or empty rather than collecting an
|
||||||
t.run(cp_cmd)
|
# empty artifact.
|
||||||
click.echo(f"[build run] artifact staged at {output_dir}")
|
click.echo(
|
||||||
|
f"[build run] artifact source is the output dir ({out}); collecting in place"
|
||||||
|
)
|
||||||
|
t.run(
|
||||||
|
f"if [ ! -d {_sh_quote(out)} ] || "
|
||||||
|
f'[ -z "$(ls -A {_sh_quote(out)} 2>/dev/null)" ]; then '
|
||||||
|
f"echo '[build run] artifact source not found or empty: {out}' >&2; "
|
||||||
|
f"exit 1; fi"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
t.run(f"rm -rf {_sh_quote(out)} && mkdir -p {_sh_quote(out)}")
|
||||||
|
cp_cmd = (
|
||||||
|
f"if [ -d {_sh_quote(srcpath)} ]; then "
|
||||||
|
f"cp -r {_sh_quote(srcpath + '/.')} {_sh_quote(out + '/')}; "
|
||||||
|
f"elif [ -e {_sh_quote(srcpath)} ]; then "
|
||||||
|
f"cp {_sh_quote(srcpath)} {_sh_quote(out + '/')}; "
|
||||||
|
f"else echo '[build run] artifact source not found: {srcpath}' >&2; "
|
||||||
|
f"exit 1; fi"
|
||||||
|
)
|
||||||
|
t.run(cp_cmd)
|
||||||
|
click.echo(f"[build run] artifact staged at {out}")
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------- Windows flow
|
# ---------------------------------------------------------------- Windows flow
|
||||||
|
|||||||
Reference in New Issue
Block a user