feat(tui): integrate the 0.9.12 Tideline shell #1947
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: PR closes an issue | |
| # 342 open issues, 329 of them touched within the month: nothing here is rotting, | |
| # the drain is just clogged. Only 8 of 35 open PRs carried a closing keyword, so | |
| # work ships and its issue stays open, and nobody can tell which of the 342 are | |
| # already done. That is how 121 issues end up on one milestone. | |
| # | |
| # This check asks every PR to either close an issue or say why it doesn't. The | |
| # opt-out is one line, so this is a prompt, not a wall. | |
| on: | |
| pull_request: | |
| types: [opened, edited, reopened, synchronize] | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| link: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # Automated dependency bumps (dependabot and any other GitHub-verified | |
| # bot account) are machine-generated and can never carry a closing | |
| # keyword; failing them here would require hand-editing every bot body, | |
| # which defeats the automation. The gate stays strict for every human | |
| # PR. `user.type` is set by GitHub for verified bot accounts, so a PR | |
| # author cannot spoof it to dodge the check. | |
| - name: Require a closing keyword or an explicit opt-out | |
| if: github.event.pull_request.user.type != 'Bot' | |
| env: | |
| # Fetched live rather than read from the event payload. A rerun | |
| # replays the payload the run started with, so a body-only fix could | |
| # never turn this check green: the obvious operator move — add the | |
| # missing line, rerun the failed check — re-read the old body and | |
| # failed again with no hint why. Reading the current body makes a | |
| # rerun mean what everyone already assumes it means. | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| # Through a variable, never interpolated into the script body: | |
| # a PR body is attacker-controlled text. | |
| PR_BODY=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json body --jq '.body // ""') | |
| # Body only, deliberately. GitHub resolves closing keywords from the | |
| # PR description; a "Closes #123" in the title auto-closes nothing. | |
| # Accepting the title here would pass PRs that never close an issue, | |
| # which is the exact false-assurance this check exists to prevent. | |
| text="${PR_BODY:-}" | |
| # GitHub's own closing-keyword set, plus the #N it must attach to. | |
| if grep -qiE '\b(close[sd]?|fix(e[sd])?|resolve[sd]?)\b[[:space:]]*:?[[:space:]]*#[0-9]+' <<<"$text"; then | |
| echo "Closing keyword found — this PR will close its issue on merge." | |
| exit 0 | |
| fi | |
| # One-line escape hatch. Anything after the marker is the reason. | |
| if grep -qiE '^[[:space:]]*No-Issue:[[:space:]]*\S' <<<"$text"; then | |
| reason=$(grep -iE '^[[:space:]]*No-Issue:' <<<"$text" | head -1) | |
| echo "Opted out — ${reason}" | |
| exit 0 | |
| fi | |
| cat >&2 <<'MSG' | |
| This PR neither closes an issue nor says why it doesn't. | |
| Add one of these to the PR body: | |
| Closes #1234 (or Fixes / Resolves — any of GitHub's keywords) | |
| No-Issue: <one-line why> (chores, docs typos, revert, dependency bump) | |
| Why this is a required check: work here ships faster than issues close, | |
| so an unlinked PR leaves its issue open forever and the backlog stops | |
| reflecting reality. Either line takes five seconds and keeps the | |
| milestone honest. | |
| MSG | |
| exit 1 |