Skip to content

Commit bc86016

Browse files
authored
Merge pull request #130 from GetTechAPI/ci/collect-patch-artifact
ci(collect): upload the commit as a patch instead of pushing a PR
2 parents dc6d07e + b094049 commit bc86016

7 files changed

Lines changed: 180 additions & 117 deletions

File tree

‎.github/workflows/ingest.yml‎

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
name: ingest
22

3-
# Reusable, manual PR generator (ADR-017). Only TechAPI's collect.yml calls it,
4-
# from workflow_dispatch, so github.token is TechAPI's GITHUB_TOKEN and the
5-
# branch and PR come from github-actions[bot]. Nothing here runs on a schedule,
6-
# posts a comment, or uses a personal or bot-account token. Crawlers send the
7-
# honest TechEngine-* User-Agent and keep their --sleep and limits.
3+
# Reusable, manual change generator (ADR-017). Only TechAPI's collect.yml calls
4+
# it, from workflow_dispatch, with a read-only token. The run commits locally,
5+
# gates the result and uploads the commit as collect.patch; a maintainer opens
6+
# the PR from their own account with TechAPI's .github/scripts/open-collect-pr.sh.
7+
# Nothing here pushes, opens a PR, posts a comment, runs on a schedule, or uses
8+
# a personal or bot-account token. Crawlers send the honest TechEngine-*
9+
# User-Agent and keep their --sleep and limits.
810
#
911
# Task: scrape upstream catalogs and draft missing SKUs into TechAPI data/.
1012
on:
@@ -24,8 +26,7 @@ on:
2426
default: false
2527

2628
permissions:
27-
contents: write
28-
pull-requests: write
29+
contents: read
2930

3031
concurrency:
3132
group: collect-ingest-${{ inputs.category }}
@@ -39,7 +40,6 @@ jobs:
3940
CATEGORY: ${{ inputs.category }}
4041
LIMIT: ${{ inputs.limit }}
4142
INCLUDE_DRAFTS: ${{ inputs.include_drafts }}
42-
DRAFT_FLAG: ${{ inputs.include_drafts && '--draft' || '' }}
4343
BRANCH: collect/ingest-${{ inputs.category }}
4444
TITLE: "feat(data/${{ inputs.category }}): ingest new SKUs"
4545
TECHAPI_DATA_DIR: ${{ github.workspace }}/TechAPI/data
@@ -55,7 +55,7 @@ jobs:
5555
submodules: true
5656
# The Tier 0 diff compares the new commit with develop's tip only.
5757
fetch-depth: 1
58-
# The write token is handed to the push step alone.
58+
# Nothing in this job pushes.
5959
persist-credentials: false
6060

