mirror of
https://github.com/Heretek-AI/awesome-opencode.git
synced 2026-11-07 10:45:57 -10:00
ci: publish the README through a self-merging bot PR
GitHub rulesets reject direct pushes while a status check is required, even when the pushed commit's check passed (verified: GH013 'Required status check "validate" is expected' on a commit with a successful validate run). The README workflow now opens a PR from bot/readme-<sha>, dispatches validate on it and squash-merges it once green; older bot README PRs are closed as superseded. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
7c166ab68f
commit
bf926fecc8
2 files changed
+53
-50
No files matched your search
@@ -10,10 +10,12 @@ on:
|
|||||||
- 'scripts/**'
|
- 'scripts/**'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
# main requires a passing "validate" check on every commit, so the regenerated README is first pushed
|
# main requires a passing "validate" check, which rulesets only accept through a pull request merge.
|
||||||
# to a bot/readme-* branch, validated there, and then fast-forwarded onto main.
|
# The regenerated README therefore goes through a bot PR: branch bot/readme-<sha>, validate dispatched on
|
||||||
|
# it, then squash-merged by this job once the check passes.
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
actions: write
|
actions: write
|
||||||
checks: read
|
checks: read
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v7
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.ref }}
|
ref: main
|
||||||
# Full history: "Recently added" is derived from when each entry file was first committed
|
# Full history: "Recently added" is derived from when each entry file was first committed
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
@@ -43,7 +45,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci --ignore-scripts
|
run: npm ci --ignore-scripts
|
||||||
|
|
||||||
- name: Generate, validate and publish README/registry
|
- name: Generate, validate and merge README/registry
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
@@ -52,50 +54,51 @@ jobs:
|
|||||||
git config user.name "github-actions[bot]"
|
git config user.name "github-actions[bot]"
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
for attempt in 1 2 3 4 5; do
|
# Close bot README PRs left open by earlier failed runs; this run supersedes them
|
||||||
echo "Generation attempt ${attempt}"
|
for old in $(gh pr list --state open --search "head:bot/readme-" --json number,headRefName \
|
||||||
git fetch origin main
|
--jq '.[] | select(.headRefName | startswith("bot/readme-")) | .number'); do
|
||||||
git reset --hard origin/main
|
gh pr close "$old" --delete-branch --comment "Superseded by a newer README regeneration." || true
|
||||||
|
|
||||||
# Both scripts validate the whole catalog and exit non-zero without writing on any error
|
|
||||||
node scripts/generate-readme.js
|
|
||||||
node scripts/export-json.js --pretty --output dist/registry.json
|
|
||||||
|
|
||||||
if git diff --quiet -- README.md dist/registry.json; then
|
|
||||||
echo "README.md and dist/registry.json are already current."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
git add README.md dist/registry.json
|
|
||||||
git commit -m "docs: auto-regenerate README and registry data"
|
|
||||||
sha="$(git rev-parse HEAD)"
|
|
||||||
branch="bot/readme-${sha:0:12}"
|
|
||||||
|
|
||||||
# Stage the commit and run the required "validate" check on it
|
|
||||||
git push --force origin "HEAD:refs/heads/${branch}"
|
|
||||||
gh workflow run validate-pr.yml --ref "${branch}"
|
|
||||||
conclusion=""
|
|
||||||
for i in $(seq 1 60); do
|
|
||||||
sleep 10
|
|
||||||
conclusion="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${sha}/check-runs?check_name=validate" \
|
|
||||||
--jq '[.check_runs[] | select(.status == "completed") | .conclusion][0] // ""')"
|
|
||||||
[ -n "${conclusion}" ] && break
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "${conclusion}" != "success" ]; then
|
|
||||||
git push origin --delete "${branch}" || true
|
|
||||||
echo "validate on ${sha} finished with '${conclusion:-timeout}'; not publishing" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if git push origin "${sha}:refs/heads/main"; then
|
|
||||||
git push origin --delete "${branch}" || true
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
git push origin --delete "${branch}" || true
|
|
||||||
echo "main moved while validating; retrying..."
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "Failed to publish regenerated README/registry after retries" >&2
|
# Both scripts validate the whole catalog and exit non-zero without writing on any error
|
||||||
|
node scripts/generate-readme.js
|
||||||
|
node scripts/export-json.js --pretty --output dist/registry.json
|
||||||
|
|
||||||
|
if git diff --quiet -- README.md dist/registry.json; then
|
||||||
|
echo "README.md and dist/registry.json are already current."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git add README.md dist/registry.json
|
||||||
|
git commit -m "docs: auto-regenerate README and registry data"
|
||||||
|
sha="$(git rev-parse HEAD)"
|
||||||
|
branch="bot/readme-${sha:0:12}"
|
||||||
|
git push --force origin "HEAD:refs/heads/${branch}"
|
||||||
|
|
||||||
|
pr="$(gh pr create --base main --head "${branch}" \
|
||||||
|
--title "docs: auto-regenerate README and registry data" \
|
||||||
|
--body "Automated by \`generate-readme.yml\` after ${GITHUB_SHA:0:12}. Merged automatically once \`validate\` passes.")"
|
||||||
|
echo "Opened ${pr}"
|
||||||
|
|
||||||
|
gh workflow run validate-pr.yml --ref "${branch}"
|
||||||
|
conclusion=""
|
||||||
|
for i in $(seq 1 60); do
|
||||||
|
sleep 10
|
||||||
|
conclusion="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${sha}/check-runs?check_name=validate" \
|
||||||
|
--jq '[.check_runs[] | select(.status == "completed") | .conclusion][0] // ""')"
|
||||||
|
[ -n "${conclusion}" ] && break
|
||||||
|
done
|
||||||
|
if [ "${conclusion}" != "success" ]; then
|
||||||
|
echo "validate on ${sha} finished with '${conclusion:-timeout}'; leaving ${pr} open for a maintainer" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The required check can take a moment to register on the PR
|
||||||
|
for i in 1 2 3 4 5 6; do
|
||||||
|
if gh pr merge "${pr}" --squash --delete-branch --subject "docs: auto-regenerate README and registry data"; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
echo "Could not merge ${pr}; leaving it open for a maintainer" >&2
|
||||||
exit 1
|
exit 1
|
||||||
+2
-2
@@ -51,7 +51,7 @@ A weekly scout searches npm for packages published since V2 shipped that depend
|
|||||||
|
|
||||||
## Branch protection
|
## Branch protection
|
||||||
|
|
||||||
`main` has a ruleset: every commit that lands on it must have a passing `validate` check, and force-pushes and deletion are blocked. Contributors and maintainers get the check through pull requests; bots get it by dispatching `validate` on their branch. Repository admins can merge a PR whose check is failing or pending (for a broken CI), but cannot push unvalidated commits directly.
|
`main` has a ruleset: changes land only through pull requests with a passing `validate` check (GitHub rulesets do not accept direct pushes while a status check is required), and force-pushes and deletion are blocked. Bots open PRs too and get the check by dispatching `validate` on their branch. Repository admins can merge a PR whose check is failing or pending (for a broken CI).
|
||||||
|
|
||||||
## Automation map
|
## Automation map
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ A weekly scout searches npm for packages published since V2 shipped that depend
|
|||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| `validate-pr.yml` | every PR | Required `validate` check |
|
| `validate-pr.yml` | every PR | Required `validate` check |
|
||||||
| `triage.yml` | PR opened/updated | Labels and a results comment (base-branch code only) |
|
| `triage.yml` | PR opened/updated | Labels and a results comment (base-branch code only) |
|
||||||
| `generate-readme.yml` | push to main | README.md and dist/registry.json; fails without writing on any invalid entry. The regenerated commit is staged on `bot/readme-*`, validated, then fast-forwarded onto main |
|
| `generate-readme.yml` | push to main | README.md and dist/registry.json; fails without writing on any invalid entry. The regenerated commit goes through a bot PR (`bot/readme-*`) that merges itself once `validate` passes |
|
||||||
| `site.yml` | push to main, daily | Search site on GitHub Pages |
|
| `site.yml` | push to main, daily | Search site on GitHub Pages |
|
||||||
| `health.yml` | daily | Health report issue, rename and removal PRs |
|
| `health.yml` | daily | Health report issue, rename and removal PRs |
|
||||||
| `reprobe.yml` | daily | Re-checks `needs-v2` PRs |
|
| `reprobe.yml` | daily | Re-checks `needs-v2` PRs |
|
||||||
|
|||||||
Reference in new issue
Block a user