@riddledc/riddle-proof 0.5.27 → 0.5.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/runtime/lib/preflight.py
CHANGED
|
@@ -42,6 +42,7 @@ with open(args_file) as f:
|
|
|
42
42
|
|
|
43
43
|
mode = (s.get('mode') or '').strip().lower()
|
|
44
44
|
reference = s.get('reference', 'both')
|
|
45
|
+
requested_reference = reference
|
|
45
46
|
reference_note = ''
|
|
46
47
|
verification_mode = (s.get('verification_mode') or 'proof').strip() or 'proof'
|
|
47
48
|
s['verification_mode'] = verification_mode
|
|
@@ -68,6 +69,15 @@ if discord_url_match:
|
|
|
68
69
|
if reference not in ('prod', 'before', 'both'):
|
|
69
70
|
raise SystemExit('Invalid reference: ' + reference + '. Must be prod, before, or both.')
|
|
70
71
|
s['reference'] = reference
|
|
72
|
+
prod_url_present = bool((s.get('prod_url') or '').strip())
|
|
73
|
+
s['reference_resolution'] = {
|
|
74
|
+
'requested_reference': requested_reference,
|
|
75
|
+
'effective_reference': reference,
|
|
76
|
+
'prod_reference_requested': requested_reference in ('prod', 'both'),
|
|
77
|
+
'prod_url_present': prod_url_present,
|
|
78
|
+
'prod_reference_skipped': False,
|
|
79
|
+
'prod_reference_skip_reason': '',
|
|
80
|
+
}
|
|
71
81
|
|
|
72
82
|
# Infer a reasonable commit title during setup instead of forcing the caller to
|
|
73
83
|
# fill boilerplate that can be derived from the requested change.
|
|
@@ -77,11 +87,17 @@ if not (s.get('commit_message') or '').strip():
|
|
|
77
87
|
# Setup should not block on a missing production URL. If prod comparison was
|
|
78
88
|
# requested but prod_url is not known yet, continue with a before-only setup so
|
|
79
89
|
# the repo homework can happen first.
|
|
80
|
-
if reference in ('prod', 'both') and not
|
|
90
|
+
if reference in ('prod', 'both') and not prod_url_present:
|
|
81
91
|
s['requested_reference'] = reference
|
|
82
92
|
reference = 'before'
|
|
83
93
|
s['reference'] = reference
|
|
84
94
|
reference_note = 'prod_url not provided; setup will continue with reference=before until prod is known.'
|
|
95
|
+
s['reference_resolution'].update({
|
|
96
|
+
'effective_reference': reference,
|
|
97
|
+
'prod_reference_skipped': True,
|
|
98
|
+
'prod_reference_skip_reason': 'prod_url_not_provided',
|
|
99
|
+
'note': reference_note,
|
|
100
|
+
})
|
|
85
101
|
|
|
86
102
|
# Parse optional assertions JSON
|
|
87
103
|
parsed_assertions = None
|
package/runtime/lib/ship.py
CHANGED
|
@@ -82,6 +82,24 @@ def git_stdout(args, repo_dir, timeout=30):
|
|
|
82
82
|
return result.stdout.strip()
|
|
83
83
|
|
|
84
84
|
|
|
85
|
+
def git_checked(args, repo_dir, timeout=120):
|
|
86
|
+
result = sp.run(['git'] + args, cwd=repo_dir, capture_output=True, text=True, timeout=timeout)
|
|
87
|
+
if result.returncode != 0:
|
|
88
|
+
raise SystemExit('git ' + ' '.join(args) + ' failed: ' + (result.stderr or result.stdout)[:300])
|
|
89
|
+
return result
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def gh_pr_create_args(title, body, branch):
|
|
93
|
+
return [
|
|
94
|
+
'gh', 'pr', 'create',
|
|
95
|
+
'--draft',
|
|
96
|
+
'--title', str(title or '').strip() or 'Riddle Proof change',
|
|
97
|
+
'--body', str(body or ''),
|
|
98
|
+
'--base', 'main',
|
|
99
|
+
'--head', str(branch or ''),
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
|
|
85
103
|
def remote_branch_head(repo_dir, branch):
|
|
86
104
|
result = sp.run(['git', 'ls-remote', 'origin', 'refs/heads/' + branch], cwd=repo_dir, capture_output=True, text=True, timeout=60)
|
|
87
105
|
if result.returncode != 0:
|
|
@@ -623,11 +641,11 @@ if lines:
|
|
|
623
641
|
print('Only ship-noise paths changed; skipping commit.')
|
|
624
642
|
if s.get('pr_url'):
|
|
625
643
|
if staged_paths:
|
|
626
|
-
|
|
644
|
+
git_checked(['commit', '--amend', '--no-edit'], after_dir)
|
|
627
645
|
push, push_info = push_existing_pr_branch(after_dir, branch, push_target)
|
|
628
646
|
else:
|
|
629
647
|
if staged_paths:
|
|
630
|
-
|
|
648
|
+
git_checked(['commit', '-m', s['commit_message']], after_dir)
|
|
631
649
|
push = sp.run(
|
|
632
650
|
['git', 'push', 'origin', push_target],
|
|
633
651
|
cwd=after_dir,
|
|
@@ -657,8 +675,8 @@ else:
|
|
|
657
675
|
|
|
658
676
|
# Create PR if needed
|
|
659
677
|
if not s.get('pr_url'):
|
|
660
|
-
q = sp.run('gh pr list --head
|
|
661
|
-
|
|
678
|
+
q = sp.run(['gh', 'pr', 'list', '--head', branch, '--json', 'url,number', '-q', '.[0]'],
|
|
679
|
+
cwd=repo_dir, capture_output=True, text=True)
|
|
662
680
|
pr_url = ''
|
|
663
681
|
if q.stdout.strip():
|
|
664
682
|
try:
|
|
@@ -667,10 +685,10 @@ if not s.get('pr_url'):
|
|
|
667
685
|
except:
|
|
668
686
|
pass
|
|
669
687
|
if not pr_url:
|
|
670
|
-
c = sp.run('
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
688
|
+
c = sp.run(gh_pr_create_args(s.get('commit_message', ''), s.get('change_request', ''), branch),
|
|
689
|
+
cwd=repo_dir, capture_output=True, text=True)
|
|
690
|
+
if c.returncode != 0:
|
|
691
|
+
raise SystemExit('Failed to create PR: ' + (c.stderr or c.stdout)[:500])
|
|
674
692
|
pr_url = c.stdout.strip().splitlines()[-1].strip() if c.returncode == 0 else ''
|
|
675
693
|
s['pr_url'] = pr_url
|
|
676
694
|
s['pr_number'] = pr_url.rstrip('/').split('/')[-1] if pr_url else ''
|
|
@@ -11,6 +11,7 @@ from pathlib import Path
|
|
|
11
11
|
ROOT = Path(__file__).resolve().parents[1]
|
|
12
12
|
LIB = ROOT / 'lib'
|
|
13
13
|
UTIL_PATH = LIB / 'util.py'
|
|
14
|
+
PREFLIGHT_PATH = LIB / 'preflight.py'
|
|
14
15
|
RECON_PATH = LIB / 'recon.py'
|
|
15
16
|
VERIFY_PATH = LIB / 'verify.py'
|
|
16
17
|
AUTHOR_PATH = LIB / 'author.py'
|
|
@@ -593,6 +594,49 @@ def temporary_env(**updates):
|
|
|
593
594
|
os.environ[key] = value
|
|
594
595
|
|
|
595
596
|
|
|
597
|
+
def run_preflight_records_prod_reference_skip_reason():
|
|
598
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-preflight-reference-'))
|
|
599
|
+
args_path = tempdir / 'args.json'
|
|
600
|
+
state_path = tempdir / 'state.json'
|
|
601
|
+
repo_dir = tempdir / 'repo'
|
|
602
|
+
try:
|
|
603
|
+
make_project(repo_dir, "export const routes = [{ path: '/pricing', element: <Pricing /> }];\n")
|
|
604
|
+
args_path.write_text(json.dumps({
|
|
605
|
+
'repo': 'example/repo',
|
|
606
|
+
'repo_dir': str(repo_dir),
|
|
607
|
+
'mode': 'static',
|
|
608
|
+
'reference': 'both',
|
|
609
|
+
'prod_url': '',
|
|
610
|
+
'change_request': 'Make the pricing CTA clearer',
|
|
611
|
+
'commit_message': 'Make the pricing CTA clearer',
|
|
612
|
+
'success_criteria': 'Pricing CTA is visible.',
|
|
613
|
+
'verification_mode': 'text',
|
|
614
|
+
'build_command': BUILD_SCRIPT,
|
|
615
|
+
'build_output': 'build',
|
|
616
|
+
'allow_static_preview_fallback': True,
|
|
617
|
+
'server_path': '/pricing',
|
|
618
|
+
}, indent=2))
|
|
619
|
+
with temporary_env(
|
|
620
|
+
RIDDLE_PROOF_ARGS_FILE=str(args_path),
|
|
621
|
+
RIDDLE_PROOF_STATE_FILE=str(state_path),
|
|
622
|
+
):
|
|
623
|
+
load_module('util_preflight_reference_skip', UTIL_PATH)
|
|
624
|
+
load_module('preflight_reference_skip', PREFLIGHT_PATH)
|
|
625
|
+
after_preflight = json.loads(state_path.read_text())
|
|
626
|
+
assert after_preflight['requested_reference'] == 'both'
|
|
627
|
+
assert after_preflight['reference'] == 'before'
|
|
628
|
+
assert after_preflight['reference_resolution']['requested_reference'] == 'both'
|
|
629
|
+
assert after_preflight['reference_resolution']['effective_reference'] == 'before'
|
|
630
|
+
assert after_preflight['reference_resolution']['prod_reference_skipped'] is True
|
|
631
|
+
assert after_preflight['reference_resolution']['prod_reference_skip_reason'] == 'prod_url_not_provided'
|
|
632
|
+
return {
|
|
633
|
+
'ok': True,
|
|
634
|
+
'reference_resolution': after_preflight['reference_resolution'],
|
|
635
|
+
}
|
|
636
|
+
finally:
|
|
637
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
638
|
+
|
|
639
|
+
|
|
596
640
|
def base_state(tempdir: Path, *, reference='before', prod_url=''):
|
|
597
641
|
before_dir = tempdir / 'before'
|
|
598
642
|
after_dir = tempdir / 'after'
|
|
@@ -1646,6 +1690,42 @@ def run_ship_filters_tool_noise_when_staging():
|
|
|
1646
1690
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
1647
1691
|
|
|
1648
1692
|
|
|
1693
|
+
def run_ship_preserves_literal_backticks_in_args():
|
|
1694
|
+
sys.modules.pop('util', None)
|
|
1695
|
+
source = SHIP_PATH.read_text()
|
|
1696
|
+
helpers_source = source.split('\ns = load_state()', 1)[0]
|
|
1697
|
+
namespace = {'__file__': str(SHIP_PATH)}
|
|
1698
|
+
exec(compile(helpers_source, str(SHIP_PATH), 'exec'), namespace)
|
|
1699
|
+
|
|
1700
|
+
title = 'Change button from `Start Run` to `Launch Run`'
|
|
1701
|
+
body = 'Proof request keeps `Start Run` and `Launch Run` literal.'
|
|
1702
|
+
args = namespace['gh_pr_create_args'](title, body, 'agent/test-backticks')
|
|
1703
|
+
assert args[0:3] == ['gh', 'pr', 'create'], args
|
|
1704
|
+
assert args[args.index('--title') + 1] == title, args
|
|
1705
|
+
assert args[args.index('--body') + 1] == body, args
|
|
1706
|
+
|
|
1707
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-ship-backticks-'))
|
|
1708
|
+
try:
|
|
1709
|
+
sp.run(['git', 'init', '-b', 'main'], cwd=tempdir, check=True, capture_output=True, text=True)
|
|
1710
|
+
sp.run(['git', 'config', 'user.email', 'test@example.com'], cwd=tempdir, check=True)
|
|
1711
|
+
sp.run(['git', 'config', 'user.name', 'Test User'], cwd=tempdir, check=True)
|
|
1712
|
+
(tempdir / 'tracked.txt').write_text('literal backticks\n')
|
|
1713
|
+
sp.run(['git', 'add', 'tracked.txt'], cwd=tempdir, check=True)
|
|
1714
|
+
|
|
1715
|
+
namespace['git_checked'](['commit', '-m', title], str(tempdir))
|
|
1716
|
+
subject = sp.run(
|
|
1717
|
+
['git', 'log', '-1', '--pretty=%s'],
|
|
1718
|
+
cwd=tempdir,
|
|
1719
|
+
check=True,
|
|
1720
|
+
capture_output=True,
|
|
1721
|
+
text=True,
|
|
1722
|
+
).stdout.strip()
|
|
1723
|
+
assert subject == title, subject
|
|
1724
|
+
return {'ok': True, 'subject': subject}
|
|
1725
|
+
finally:
|
|
1726
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
1727
|
+
|
|
1728
|
+
|
|
1649
1729
|
def run_ship_resolves_real_pr_branch():
|
|
1650
1730
|
sys.modules.pop('util', None)
|
|
1651
1731
|
source = SHIP_PATH.read_text()
|
|
@@ -1704,6 +1784,7 @@ def run_ship_resolves_real_pr_branch():
|
|
|
1704
1784
|
|
|
1705
1785
|
if __name__ == '__main__':
|
|
1706
1786
|
payload = {
|
|
1787
|
+
'preflight_reference_skip_reason': run_preflight_records_prod_reference_skip_reason(),
|
|
1707
1788
|
'capture_artifact_enrichment': run_capture_artifact_enrichment(),
|
|
1708
1789
|
'capture_diagnostics_redaction': run_capture_diagnostics_redact_sensitive_values(),
|
|
1709
1790
|
'apply_auth_context': run_apply_auth_context_passes_supported_auth_payloads(),
|
|
@@ -1728,6 +1809,7 @@ if __name__ == '__main__':
|
|
|
1728
1809
|
'ship_structured_after_evidence': run_ship_accepts_structured_after_evidence(),
|
|
1729
1810
|
'ship_discord_thread_target': run_ship_discord_thread_target(),
|
|
1730
1811
|
'ship_filters_tool_noise_when_staging': run_ship_filters_tool_noise_when_staging(),
|
|
1812
|
+
'ship_preserves_literal_backticks_in_args': run_ship_preserves_literal_backticks_in_args(),
|
|
1731
1813
|
'ship_resolves_real_pr_branch': run_ship_resolves_real_pr_branch(),
|
|
1732
1814
|
}
|
|
1733
1815
|
print(json.dumps(payload, indent=2))
|