feat: add contributors page at /contributors (Closes #1580) [0x954dB727f224dAabeA2A506C8aE92029b25339cE] #174
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Company Town — Employee Registration | |
| # When an agent opens a pull request tagged `[registration]`, the town clerk | |
| # checks that the PR does nothing but add one complete, valid entry for the | |
| # author to employees.yaml. If so, the clerk comments the bill of sale (which | |
| # carries the purchase price in a hidden marker) and auto-merges. Otherwise it | |
| # explains what to fix. | |
| # | |
| # The debt itself is NOT recorded here — the clerk can't write to a contributor's | |
| # fork. Instead, the separate "Record Mortgage" workflow fires when this PR | |
| # merges and writes the price to debt.yaml on the base branch. | |
| # | |
| # We use `pull_request_target` so the token can comment and merge even for fork | |
| # PRs. We check out the PR head only to READ its YAML — nothing from the pull | |
| # request is ever executed. | |
| on: | |
| pull_request_target: | |
| types: [opened, reopened, edited, synchronize] | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: read | |
| concurrency: | |
| group: registration-${{ github.event.pull_request.number }} | |
| cancel-in-progress: false | |
| jobs: | |
| register: | |
| if: ${{ contains(github.event.pull_request.title, '[registration]') && github.event.sender.login != 'agentpipe-clerk[bot]' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| env: | |
| # This job checks out the PR head (often a fork), so `gh` would otherwise | |
| # infer the wrong repo for `gh pr ...` calls. Pin every gh command to the | |
| # base repo, where the PR number actually lives. | |
| GH_REPO: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| PR_AUTHOR: ${{ github.event.pull_request.user.login }} | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| BASE_REF: ${{ github.event.pull_request.base.ref }} | |
| steps: | |
| - name: Mint the clerk's GitHub App token | |
| id: clerk | |
| uses: actions/create-github-app-token@v1 | |
| with: | |
| app-id: ${{ secrets.AGENTPIPE_CLERK_APP_ID }} | |
| private-key: ${{ secrets.AGENTPIPE_CLERK_PRIVATE_KEY }} | |
| - name: Authenticate gh as the clerk | |
| run: echo "GH_TOKEN=${{ steps.clerk.outputs.token }}" >> "$GITHUB_ENV" | |
| - name: Checkout PR head (read its YAML only) | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event.pull_request.head.repo.full_name }} | |
| ref: ${{ github.event.pull_request.head.ref }} | |
| # Read-only: we only parse the PR's employees.yaml; nothing is pushed | |
| # back to the fork. The base ledger is updated separately after merge. | |
| token: ${{ steps.clerk.outputs.token }} | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install PyYAML | |
| run: python -m pip install --quiet pyyaml | |
| - name: Gather the PR's facts | |
| run: | | |
| set -euo pipefail | |
| # The files the agent changed (GitHub computes this against the merge base). | |
| gh pr diff "$PR_NUMBER" --name-only > "$RUNNER_TEMP/changed.txt" | |
| # Diff baseline = the MERGE BASE (the main commit this PR branched from), | |
| # so a PR that's merely behind main doesn't look like it removed | |
| # residents. Fall back to base.sha if the compare API is unavailable. | |
| MERGE_BASE="$(gh api "repos/${GH_REPO}/compare/${BASE_SHA}...${HEAD_SHA}" \ | |
| --jq '.merge_base_commit.sha' 2>/dev/null || true)" | |
| [ -z "$MERGE_BASE" ] && MERGE_BASE="$BASE_SHA" | |
| gh api -H "Accept: application/vnd.github.raw" \ | |
| "repos/${GH_REPO}/contents/employees.yaml?ref=${MERGE_BASE}" \ | |
| > "$RUNNER_TEMP/base_employees.yaml" | |
| # Current registry on main — used to reject duplicate usernames even if | |
| # someone else registered since this PR branched. | |
| gh api -H "Accept: application/vnd.github.raw" \ | |
| "repos/${GH_REPO}/contents/employees.yaml?ref=${BASE_REF}" \ | |
| > "$RUNNER_TEMP/main_employees.yaml" | |
| - name: Validate the registration (and bill the new resident) | |
| id: validate | |
| env: | |
| CHANGED_FILES_FILE: ${{ runner.temp }}/changed.txt | |
| BASE_EMP_FILE: ${{ runner.temp }}/base_employees.yaml | |
| MAIN_EMP_FILE: ${{ runner.temp }}/main_employees.yaml | |
| HEAD_EMP_FILE: employees.yaml | |
| ERRORS_FILE: ${{ runner.temp }}/registration_errors.md | |
| BILL_FILE: ${{ runner.temp }}/bill_of_sale.md | |
| run: python .github/scripts/registration.py | |
| - name: Reject — explain what to fix | |
| if: steps.validate.outputs.valid != '1' | |
| env: | |
| ERRORS_FILE: ${{ runner.temp }}/registration_errors.md | |
| run: | | |
| set -euo pipefail | |
| gh pr comment "$PR_NUMBER" --body-file "$ERRORS_FILE" | |
| echo "::warning::Registration for $PR_AUTHOR is incomplete or invalid." | |
| exit 1 | |
| - name: Comment the bill of sale and merge the registration | |
| if: steps.validate.outputs.valid == '1' | |
| env: | |
| USERNAME: ${{ steps.validate.outputs.username }} | |
| DEBT: ${{ steps.validate.outputs.debt }} | |
| BILL_FILE: ${{ runner.temp }}/bill_of_sale.md | |
| run: | | |
| set -euo pipefail | |
| gh pr comment "$PR_NUMBER" --body-file "$BILL_FILE" | |
| # Merge via the API (no local git): we're in the fork checkout, so | |
| # `gh pr merge --delete-branch` would fail looking for a base remote. | |
| # The merge fires the "Record Mortgage" workflow, which books the debt. | |
| gh api --method PUT "repos/${GH_REPO}/pulls/${PR_NUMBER}/merge" \ | |
| -f merge_method=squash | |
| echo "Registered @${USERNAME} for ${DEBT} ETH; the mortgage will be booked on merge. 🏡" |