inbox.yml

Org-wide prioritised PR inbox on GitHub Pages. Lives in this (source) repo.

What this is

Rebuilds the org-wide prioritised PR inbox and publishes it to GitHub Pages, via scripts/build-inbox.mjs.

How to onboard it

It lives in this repository and is already installed here. Before it will build, set the repository variable PAGES_VISIBILITY_ACKNOWLEDGED to private or internal and provide REDLINE_ORG_READ_TOKEN.

  • Lives in: This (source) repo.
  • Trigger: Every 30 minutes, 06:00-19:00 UTC, Monday-Friday, plus workflow_dispatch.

How to use it

Nothing, normally — it runs itself. Run scripts/build-inbox.mjs locally with a scoped GH_TOKEN to preview a layout change before it ships.

What a run does, in order:

  • Refuses to build unless the repository variable PAGES_VISIBILITY_ACKNOWLEDGED is set to private or internal — the page lists PR titles, authors and repo names, and a public Pages site would leak them.
  • Builds dist/index.html with scripts/build-inbox.mjs.
  • Deploys to GitHub Pages, then opens or updates a tracking issue if the build or deploy failed.

Works, once Pages visibility is acknowledged and REDLINE_ORG_READ_TOKEN is set.

Expected output

A static page on GitHub Pages listing open org pull requests in priority order. On a build or deploy failure it opens or updates a single tracking issue rather than failing silently. Without the visibility acknowledgement it refuses to build at all — the page carries PR titles, authors and repo names, and a public Pages site would leak them.

How to edit it

  1. Edit the YAML in workflows/ or .github/workflows/workflows/ holds files destined for other repositories; .github/workflows/ is this repository's own CI. The two are not interchangeable — check where this one lives before editing.
  2. actionlintCI lints .github/workflows/*.yml, workflows/*.yml and templates/redline.yml together. workflows/ is pointed at explicitly because actionlint's own discovery would skip it.
  3. node scripts/check-pins.mjsIf you add a third-party action, pin it to a 40-character commit SHA with a trailing # vX.Y.Z comment. First-party actions/* are referenced by tag. The pin checker re-resolves the SHA against the tag the comment claims.
  4. node scripts/validate.mjsAsserts the workflow files the bundle depends on still exist, and that the gate's job ids still match the required check name derived from them.

The full file

workflows/inbox.yml · 98 lines · 3.2 KB
# Lives in the Redline source repo. Rebuilds the org-wide PR inbox on a schedule and
# publishes it to GitHub Pages.
#
# SECURITY: the page lists PR titles, authors and repo names. Set the Pages site to
# private or internal visibility (Settings > Pages > Visibility) BEFORE enabling this.
# On a public Pages site this publishes internal delivery detail to the internet. The
# build refuses to run until PAGES_VISIBILITY_ACKNOWLEDGED is set as a repo variable.
name: Redline Inbox

on:
  schedule:
    - cron: '*/30 6-19 * * 1-5'
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: inbox
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Confirm Pages visibility was reviewed
        env:
          ACK: ${{ vars.PAGES_VISIBILITY_ACKNOWLEDGED }}
        run: |
          if [[ "${ACK:-}" != "private" && "${ACK:-}" != "internal" ]]; then
            echo "::error::Set the repository variable PAGES_VISIBILITY_ACKNOWLEDGED to 'private' or 'internal' after confirming the Pages site is not public. This page exposes org-wide PR titles and authors."
            exit 1
          fi

      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install and build
        run: |
          npm ci
          npm run build

      # This one runs in the source repo, so it uses the build it is about to
      # ship rather than the last published package: a broken inbox here is a
      # broken command, and finding that out from the release is too late.
      - name: Build inbox
        env:
          GH_TOKEN: ${{ secrets.REDLINE_ORG_READ_TOKEN }}
        run: |
          node dist/bin/redline.js metrics inbox \
            --org "${{ github.repository_owner }}" \
            --out dist

      - uses: actions/upload-pages-artifact@v3
        with:
          path: dist

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4

  # A silently stale inbox is worse than no inbox: people trust a page that stopped
  # updating three weeks ago. Surface the failure where someone will see it.
  alert:
    needs: [build, deploy]
    if: failure()
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
    steps:
      - name: Open or update a failure issue
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
        run: |
          set -euo pipefail
          title="Redline inbox build is failing"
          existing=$(gh issue list --repo "$REPO" --state open --search "$title in:title" --json number --jq '.[0].number // ""')
          if [[ -n "$existing" ]]; then
            gh issue comment "$existing" --repo "$REPO" --body "Still failing: $RUN"
          else
            gh issue create --repo "$REPO" --title "$title" \
              --body "The scheduled inbox build failed. The published page is now stale. Run: $RUN"
          fi