diff --git a/src/ci_orchestrator/commands/build.py b/src/ci_orchestrator/commands/build.py index 0b44650..28581b1 100644 --- a/src/ci_orchestrator/commands/build.py +++ b/src/ci_orchestrator/commands/build.py @@ -180,17 +180,40 @@ def _linux_build( click.echo("[build run] artifact packaging skipped (--skip-artifact).") 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" - cp_cmd = ( - f"if [ -d {_sh_quote(workdir + '/' + src)} ]; then " - f"cp -r {_sh_quote(workdir + '/' + src + '/.')} {_sh_quote(output_dir + '/')}; " - f"elif [ -e {_sh_quote(workdir + '/' + src)} ]; then " - f"cp {_sh_quote(workdir + '/' + src)} {_sh_quote(output_dir + '/')}; " - f"else echo '[build run] WARNING: artifact source not found: {src}' >&2; fi" - ) - t.run(cp_cmd) - click.echo(f"[build run] artifact staged at {output_dir}") + srcpath = src.rstrip("/") if src.startswith("/") else workdir.rstrip("/") + "/" + src + out = output_dir.rstrip("/") + + if srcpath == out or srcpath.startswith(out + "/"): + # The build wrote directly into the collect dir; do NOT wipe it + # (that deleted the build output) and nothing to copy. Fail + # loudly if it is missing or empty rather than collecting an + # empty artifact. + 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