Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions scripts/stage-release-bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,35 @@ cp \
"$source_root/.dockerignore" \
"$destination/"

# Promotion manifests hash-bind an eligibility policy that lives under docs/,
# which is otherwise outside the staged tree. A bundle has to contain every
# artifact its manifests bind or freeze-manifest cannot canonicalize them, so
# copy exactly those files. Not all of docs/: that also carries node_modules
# and build output, which bloats the bundle and gives the analyzer a large
# unrelated tree to index.
promotion_root="$source_root/benchmarks/promotion"
if [[ -d "$promotion_root" ]]; then
bound_list="$(mktemp)"
trap 'rm -f "$bound_list"' EXIT
find "$promotion_root" -type f -name '*.json' -print | sort | while IFS= read -r promotion_manifest; do
jq -r '.. | objects | select(has("file")) | .file' "$promotion_manifest"
done | sort -u | grep -Ev '^(benchmarks|fixtures|adapters|schema|src|containers|scripts)/' > "$bound_list" || true
while IFS= read -r bound_artifact; do
[[ -n "$bound_artifact" ]] || continue
[[ "$bound_artifact" != /* && "$bound_artifact" != *..* ]] || {
echo "promotion manifest binds an unsafe artifact path: $bound_artifact" >&2
exit 1
}
[[ -f "$source_root/$bound_artifact" ]] || {
echo "promotion manifest binds a missing artifact: $bound_artifact" >&2
exit 1
}
mkdir -p "$destination/$(dirname "$bound_artifact")"
cp -- "$source_root/$bound_artifact" "$destination/$bound_artifact"
echo "staged bound promotion artifact: $bound_artifact"
done < "$bound_list"
fi

jq -n \
--arg releaseTag "$release_tag" \
--arg releaseVersion "${release_tag#v}" \
Expand Down
47 changes: 47 additions & 0 deletions tests/test_freeze_shards.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,53 @@ def test_ruby_lsp_native_shard_provisions_ruby_three_four_keg(self):
self.assertNotIn('brew list ruby >/dev/null', workflow)
self.assertNotIn('ruby\\ 3\\.[4-9]', workflow)

def test_release_bundle_stages_every_artifact_a_promotion_manifest_binds(self):
"""A bundle must contain what its manifests hash-bind.

The v0.3.1 freeze reached aggregation and failed on `canonicalize
promotion artifact docs/legacy-promotion-selection-policy.md`: the
legacy manifest binds an eligibility policy under docs/, and the
staging step copies benchmarks, fixtures, adapters, schema, src,
containers, and scripts but not docs.
"""

staging = (ROOT / "scripts/stage-release-bundle.sh").read_text()
# Derived from the manifests rather than a hardcoded docs/ path, so a
# newly bound artifact is staged without editing this script.
self.assertIn(
"jq -r '.. | objects | select(has(\"file\")) | .file' \"$promotion_manifest\"",
staging,
)
self.assertIn('cp -- "$source_root/$bound_artifact" "$destination/$bound_artifact"', staging)
# All of docs/ would drag in node_modules and build output.
self.assertNotIn('"$source_root/docs" \\', staging)

promotion_root = ROOT / "benchmarks/promotion"
staged_prefixes = (
"benchmarks/", "fixtures/", "adapters/", "schema/", "src/",
"containers/", "scripts/",
)
bound = set()

def walk(node):
if isinstance(node, dict):
value = node.get("file")
if isinstance(value, str):
bound.add(value)
for child in node.values():
walk(child)
elif isinstance(node, list):
for child in node:
walk(child)

for manifest in sorted(promotion_root.rglob("*.json")):
walk(json.loads(manifest.read_text()))
outside = sorted(p for p in bound if not p.startswith(staged_prefixes))
# Every such artifact must exist, or the freeze fails at aggregation.
for relative in outside:
self.assertTrue((ROOT / relative).is_file(), f"bound artifact missing: {relative}")
self.assertIn("docs/legacy-promotion-selection-policy.md", outside)

def test_legacy_scope_is_bound_to_the_110_case_manifest(self):
scope = subprocess.run(
[ROOT / "scripts/resolve-freeze-scope.sh", "legacy-promoted"],
Expand Down