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
8 changes: 4 additions & 4 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
inputs.effect-utils.inputs.nixpkgs.url = "github:NixOS/nixpkgs/4ba99f3209788ed04f01af38f77ddb803ad6ec63";
inputs.effect-utils.inputs.tsgo.inputs.nixpkgsUnstable.url = "github:NixOS/nixpkgs/44a91898084f46797b5fac650c7e8c9ac38c43d4";
inputs.fractal-fixture = {
url = "github:compoundingtech/fractal/e83871ec919f95b3b3e2a9a1cd211c2ac37babda";
url = "github:compoundingtech/fractal/e2721e52463428b4ff655addee129cecd2839763";
flake = false;
};
inputs.python-oracle = {
Expand Down
5 changes: 5 additions & 0 deletions scripts/PROVENANCE
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
# resync-blob scripts/fractal-test-report-test b0dc50163986760343d7eb67c701cb4b775e9945
# resync-blob scripts/lane-definition-closure 492b3741b117092395855d9790dc96e6ce3612e6
# resync-blob scripts/lane-definition-closure-test 635945d2a01f18e9c4716c50a2eb9803896cbb08
# resync-blob scripts/evidence-flip-ready ce94216c0435711419e1b2bc5acc996e2ac926b9
# resync-blob scripts/evidence-flip-ready-test 16e505355c4092c880c3f5e283baa8c0996cea4b
# resync-blob scripts/evidence-verify-test 08d11cc7ba5e8a3d5ffb59fadb9eb49238aec95f
# resync-blob scripts/st-test 087ae7d9f3d1106a38eedc1e911caeeaf46a96ae
# resync-blob scripts/fractal-test-test decb42b9d442807c9601b473c190b3743b24c4c0
# scripts/fractal-test-test: apply the fixture maintenance-isolation patch from
# https://github.com/compoundingtech/fractal/pull/4398 (5f995f26e5).
# The source_blob column remains the original import; mergemaster_blob includes applied patches.
Expand Down
23 changes: 22 additions & 1 deletion scripts/ci-evidence-gate
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ VERIFIER_TIMEOUT = int(os.environ.get('GATE_VERIFIER_TIMEOUT', '30'))
# A change that touches anything that decides a skip is not skipped on a note alone: those files are what a forged skip would
# have to edit. Compared between the accepted base and this run's tree. One exception (decide): a pull_request run covered by a note
# of one of OWN_LEVELS, our dev hosts, which ran the PR's own scripts. It is judged by THIS gate and verifier as the base has them
# (the workflow fetches both from BASE_SHA), never the PR's copies, and the merge queue runs every check in full before it lands.
# (the workflow fetches both from BASE_SHA), never the PR's copies. Merge groups reuse only exact-tree evidence enabled at BASE.
PROTECTED = (
'scripts/ci-evidence-gate', 'scripts/evidence-verify', '.st/evidence-skip-policy.json', '.st/evidence-keys',
'.github/workflows/fleet.yml', '.github/workflows/fleet.yml.genie.ts', '.github/workflows/workspace-ci.ts',
Expand Down Expand Up @@ -158,6 +158,11 @@ def decide(context, outcome, result, tree):
return 'run', 'event does not allow skipping'
if context.get('tree_of') == 'head' and context['event'] != 'pull_request':
return 'run', 'a head-tree note covers pull request runs only'
if context['event'] == 'merge_group':
if context.get('merge_group_mode') != 'same-tree':
return 'run', 'merge-group tree reuse is not enabled at the accepted base'
if result.get('match') != 'tree':
return 'run', 'merge groups require exact-tree evidence, not input-key reuse'
protected = context.get('protected_changed')
if protected != [] and not (own_pull_request(context, result) and isinstance(protected, list)
and all(isinstance(p, str) and p and not p.startswith('<') for p in protected)):
Expand Down Expand Up @@ -190,6 +195,20 @@ def own_pull_request(context, result):
return context['event'] == 'pull_request' and result.get('trust_level') in OWN_LEVELS


def merge_group_mode(context):
"""Queue reuse is opt-in at BASE; absent, malformed or unknown modes keep hosted CI running."""
path = config_path(context['base'], SIGNED_ONLY)
if path is None:
return None
shown = run('git', 'show', f"{context['base']}:{path}")
if shown.returncode != 0:
return None
try:
return json.loads(shown.stdout).get('merge_group')
except (ValueError, AttributeError):
return None


def signed_only(context):
"""Whether this opener is signed-only, using the accepted base's selected layout.

Expand Down Expand Up @@ -736,6 +755,8 @@ def main():
except Exception:
context['protected_changed'] = ['<comparison failed>']
try:
if context['event'] == 'merge_group':
context['merge_group_mode'] = merge_group_mode(context)
decision, why = decide(context, outcome, result, tree)
except Exception:
decision, why = 'run', 'decision error'
Expand Down
Loading