Files
supabase/.github/workflows/studio-lint-ratchet-decrease.yml
0003958f70 chore(ci): notify #team-frontend when ratchet baseline hits zero (#50978)
<!-- ccr-slack-attribution -->
_Requested by **Charis Lam** · [Slack
thread](https://supabase.slack.com/archives/C0161K73J1J/p1790599888647059?thread_ts=1790599888.647059&cid=C0161K73J1J)_

## Problem

The weekly "Decrease studio lint ratchet baselines" workflow
(`.github/workflows/studio-lint-ratchet-decrease.yml`) mechanically
decreases each tracked ESLint rule's baseline count in
`apps/studio/.github/eslint-rule-baselines.json` and opens/updates a PR.
When a rule's count reaches exactly 0, there's nothing left to ratchet —
a human (or agent) needs to remove it from ratchet tracking
(`apps/studio/scripts/ratchet-rules.json` and the baseline file) and
bump its ESLint severity to `error`, as was just done manually in
#50977. Nobody is currently notified when this threshold is crossed, so
it can sit unnoticed.

## Solution

**Before:** the job silently commits the decreased baselines and
opens/updates its PR with no signal that any rule just hit 0.

**After:** a new step runs after the baseline commit/PR step, only when
that step found changes (via a new `id: decrease-baselines` and a
`changed` step output, added without touching the existing decrease
logic itself — just capturing its existing control flow into an output).
It parses the final `apps/studio/.github/eslint-rule-baselines.json` on
disk for any rule whose count is exactly `0`. If any are found, it posts
a Slack message via `curl` to a webhook, tagging `@Claude` in
`#team-frontend` with the rule names and a link to the PR the job just
created/updated, asking it to do the same triage as #50977 (remove from
ratchet tracking, bump severity to `error`). If no rule is at 0, it
skips silently.

The webhook URL comes from a new repo secret,
`secrets.SLACK_TEAM_FRONTEND_WEBHOOK_URL`, which **does not exist yet**.
**A human needs to create a Slack incoming webhook for #team-frontend
and add its URL as the `SLACK_TEAM_FRONTEND_WEBHOOK_URL` repository
secret before this step will actually post anything.** Until then, the
step detects the missing/empty secret and only logs a `::warning::`,
exiting 0 — it will never fail the job.

## Review instructions

1. Read `.github/workflows/studio-lint-ratchet-decrease.yml`: confirm
the existing decrease/commit/PR step is unchanged except for the added
`id: decrease-baselines` and the two `echo ... >> "$GITHUB_OUTPUT"`
lines that record whether anything changed and the PR URL.
2. Confirm the new final step only runs `if:
steps.decrease-baselines.outputs.changed == 'true'`.
3. Confirm the new step parses
`apps/studio/.github/eslint-rule-baselines.json`'s `rules` map for
entries equal to `0`, and skips (exit 0, no curl) when none are found.
4. Confirm the `curl` call is gated on `SLACK_WEBHOOK_URL` being
non-empty, and that a failed `curl` only emits `::warning::` rather than
failing the step (`set -euo pipefail` is still safe because the failure
is inside an `if !`).
5. Note that this PR alone does not make the notification fire:
`SLACK_TEAM_FRONTEND_WEBHOOK_URL` must be provisioned as a repo secret
(Settings → Secrets and variables → Actions) from a Slack incoming
webhook for #team-frontend first.

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [ ] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01LZThbcWV5U1r5cvUDKPVQP

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
2026-09-28 15:08:03 +00:00

128 lines
4.7 KiB
YAML

name: Decrease studio lint ratchet baselines
on:
schedule:
- cron: '0 0 * * SUN'
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
decrease-baselines:
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
sparse-checkout: |
.github
apps/studio
packages
patches
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
name: Install pnpm
with:
run_install: false
- name: Use Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install deps
run: pnpm install --frozen-lockfile
- name: Generate token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.GH_AUTOFIX_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_AUTOFIX_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
- name: Decrease ESLint ratchet baselines and open PR
id: decrease-baselines
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
set -eo pipefail
DEFAULT_BRANCH=${DEFAULT_BRANCH:-master}
BRANCH="bot/decrease-eslint-ratchet-baselines"
git fetch origin "$DEFAULT_BRANCH" --depth=1
if git ls-remote --exit-code --heads origin "$BRANCH" > /dev/null 2>&1; then
git fetch origin "$BRANCH":"$BRANCH" --depth=1
git switch "$BRANCH"
git reset --hard "origin/$DEFAULT_BRANCH"
else
git switch --create "$BRANCH" "origin/$DEFAULT_BRANCH"
fi
pnpm --filter studio run lint:ratchet --decrease-baselines
if git diff --quiet; then
echo "No baseline updates detected."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add apps/studio/.github/eslint-rule-baselines.json
git commit --message "chore: decrease ESLint ratchet baselines"
git -c credential.helper= push --force "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "HEAD:${BRANCH}"
pr_url=$(gh pr list --state open --head "$BRANCH" --json url --jq '.[0].url // ""' 2>/dev/null || echo "")
if [ -z "$pr_url" ]; then
pr_url=$(gh pr create \
--title "[bot] Decrease ESLint ratchet baselines" \
--body "Automated weekly decrease of ESLint ratchet baselines." \
--base "$DEFAULT_BRANCH" \
--head "$BRANCH")
else
gh pr comment "$pr_url" --body "Updated ESLint ratchet baselines with the latest weekly decreases."
fi
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "pr_url=$pr_url" >> "$GITHUB_OUTPUT"
- name: 'Notify #team-frontend about rules that hit a zero baseline'
if: steps.decrease-baselines.outputs.changed == 'true'
env:
PR_URL: ${{ steps.decrease-baselines.outputs.pr_url }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DASHBOARD_WEBHOOK_URL }}
run: |
set -euo pipefail
zero_rules=$(jq -r '.rules | to_entries | map(select(.value == 0) | .key) | join(", ")' apps/studio/.github/eslint-rule-baselines.json)
if [ -z "$zero_rules" ]; then
echo "No rules dropped to a baseline of 0; nothing to notify."
exit 0
fi
if [ -z "${SLACK_WEBHOOK_URL:-}" ]; then
echo "::warning::SLACK_DASHBOARD_WEBHOOK_URL secret is not set; skipping Slack notification for zero-baseline rules: $zero_rules"
exit 0
fi
pr_number="${PR_URL##*/}"
text="<@U0A1BRW39PC> the weekly ratchet-baseline job just dropped these rules to 0 in <${PR_URL}|#${pr_number}>: ${zero_rules}. Can you remove them from ratchet tracking and bump their ESLint severity to \"error\"?"
payload=$(jq -n --arg text "$text" '{text: $text}')
if ! curl --fail --silent --show-error -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d "$payload"; then
echo "::warning::Failed to post Slack notification for zero-baseline rules: $zero_rules"
fi