This repository was archived by the owner on Jun 26, 2026. It is now read-only.
fix(forms): stop VM disk selection being dropped on deploy #22
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 size label | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize, reopened] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| concurrency: | |
| group: pr-size-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| size: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const pr = context.payload.pull_request; | |
| // Skip files that should not count as "real diff" — they are produced by tools | |
| // or vendored, not authored by humans, and including them lies to reviewers | |
| // about review effort: | |
| // - lockfiles (pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lockb, *.lock) | |
| // - build / dist output checked in by accident | |
| // - generated code trees (any path segment named `generated/`) | |
| // - vendored deps (node_modules — should be gitignored, defence in depth) | |
| const isIgnored = (path) => | |
| path === 'pnpm-lock.yaml' || path.endsWith('/pnpm-lock.yaml') || | |
| path === 'package-lock.json' || path.endsWith('/package-lock.json') || | |
| path === 'yarn.lock' || path.endsWith('/yarn.lock') || | |
| path === 'bun.lockb' || path.endsWith('/bun.lockb') || | |
| path.endsWith('.lock') || | |
| /(^|\/)node_modules\//.test(path) || | |
| /(^|\/)dist\//.test(path) || | |
| /(^|\/)build\//.test(path) || | |
| /(^|\/)generated\//.test(path); | |
| const files = await github.paginate(github.rest.pulls.listFiles, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr.number, | |
| }); | |
| const lines = files | |
| .filter((f) => !isIgnored(f.filename)) | |
| .reduce((acc, f) => acc + (f.additions || 0) + (f.deletions || 0), 0); | |
| // Thresholds match the descriptions of size/* labels in .github/labels.yml. | |
| const bucket = | |
| lines <= 9 ? 'XS' : | |
| lines <= 29 ? 'S' : | |
| lines <= 99 ? 'M' : | |
| lines <= 499 ? 'L' : | |
| lines <= 999 ? 'XL' : 'XXL'; | |
| const target = `size/${bucket}`; | |
| // Match both legacy "size:" and canonical "size/" during the migration window. | |
| const existing = (pr.labels || []).map((l) => l.name); | |
| const oldSizes = existing.filter((n) => n.startsWith('size/') || n.startsWith('size:')); | |
| const alreadyTarget = oldSizes.includes(target); | |
| // Remove every size/* label that is not the target. Tolerate 404 — concurrent | |
| // runs or manual edits between event payload and execution can race here. | |
| for (const name of oldSizes) { | |
| if (name === target) continue; | |
| try { | |
| await github.rest.issues.removeLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| name, | |
| }); | |
| } catch (e) { | |
| if (e.status !== 404) throw e; | |
| core.info(`label ${name} already gone (404)`); | |
| } | |
| } | |
| if (alreadyTarget && oldSizes.length === 1) { | |
| core.info(`PR #${pr.number}: ${lines} lines, label already ${target}`); | |
| return; | |
| } | |
| if (!alreadyTarget) { | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| labels: [target], | |
| }); | |
| } | |
| core.info(`PR #${pr.number}: ${lines} lines -> ${target}`); |