Skip to content

feat(tui): integrate the 0.9.12 Tideline shell #1947

feat(tui): integrate the 0.9.12 Tideline shell

feat(tui): integrate the 0.9.12 Tideline shell #1947

Workflow file for this run

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