mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
ci: relay contributor card events to worker (#3113)
This commit is contained in:
parent
74fa8a754a
commit
bc44a8add3
1 changed files with 46 additions and 39 deletions
85
.github/workflows/contributor-card-bot.yml
vendored
85
.github/workflows/contributor-card-bot.yml
vendored
|
|
@ -6,10 +6,8 @@ name: Contributor Card Bot
|
||||||
#
|
#
|
||||||
# Intentionally NOT included: pull_request_review, pull_request_review_comment,
|
# Intentionally NOT included: pull_request_review, pull_request_review_comment,
|
||||||
# issue_comment. GitHub withholds repository secrets from these events when
|
# issue_comment. GitHub withholds repository secrets from these events when
|
||||||
# they originate on forked PRs, which is precisely the path most external
|
# they originate on forked PRs, so the relay secret would fail-closed there too.
|
||||||
# contributor activity takes; the bot requires BOT_APP_* secrets to authenticate,
|
# They can be re-added later via a workflow_run handoff.
|
||||||
# so wiring those events here would fail-closed exactly for the contributors we
|
|
||||||
# want to recognize. They can be re-added later via a workflow_run handoff.
|
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [closed]
|
types: [closed]
|
||||||
|
|
@ -24,21 +22,16 @@ on:
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
# Serialize all bot runs across the whole repository. The bot reads-then-writes
|
# Serialize all relay runs across the whole repository. The Cloudflare worker
|
||||||
# `data/contributor-card-state.json`; running events in parallel let multiple
|
# owns durable state now, but queuing still keeps identical GitHub events from
|
||||||
# runs read the same SHA and only the first PUT succeeds, the rest fail with a
|
# racing each other and producing duplicate comments during bursty merge windows.
|
||||||
# 409 Conflict. They also let the same actor receive duplicate cards when a
|
|
||||||
# burst of events fires before the first state write lands. A single repo-wide
|
|
||||||
# group with `cancel-in-progress: false` queues runs and processes them in
|
|
||||||
# arrival order, so every event still gets a card and the state file is never
|
|
||||||
# stale on write.
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: contributor-card-bot
|
group: contributor-card-bot
|
||||||
cancel-in-progress: false
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
recognize:
|
recognize:
|
||||||
name: Render and post contributor card
|
name: Relay contributor event to Cloudflare worker
|
||||||
if: |
|
if: |
|
||||||
github.repository == 'nexu-io/open-design' &&
|
github.repository == 'nexu-io/open-design' &&
|
||||||
(
|
(
|
||||||
|
|
@ -49,32 +42,46 @@ jobs:
|
||||||
github.event_name == 'workflow_dispatch'
|
github.event_name == 'workflow_dispatch'
|
||||||
)
|
)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 8
|
timeout-minutes: 5
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout contributor bot
|
- name: Relay event payload
|
||||||
uses: actions/checkout@v6.0.2
|
|
||||||
with:
|
|
||||||
repository: nexu-io/open-design-bot-sandbox
|
|
||||||
ref: main
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v6.0.0
|
|
||||||
with:
|
|
||||||
node-version: 22
|
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Install bot dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Run contributor bot
|
|
||||||
env:
|
env:
|
||||||
BOT_APP_ID: ${{ secrets.BOT_APP_ID }}
|
CONTRIBUTOR_CARD_WORKER_URL: ${{ secrets.CONTRIBUTOR_CARD_WORKER_URL }}
|
||||||
BOT_APP_INSTALLATION_ID: ${{ secrets.BOT_APP_INSTALLATION_ID }}
|
CONTRIBUTOR_CARD_WORKER_SECRET: ${{ secrets.CONTRIBUTOR_CARD_WORKER_SECRET }}
|
||||||
BOT_APP_PRIVATE_KEY: ${{ secrets.BOT_APP_PRIVATE_KEY }}
|
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
||||||
run: pnpm exec tsx scripts/action-handler.ts
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||||
|
GITHUB_EVENT_ACTION: ${{ github.event.action }}
|
||||||
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
||||||
|
GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }}
|
||||||
|
GITHUB_EVENT_PATH: ${{ github.event_path }}
|
||||||
|
run: |
|
||||||
|
python - <<'PY'
|
||||||
|
import json, os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
payload = json.loads(Path(os.environ["GITHUB_EVENT_PATH"]).read_text())
|
||||||
|
envelope = {
|
||||||
|
"repository": os.environ["GITHUB_REPOSITORY"],
|
||||||
|
"eventName": os.environ["GITHUB_EVENT_NAME"],
|
||||||
|
"action": os.environ.get("GITHUB_EVENT_ACTION") or payload.get("action"),
|
||||||
|
"deliveryId": f"{os.environ['GITHUB_RUN_ID']}-{os.environ['GITHUB_RUN_ATTEMPT']}",
|
||||||
|
"triggeredAt": __import__("datetime").datetime.utcnow().isoformat(timespec="milliseconds") + "Z",
|
||||||
|
"payload": payload,
|
||||||
|
}
|
||||||
|
Path("body.json").write_text(json.dumps(envelope, separators=(",", ":")))
|
||||||
|
PY
|
||||||
|
python - <<'PY'
|
||||||
|
import hashlib, hmac, os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
body = Path("body.json").read_bytes()
|
||||||
|
digest = hmac.new(os.environ["CONTRIBUTOR_CARD_WORKER_SECRET"].encode(), body, hashlib.sha256).hexdigest()
|
||||||
|
Path("signature.txt").write_text(f"sha256={digest}")
|
||||||
|
PY
|
||||||
|
curl --fail --silent --show-error \
|
||||||
|
-X POST \
|
||||||
|
-H "content-type: application/json" \
|
||||||
|
-H "x-open-design-signature: $(cat signature.txt)" \
|
||||||
|
--data-binary @body.json \
|
||||||
|
"$CONTRIBUTOR_CARD_WORKER_URL/api/github/events"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue