Skip to content

Commit dacc817

Browse files
committed
ci(verify): route Tier 0 analysis to a TechEngineBot PR comment
Reworks how verification surfaces on PRs so TechEngineBot owns the analysis, instead of TechAPI running its own (failing) job: - Remove the self-run verify-offline job from validate-data.yml. It failed because the stdlib-only CI image has no pytest, and having TechAPI score its own PRs duplicated what the bot should own. validate-data.yml is back to the pure structural gate. - Add verify-report.yml: runs `app.verify score` (changed records + full baseline) and has TechEngineBot post the band histogram as a PR comment via ENGINE_TOKEN. Dormant if the token is unset; same-repo PRs only; never gates a merge; updates one marked comment in place. - Add app/verify/** to request-engine-pr-validation paths so the engine's PR validation (and its TechEngineBot comment) also covers verifier changes. Refs #1
1 parent c4303e1 commit dacc817

3 files changed

Lines changed: 100 additions & 26 deletions

File tree

.github/workflows/request-engine-pr-validation.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ on:
1717
- "site/package.json"
1818
- "site/package-lock.json"
1919
- "app/validate.py"
20+
- "app/verify/**"
2021
workflow_dispatch:
2122
inputs:
2223
pr_number:

.github/workflows/validate-data.yml

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@ on:
77
paths:
88
- "data/**"
99
- "app/validate.py"
10-
- "app/verify/**"
11-
- "tests/verify/**"
1210
push:
1311
branches: [main]
1412
paths:
1513
- "data/**"
1614
- "app/validate.py"
17-
- "app/verify/**"
18-
- "tests/verify/**"
1915

2016
jobs:
2117
self-validate:
@@ -28,28 +24,6 @@ jobs:
2824
- name: Self-check (bundled validator)
2925
run: python -m app.validate
3026

31-
# Non-blocking existence/trust signal: scores the records changed in this PR
32-
# with the Tier 0 offline verifier and prints a band histogram. Informational
33-
# only — never gates the merge (continue-on-error).
34-
verify-offline:
35-
runs-on: ubuntu-latest
36-
continue-on-error: true
37-
env:
38-
PYTHONIOENCODING: utf-8
39-
steps:
40-
- uses: actions/checkout@v4
41-
with:
42-
fetch-depth: 0
43-
- uses: actions/setup-python@v5
44-
with:
45-
python-version: "3.12"
46-
- name: Tier 0 verification report (changed records)
47-
run: |
48-
git fetch origin main --depth=1 || true
49-
python -m app.verify score --changed --no-cache
50-
- name: Verifier unit tests
51-
run: python -m pytest tests/verify -q -m "not slow"
52-
5327
engine-validate:
5428
needs: self-validate
5529
uses: GetTechAPI/TechEngine/.github/workflows/validate-data.yml@main
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: verify-report
2+
3+
# Run the Tier 0 offline data *verification* (existence/trust scoring) on a PR and
4+
# let TechEngineBot post the band analysis as a PR comment. The bot owns the
5+
# analysis surface: this workflow only computes the report and hands it to the bot
6+
# (the comment is authored via the bot's token). It never gates a merge.
7+
#
8+
# Dormant unless ENGINE_TOKEN (TechEngineBot's PAT) is configured. Restricted to
9+
# same-repo branch PRs so fork PRs never see the token. The structural gate stays
10+
# in validate-data.yml; this is purely informational.
11+
on:
12+
pull_request:
13+
types: [opened, synchronize, reopened, ready_for_review]
14+
paths:
15+
- "data/**"
16+
- "app/validate.py"
17+
- "app/verify/**"
18+
19+
permissions:
20+
contents: read
21+
pull-requests: write
22+
23+
concurrency:
24+
group: verify-report-${{ github.event.pull_request.number }}
25+
cancel-in-progress: true
26+
27+
jobs:
28+
verify-report:
29+
runs-on: ubuntu-latest
30+
if: github.event.pull_request.head.repo.full_name == github.repository
31+
env:
32+
PYTHONIOENCODING: utf-8
33+
ENGINE_TOKEN: ${{ secrets.ENGINE_TOKEN }}
34+
steps:
35+
- name: Dormant when ENGINE_TOKEN is unset
36+
if: env.ENGINE_TOKEN == ''
37+
run: echo "::warning::ENGINE_TOKEN not configured — TechEngineBot verify comment skipped."
38+
39+
- uses: actions/checkout@v4
40+
if: env.ENGINE_TOKEN != ''
41+
with:
42+
fetch-depth: 0
43+
44+
- uses: actions/setup-python@v5
45+
if: env.ENGINE_TOKEN != ''
46+
with:
47+
python-version: "3.12"
48+
49+
- name: Tier 0 verification (changed + full baseline)
50+
if: env.ENGINE_TOKEN != ''
51+
id: verify
52+
run: |
53+
git fetch origin main --depth=1 || true
54+
{
55+
echo 'report<<VERIFY_EOF'
56+
echo "### Changed records in this PR"
57+
python -m app.verify score --changed --no-cache
58+
echo ""
59+
echo "### Full-dataset baseline"
60+
python -m app.verify score --no-cache
61+
echo VERIFY_EOF
62+
} >> "$GITHUB_OUTPUT"
63+
64+
- name: TechEngineBot posts the verification analysis
65+
if: env.ENGINE_TOKEN != ''
66+
uses: actions/github-script@v7
67+
env:
68+
REPORT: ${{ steps.verify.outputs.report }}
69+
with:
70+
github-token: ${{ secrets.ENGINE_TOKEN }}
71+
script: |
72+
const marker = '<!-- techengine-verify-report -->';
73+
const report = (process.env.REPORT || '').trim() || '(no output)';
74+
const body = [
75+
marker,
76+
'## 🔎 Data verification — Tier 0 (offline existence/trust)',
77+
'',
78+
'Scored by `app.verify`; posted by **TechEngineBot**. Informational only —',
79+
'the structural gate (`app.validate`) is separate and authoritative for merge.',
80+
'',
81+
'```text',
82+
report,
83+
'```',
84+
'',
85+
'<sub>green = authoritative source + complete + consistent · '
86+
+ 'yellow = plausible, needs confirmation · red = sparse/weak source or a hard contradiction. '
87+
+ 'Promotion to `verified` runs in the scheduled `verify-network` workflow.</sub>',
88+
].join('\n');
89+
const { owner, repo } = context.repo;
90+
const issue_number = context.payload.pull_request.number;
91+
const comments = await github.paginate(github.rest.issues.listComments, {
92+
owner, repo, issue_number, per_page: 100,
93+
});
94+
const existing = comments.find((c) => c.body && c.body.includes(marker));
95+
if (existing) {
96+
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
97+
} else {
98+
await github.rest.issues.createComment({ owner, repo, issue_number, body });
99+
}

0 commit comments

Comments
 (0)