fix: hold the pipeline's fixed outputs for a run

The pipeline locked only --output-dir while it also writes database.json,
install/, README.md and docs/. A run on a scratch output directory could
start beside the run on dist/ and rewrite them. Every run now holds the
repository's .lock first.
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 09:53:15 +02:00
1 parent 43337c6719
commit 12cc71b634
5 files changed
+75 -8

No files matched your search

+27
View File
@@ -217,6 +217,33 @@ def hold_artifact_lock(directory: str) -> Iterator[None]:
else:
os.environ[HELD_LOCK_ENV] = previous
# What a pipeline run writes at fixed paths, whatever its --output-dir.
REPOSITORY_OUTPUTS = ("database.json", "install/", "README.md", "CONTRIBUTING.md", "docs/")
@contextlib.contextmanager
def hold_repository_outputs(root: str = ".") -> Iterator[None]:
"""Hold the outputs a pipeline writes at fixed paths, for the whole run.
The output-directory lock let a run on tmp/packtest start beside a run
on dist/: both rewrote database.json, and the second to reach the
manifest step found install/ held after minutes of work, or, when the
steps did not overlap, rewrote the committed manifests from its own
state. The lock file is the repository root's .lock.
"""
stack = contextlib.ExitStack()
try:
stack.enter_context(artifact_lock(root))
except ArtifactLockBusy as exc:
raise ArtifactLockBusy(
f"another pipeline run is writing {', '.join(REPOSITORY_OUTPUTS)} "
f"(lock: {os.path.join(root, '.lock')}). Wait for it to finish."
) from exc
with stack:
yield
def _build_timestamp(db: dict | None = None) -> str:
"""Timestamp for generated artifacts.
+1
View File
@@ -2810,6 +2810,7 @@ from artifacts import ( # noqa: E402,F401
ArtifactLockBusy,
artifact_lock,
hold_artifact_lock,
hold_repository_outputs,
_TIMESTAMP_PATTERNS,
_strip_timestamps,
)
+13 -5
View File
@@ -68,6 +68,7 @@ from common import (
artifact_lock,
github_token,
hold_artifact_lock,
hold_repository_outputs,
load_data_dir_registry,
)
from refresh_data_dirs import hold_data_dirs
@@ -700,13 +701,20 @@ def main() -> None:
# hold lasts until this process exits: taken step by step, it let another
# run purge the packs between the build and the integrity check, which
# then reported every platform SKIP and passed.
# database.json, install/, README.md and docs/ sit at fixed paths, so
# every run holds them too: a run on a scratch --output-dir otherwise
# rewrote them beside the run on dist/.
held = contextlib.ExitStack()
if not args.skip_packs:
try:
try:
held.enter_context(
hold_repository_outputs(str(Path(__file__).resolve().parent.parent))
)
if not args.skip_packs:
held.enter_context(hold_artifact_lock(args.output_dir))
except ArtifactLockBusy as exc:
print(f"ERROR: {exc}", file=sys.stderr)
sys.exit(1)
except ArtifactLockBusy as exc:
held.close()
print(f"ERROR: {exc}", file=sys.stderr)
sys.exit(1)
all_ok = True
total_start = time.monotonic()