feat: implement changesets in repo #6
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 Snapshot Diff (PNG/YML) | |
| on: | |
| pull_request: | |
| branches: ["main"] | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| concurrency: | |
| 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-latest | |
| steps: | |
| - name: ⏬ Checkout PR head (not merge ref) | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - 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 | |
| - name: 🧾 Collect changed PNG/YML snapshots | |
| id: diff | |
| 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 | |
| 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) | |
| 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 | |
| { | |
| 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" | |
| - name: 📎 Upload unified diff (artifact) | |
| if: env.SNAP_TOTAL != '0' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: snapshots-diff | |
| path: snapshots.diff | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| - name: 💬 Upsert PR comment | |
| uses: actions/github-script@v7 | |
| env: | |
| SNAP_SUMMARY_MD_PATH: ${{ env.SNAP_SUMMARY_MD_PATH }} | |
| with: | |
| script: | | |
| const fs = require('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 }); | |
| } | |
| # If snapshots (png/yml) were changed, require at least a minor bump | |
| - 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 | |
| - name: 🔎 Determine bump plan (JSON + Fallback) | |
| id: plan | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| npx -y @changesets/cli@^2 status --since=origin/main --output=json > .changeset-status.json || true | |
| node > .changeset-env <<'NODE' | |
| const fs = require('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 | |
| source .changeset-env || true | |
| if [ "${HAS_MINOR}" = "0" ] && [ "${HAS_MAJOR}" = "0" ]; then | |
| 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 | |
| if grep -E ':\s*minor\b' "$f" >/dev/null 2>&1; then HAS_MINOR=1; fi | |
| if grep -E ':\s*major\b' "$f" >/dev/null 2>&1; then HAS_MAJOR=1; fi | |
| done < .cs-files | |
| fi | |
| { | |
| echo "HAS_MINOR=${HAS_MINOR}" | |
| echo "HAS_MAJOR=${HAS_MAJOR}" | |
| } > .changeset-env | |
| fi | |
| cat .changeset-env >> "$GITHUB_ENV" | |
| { | |
| echo "### Bump Plan Detection" | |
| echo | |
| echo "- HAS_MINOR: ${HAS_MINOR}" | |
| echo "- HAS_MAJOR: ${HAS_MAJOR}" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| - name: 🚦 Enforce Snapshot changes require >= minor | |
| if: 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 |