6161
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
@@ -112,7 +112,7 @@ jobs:
112112
set -euo pipefail
113113
git add data/
114114
if git diff --cached --quiet; then
115-
echo "No data changes; no PR."
115+
echo "No data changes; no patch."
116116
echo "changed=false" >> "$GITHUB_OUTPUT"
117117
exit 0
118118
fi
@@ -123,8 +123,8 @@ jobs:
123123
git commit -q -m "$TITLE"
124124
echo "changed=true" >> "$GITHUB_OUTPUT"
125125
126-
# Gate: a PR opened with GITHUB_TOKEN triggers no checks, so the gate runs
127-
# here and its result goes in the PR body. Any failure stops the push.
126+
# Gate: the result goes in the PR body. Any failure stops the run before
127+
# the patch is uploaded.
128128
- name: Gate (app.validate + integrity_check --strict)
129129
if: steps.commit.outputs.changed == 'true'
130130
working-directory: TechAPI/TechEngine
@@ -143,8 +143,8 @@ jobs:
143143
> "$GITHUB_WORKSPACE/verify-report.md" 2>&1 \
144144
|| echo "_Tier 0 report unavailable._" > "$GITHUB_WORKSPACE/verify-report.md"
145145
146-
# github-actions[bot] writes the body, so scraped text must not mention
147-
# anyone or cross-reference an issue: drop "@", break "#123"/"GH-123" and
146+
# The body carries scraped text, which must not mention anyone or
147+
# cross-reference an issue: drop "@", break "#123"/"GH-123" and
148148
# URLs with a zero-width space. Colours such as #3fb950 are untouched.
149149
- name: Build PR body
150150
if: steps.commit.outputs.changed == 'true'
@@ -187,26 +187,46 @@ jobs:
187187
Path("pr-body.md").write_text(body, encoding="utf-8")
188188
PY
189189
190-
# One open PR per task: the fixed branch is cut from develop and
191-
# force-pushed each run; an open PR is edited in place. No comments.
192-
- name: Push and open or update the PR
190+
# The token is read-only, so the commit leaves the run as a patch. A
191+
# maintainer opens the PR from their own account with TechAPI's
192+
# .github/scripts/open-collect-pr.sh <run-id>, so the PR's checks run.
193+
- name: Export the commit as collect.patch
193194
if: steps.commit.outputs.changed == 'true'
194-
working-directory: TechAPI
195195
env:
196-
GH_TOKEN: ${{ github.token }}
196+
BASE: ${{ steps.commit.outputs.base }}
197+
DRAFT: ${{ inputs.include_drafts }}
197198
run: |
198199
set -euo pipefail
199-
auth=$(printf 'x-access-token:%s' "$GH_TOKEN" | base64 -w0)
200-
git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic $auth" \
201-
push --force origin "HEAD:refs/heads/$BRANCH"
202-
number=$(gh pr list --repo GetTechAPI/TechAPI --head "$BRANCH" --base develop \
203-
--state open --json number --jq '.[0].number // empty')
204-
if [ -n "$number" ]; then
205-
gh pr edit "$number" --repo GetTechAPI/TechAPI --title "$TITLE" --body-file ../pr-body.md
206-
else
207-
gh pr create --repo GetTechAPI/TechAPI --base develop --head "$BRANCH" \
208-
--title "$TITLE" --body-file ../pr-body.md $DRAFT_FLAG \
209-
--assignee Seungpyo1007 --assignee TechEngineBot \
210-
--label data --label enhancement \
211-
--milestone "Massive dataset rebuild (1989-2026)"
200+
outside=$(git -C TechAPI diff --no-renames --name-only "$BASE" HEAD | grep -v '^data/' || true)
201+
if [ -n "$outside" ]; then
202+
echo "::error::The commit touches files outside data/:"
203+
echo "$outside"
204+
exit 1
212205
fi
206+
git -C TechAPI format-patch -1 --base="$BASE" --stdout HEAD > collect.patch
207+
python - <<'PY'
208+
import json
209+
import os
210+
meta = {
211+
"branch": os.environ["BRANCH"],
212+
"title": os.environ["TITLE"],
213+
"draft": os.environ.get("DRAFT") == "true",
214+
"base": os.environ["BASE"],
215+
}
216+
with open("pr.json", "w", encoding="utf-8") as f:
217+
json.dump(meta, f, indent=2)
218+
f.write("\n")
219+
PY
220+
cat pr-body.md >> "$GITHUB_STEP_SUMMARY"
221+
222+
- name: Upload collect.patch
223+
if: steps.commit.outputs.changed == 'true'
224+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
225+
with:
226+
name: collect-ingest-${{ inputs.category }}
227+
path: |
228+
collect.patch
229+
pr-body.md
230+
pr.json
231+
if-no-files-found: error
232+
retention-days: 14

‎.github/workflows/refresh.yml‎

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
name: refresh
22

3-
# Reusable, manual PR generator (ADR-017). Only TechAPI's collect.yml calls it,
4-
# from workflow_dispatch, so github.token is TechAPI's GITHUB_TOKEN and the
5-
# branch and PR come from github-actions[bot]. Nothing here runs on a schedule,
6-
# posts a comment, or uses a personal or bot-account token. Crawlers send the
7-
# honest TechEngine-* User-Agent and keep their --sleep and limits.
3+
# Reusable, manual change generator (ADR-017). Only TechAPI's collect.yml calls
4+
# it, from workflow_dispatch, with a read-only token. The run commits locally,
5+
# gates the result and uploads the commit as collect.patch; a maintainer opens
6+
# the PR from their own account with TechAPI's .github/scripts/open-collect-pr.sh.
7+
# Nothing here pushes, opens a PR, posts a comment, runs on a schedule, or uses
8+
# a personal or bot-account token. Crawlers send the honest TechEngine-*
9+
# User-Agent and keep their --sleep and limits.
810
#
911
# Task: re-scrape benchmark sources into TechAPI data/. No dump: TechAPI builds
1012
# the static API at deploy time, so the commit holds data/ only.
@@ -17,8 +19,7 @@ on:
1719
default: "1.0"
1820

1921
permissions:
20-
contents: write
21-
pull-requests: write
22+
contents: read
2223

2324
concurrency:
2425
group: collect-refresh
@@ -32,7 +33,6 @@ jobs:
3233
timeout-minutes: 330
3334
env:
3435
SLEEP: ${{ inputs.sleep }}
35-
DRAFT_FLAG: ""
3636
BRANCH: collect/refresh
3737
TITLE: "chore(data): refresh benchmark data"
3838
TECHAPI_DATA_DIR: ${{ github.workspace }}/TechAPI/data
@@ -48,7 +48,7 @@ jobs:
4848
submodules: true
4949
# The Tier 0 diff compares the new commit with develop's tip only.
5050
fetch-depth: 1
51-
# The write token is handed to the push step alone.
51+
# Nothing in this job pushes.
5252
persist-credentials: false
5353

