Studio: bootstrap install-script allowlist on PR that introduces it
The previous commit tightened the install-script gate so a PR cannot add new allowlist entries on its own head branch -- they must already exist on the base ref. That created a chicken-and-egg problem for the very PR that introduces studio/frontend/.install-script-allowlist: base does not have the file yet, so every head entry is "new" and the gate refuses to land. Resolve by making the head-only rejection conditional on the base ref actually having the allowlist file. The workflow signals "missing on base" by removing the temp file after a failed git show (previously it was always truncated to empty, which the checker could not distinguish from an empty-by-intent base). The checker treats a missing base allowlist path as bootstrap mode and accepts the head allowlist as-is for that single run. Once the file exists on base, every subsequent PR is back under the strict head-only rejection rule.
This commit is contained in:
parent
c3c09dbd80
commit
b21717120c
2 changed files with 49 additions and 20 deletions
13
.github/workflows/security-audit.yml
vendored
13
.github/workflows/security-audit.yml
vendored
|
|
@ -1105,10 +1105,15 @@ jobs:
|
||||||
> /tmp/base-package-lock.json
|
> /tmp/base-package-lock.json
|
||||||
# Pull the TRUSTED allowlist from the base ref so a PR cannot
|
# Pull the TRUSTED allowlist from the base ref so a PR cannot
|
||||||
# allowlist its own new postinstall dependency in the same diff
|
# allowlist its own new postinstall dependency in the same diff
|
||||||
# the checker scans. Missing file is OK (empty allowlist).
|
# the checker scans. If the file does NOT exist on base, REMOVE
|
||||||
git show "$BASE_SHA:studio/frontend/.install-script-allowlist" \
|
# the temp file -- the checker treats a missing base allowlist
|
||||||
> /tmp/base-install-script-allowlist 2>/dev/null \
|
# as bootstrap mode (the PR that introduces the file is allowed
|
||||||
|| : > /tmp/base-install-script-allowlist
|
# to populate it; once it lands, subsequent PRs must respect
|
||||||
|
# the head-only rejection rule).
|
||||||
|
if ! git show "$BASE_SHA:studio/frontend/.install-script-allowlist" \
|
||||||
|
> /tmp/base-install-script-allowlist 2>/dev/null; then
|
||||||
|
rm -f /tmp/base-install-script-allowlist
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Diff for newly-added install-script deps
|
- name: Diff for newly-added install-script deps
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
|
|
|
||||||
|
|
@ -328,28 +328,52 @@ def main(argv: list[str] | None = None) -> int:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
head_allowlist = _load_allowlist(head_allowlist_path)
|
head_allowlist = _load_allowlist(head_allowlist_path)
|
||||||
base_allowlist = _load_allowlist(base_allowlist_path)
|
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
print(f"[install-script-diff] ERROR: {exc}", file = sys.stderr)
|
print(f"[install-script-diff] ERROR: {exc}", file = sys.stderr)
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
# Refuse a PR that adds new allowlist entries on its own head branch.
|
# Bootstrap: if the BASE ref has no allowlist file at all, this is
|
||||||
# Allowlist deltas must land in a separate, trusted commit on base
|
# the PR that creates it. There is no prior allowlist to diff
|
||||||
# first; otherwise the same PR could approve its own postinstall.
|
# against, and refusing every head entry here would make the gate
|
||||||
added_head_only = sorted(head_allowlist - base_allowlist)
|
# unlandable. The workflow signals "missing on base" by NOT writing
|
||||||
if added_head_only:
|
# the temp file (rm -f after a failed ``git show``), which is what
|
||||||
|
# we detect here. Once the file exists on base, future PRs must
|
||||||
|
# land allowlist deltas there first.
|
||||||
|
if not base_allowlist_path.exists():
|
||||||
print(
|
print(
|
||||||
"[install-script-diff] FAIL: install-script allowlist entries "
|
f"[install-script-diff] bootstrap: {base_allowlist_path} "
|
||||||
"must already exist on the base branch; do not let a PR "
|
"missing on base; accepting head allowlist as-is for this run.",
|
||||||
"allowlist its own new postinstall dependency.",
|
flush = True,
|
||||||
file = sys.stderr,
|
|
||||||
)
|
)
|
||||||
for entry in added_head_only:
|
allowlist = head_allowlist
|
||||||
print(f" head-only allowlist entry: {entry}", file = sys.stderr)
|
else:
|
||||||
return 1
|
try:
|
||||||
|
base_allowlist = _load_allowlist(base_allowlist_path)
|
||||||
|
except ValueError as exc:
|
||||||
|
print(f"[install-script-diff] ERROR: {exc}", file = sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
# Only the trusted base allowlist participates in the skip set.
|
# Refuse a PR that adds new allowlist entries on its own head
|
||||||
allowlist = base_allowlist
|
# branch. Allowlist deltas must land in a separate trusted
|
||||||
|
# commit on base first; otherwise the same PR could approve
|
||||||
|
# its own postinstall dependency.
|
||||||
|
added_head_only = sorted(head_allowlist - base_allowlist)
|
||||||
|
if added_head_only:
|
||||||
|
print(
|
||||||
|
"[install-script-diff] FAIL: install-script allowlist "
|
||||||
|
"entries must already exist on the base branch; do not "
|
||||||
|
"let a PR allowlist its own new postinstall dependency.",
|
||||||
|
file = sys.stderr,
|
||||||
|
)
|
||||||
|
for entry in added_head_only:
|
||||||
|
print(
|
||||||
|
f" head-only allowlist entry: {entry}",
|
||||||
|
file = sys.stderr,
|
||||||
|
)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Only the trusted base allowlist participates in the skip set.
|
||||||
|
allowlist = base_allowlist
|
||||||
|
|
||||||
findings = diff_new_install_scripts(base_lock, head_lock)
|
findings = diff_new_install_scripts(base_lock, head_lock)
|
||||||
if allowlist:
|
if allowlist:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue