Skip to content

Update .changeset/README.md #40

Update .changeset/README.md

Update .changeset/README.md #40

# -------------------------------------------------------------

Check failure on line 1 in .github/workflows/pull-request-snapshot-diff.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/pull-request-snapshot-diff.yml

Invalid workflow file

(Line: 31, Col: 8): Unexpected value ''
# 🧪 PR Snapshot Diff (PNG/YML)
# Compares the PR branch against origin/main for snapshot changes
# under __snapshots__/ (PNG + YML). Posts a PR comment summary and
# enforces that visual/config snapshot changes require >= MINOR bump.
# -------------------------------------------------------------
name: 🧪 PR Snapshot Diff (PNG/YML)
on:
pull_request:
branches: ["main"]
# Run on new PRs, updates (pushes), and when PRs are reopened/un-drafted.
types: [opened, synchronize, reopened, ready_for_review]
permissions:
# Read repo content to compute diffs; write to PR to post/update a comment.
contents: read
pull-requests: write
concurrency:
# Ensure only one snapshot job per PR runs at a time; cancel older runs.
group: pr-snapshot-diff-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
snapshot-diff:
name: 🔎 Snapshot changes (png/yml) & bump guard
runs-on: ubuntu-24.04
steps:
- # Check out the PR *head* commit (not the merge ref), with full history.
- name: ⏬ Checkout PR head (not merge ref)
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
# Make sure origin/main exists locally to diff against; unshallow if needed.
- name: 🔁 Ensure base (origin/main) is present
shell: bash
run: |
set -euo pipefail
if [ -f .git/shallow ]; then
git fetch --unshallow --no-tags --prune
fi
git fetch --no-tags --prune origin +refs/heads/main:refs/remotes/origin/main
git rev-parse remotes/origin/main >/dev/null
# Early scan of changed .changeset/*.md files for 'minor'/'major'.
- name: 🔎 Early bump plan (fallback-only for skip)
id: early_plan
shell: bash
run: |
set -euo pipefail
HAS_MINOR=0
HAS_MAJOR=0
git diff --name-only origin/main...HEAD -- .changeset/*.md > .cs-files || true
if [ -s .cs-files ]; then
while read -r f; do
[ -z "${f:-}" ] && continue
grep -qE ':\s*minor\b' "$f" && HAS_MINOR=1 || true
grep -qE ':\s*major\b' "$f" && HAS_MAJOR=1 || true
done < .cs-files
fi
{
echo "HAS_MINOR=${HAS_MINOR}"
echo "HAS_MAJOR=${HAS_MAJOR}"
} >> "$GITHUB_ENV"
# Compute unified diff + name-status for PNG/YML snapshot files.
# Build a Markdown summary and export counters via $GITHUB_ENV.
- name: 🧾 Collect changed PNG/YML snapshots
id: diff
if: env.HAS_MINOR == '0' && env.HAS_MAJOR == '0'
shell: bash
run: |
set -euo pipefail
git diff --unified=3 --no-color origin/main...HEAD -- __snapshots__/**/*.{png,yml} > snapshots.diff || true
git diff --name-status origin/main...HEAD -- __snapshots__/**/*.{png,yml} > snapshots.list || true
# Robust counters (tolerant if file is empty/missing)
TOTAL=$(wc -l < snapshots.list 2>/dev/null | tr -d '[:space:]' || echo 0)
ADDED=$(grep -E '^[A]\s' snapshots.list 2>/dev/null | wc -l | tr -d '[:space:]' || echo 0)
MOD=$(grep -E '^[M]\s' snapshots.list 2>/dev/null | wc -l | tr -d '[:space:]' || echo 0)
DEL=$(grep -E '^[D]\s' snapshots.list 2>/dev/null | wc -l | tr -d '[:space:]' || echo 0)
REN=$(grep -E '^[R]\d*\s' snapshots.list 2>/dev/null | wc -l | tr -d '[:space:]' || echo 0)
# Build a short table (first 200 rows) for the PR comment
head -n 200 snapshots.list > snapshots.short || true
{
echo "### Snapshot Changes (PNG/YML)"
echo
if [ "${TOTAL}" = "0" ]; then
echo "_No \`__snapshots__/**/*.{png,yml}\` changes detected._"
else
echo "- Total: **${TOTAL}** (added: ${ADDED}, modified: ${MOD}, deleted: ${DEL}, renamed: ${REN})"
echo
echo "| Status | File |"
echo "|-------:|:-----|"
while read -r LINE; do
[ -z "${LINE:-}" ] && continue
STATUS=$(echo "$LINE" | awk '{print $1}')
FILE=$(echo "$LINE" | awk '{print $2}')
if echo "$STATUS" | grep -qE '^R'; then
FILE=$(echo "$LINE" | awk '{print $3}')
fi
echo "| \`$STATUS\` | \`$FILE\` |"
done < snapshots.short
if [ "$TOTAL" -gt 200 ]; then
echo ""
echo "_…and $(($TOTAL - 200)) more_"
fi
fi
echo ""
echo "<!-- snapshot-summary-marker -->"
} > snapshot-summary.md
# Export counters and the summary path as job environment variables
{
echo "SNAP_TOTAL=${TOTAL}"
echo "SNAP_ADDED=${ADDED}"
echo "SNAP_MODIFIED=${MOD}"
echo "SNAP_DELETED=${DEL}"
echo "SNAP_RENAMED=${REN}"
echo "SNAP_SUMMARY_MD_PATH=$(pwd)/snapshot-summary.md"
} >> "$GITHUB_ENV"
# Attach the full unified diff as a downloadable artifact if there are changes.
- name: 📎 Upload unified diff (artifact)
if: env.HAS_MINOR == '0' && env.HAS_MAJOR == '0' && env.SNAP_TOTAL && env.SNAP_TOTAL != '0'
uses: actions/upload-artifact@v4
with:
name: snapshots-diff
path: snapshots.diff
if-no-files-found: ignore
retention-days: 7
# Post (or update) a PR comment with the table summary.
- name: 💬 Upsert PR comment
if: env.HAS_MINOR == '0' && env.HAS_MAJOR == '0'
uses: actions/github-script@v7
env:
SNAP_SUMMARY_MD_PATH: ${{ env.SNAP_SUMMARY_MD_PATH }}
with:
script: |
const fs = require('node:fs');
const { owner, repo, number } = context.issue;
const marker = '<!-- snapshot-summary-marker -->';
let body = '_No snapshot info._';
try {
const p = process.env.SNAP_SUMMARY_MD_PATH;
if (p && fs.existsSync(p)) body = fs.readFileSync(p, 'utf8');
} catch {}
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number: number, per_page: 100 });
const existing = comments.find(c => c.user?.type === 'Bot' && c.body?.includes(marker));
if (existing) {
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
} else {
await github.rest.issues.createComment({ owner, repo, issue_number: number, body });
}
# Set up Node + install deps so `npx changeset` can run reliably.
- name: 🟦 Setup Node (for changeset status)
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: 📦 Install deps (root)
run: npm ci
# Determine if the PR’s changesets imply a MINOR/MAJOR bump.
# Primary source: changesets JSON;
- name: 🔎 Determine bump plan (JSON only)
id: plan
shell: bash
run: |
set -euo pipefail
npx changeset status --since=origin/main --output=json > .changeset-status.json || true
# Parse JSON and emit HAS_MINOR/HAS_MAJOR to a temp env file
node > .changeset-env <<'NODE'
const fs = require('node:fs');
let hasMinor = 0, hasMajor = 0;
try {
const txt = fs.readFileSync('.changeset-status.json','utf8').trim();
if (txt) {
const j = JSON.parse(txt);
for (const r of (j.releases || [])) {
if (r.type === 'minor') hasMinor = 1;
if (r.type === 'major') hasMajor = 1;
}
}
} catch (_) {}
process.stdout.write(`HAS_MINOR=${hasMinor}\nHAS_MAJOR=${hasMajor}\n`);
NODE
cat .changeset-env >> "$GITHUB_ENV"
# Guardrail: if snapshots changed, require at least MINOR (or MAJOR).
# This prevents accidental PATCH releases for visual/markup-impacting changes.
- name: 🚦 Enforce Snapshot changes require >= minor
if: env.HAS_MINOR == '0' && env.HAS_MAJOR == '0' && env.SNAP_TOTAL && env.SNAP_TOTAL != '0'
shell: bash
run: |
set -euo pipefail
if [ "${HAS_MINOR}" = "0" ] && [ "${HAS_MAJOR}" = "0" ]; then
echo "::error title=Snapshots changed but only patch detected::PNG/YML snapshots changed. Please bump at least MINOR in your changeset."
exit 1
else
echo "Snapshot changes and non-patch bump present → OK."
fi