5454
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
@@ -129,7 +129,7 @@ jobs:
129129
set -euo pipefail
130130
git add data/
131131
if git diff --cached --quiet; then
132-
echo "No data changes; no PR."
132+
echo "No data changes; no patch."
133133
echo "changed=false" >> "$GITHUB_OUTPUT"
134134
exit 0
135135
fi
@@ -140,8 +140,8 @@ jobs:
140140
git commit -q -m "$TITLE"
141141
echo "changed=true" >> "$GITHUB_OUTPUT"
142142
143-
# Gate: a PR opened with GITHUB_TOKEN triggers no checks, so the gate runs
144-
# here and its result goes in the PR body. Any failure stops the push.
143+
# Gate: the result goes in the PR body. Any failure stops the run before
144+
# the patch is uploaded.
145145
- name: Gate (app.validate + integrity_check --strict)
146146
if: steps.commit.outputs.changed == 'true'
147147
working-directory: TechAPI/TechEngine
@@ -160,8 +160,8 @@ jobs:
160160
> "$GITHUB_WORKSPACE/verify-report.md" 2>&1 \
161161
|| echo "_Tier 0 report unavailable._" > "$GITHUB_WORKSPACE/verify-report.md"
162162
163-
# github-actions[bot] writes the body, so scraped text must not mention
164-
# anyone or cross-reference an issue: drop "@", break "#123"/"GH-123" and
163+
# The body carries scraped text, which must not mention anyone or
164+
# cross-reference an issue: drop "@", break "#123"/"GH-123" and
165165
# URLs with a zero-width space. Colours such as #3fb950 are untouched.
166166
- name: Build PR body
167167
if: steps.commit.outputs.changed == 'true'
@@ -205,26 +205,45 @@ jobs:
205205
Path("pr-body.md").write_text(body, encoding="utf-8")
206206
PY
207207
208-
# One open PR per task: the fixed branch is cut from develop and
209-
# force-pushed each run; an open PR is edited in place. No comments.
210-
- name: Push and open or update the PR
208+
# The token is read-only, so the commit leaves the run as a patch. A
209+
# maintainer opens the PR from their own account with TechAPI's
210+
# .github/scripts/open-collect-pr.sh <run-id>, so the PR's checks run.
211+
- name: Export the commit as collect.patch
211212
if: steps.commit.outputs.changed == 'true'
212-
working-directory: TechAPI
213213
env:
214-
GH_TOKEN: ${{ github.token }}
214+
BASE: ${{ steps.commit.outputs.base }}
215215
run: |
216216
set -euo pipefail
217-
auth=$(printf 'x-access-token:%s' "$GH_TOKEN" | base64 -w0)
218-
git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic $auth" \
219-
push --force origin "HEAD:refs/heads/$BRANCH"
220-
number=$(gh pr list --repo GetTechAPI/TechAPI --head "$BRANCH" --base develop \
221-
--state open --json number --jq '.[0].number // empty')
222-
if [ -n "$number" ]; then
223-
gh pr edit "$number" --repo GetTechAPI/TechAPI --title "$TITLE" --body-file ../pr-body.md
224-
else
225-
gh pr create --repo GetTechAPI/TechAPI --base develop --head "$BRANCH" \
226-
--title "$TITLE" --body-file ../pr-body.md $DRAFT_FLAG \
227-
--assignee Seungpyo1007 --assignee TechEngineBot \
228-
--label data --label enhancement \
229-
--milestone "Massive dataset rebuild (1989-2026)"
217+
outside=$(git -C TechAPI diff --no-renames --name-only "$BASE" HEAD | grep -v '^data/' || true)
218+
if [ -n "$outside" ]; then
219+
echo "::error::The commit touches files outside data/:"
220+
echo "$outside"
221+
exit 1
230222
fi
223+
git -C TechAPI format-patch -1 --base="$BASE" --stdout HEAD > collect.patch
224+
python - <<'PY'
225+
import json
226+
import os
227+
meta = {
228+
"branch": os.environ["BRANCH"],
229+
"title": os.environ["TITLE"],
230+
"draft": os.environ.get("DRAFT") == "true",
231+
"base": os.environ["BASE"],
232+
}
233+
with open("pr.json", "w", encoding="utf-8") as f:
234+
json.dump(meta, f, indent=2)
235+
f.write("\n")
236+
PY
237+
cat pr-body.md >> "$GITHUB_STEP_SUMMARY"
238+
239+
- name: Upload collect.patch
240+
if: steps.commit.outputs.changed == 'true'
241+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
242+
with:
243+
name: collect-refresh
244+
path: |
245+
collect.patch
246+
pr-body.md
247+
pr.json
248+
if-no-files-found: error
249+
retention-days: 14

0 commit comments

Comments
 (0)