name: Publish to GitHub Packages on: push: tags: - 'v*.*.*' # Manual trigger: run audit-matrix + render-gate without publishing # (publish job is guarded to tag pushes only). Lets us validate the # INFRA-F40 render-gate on a root-capable runner without cutting a release. workflow_dispatch: permissions: contents: read packages: write jobs: # F34-A: validate all prepublishOnly gates on Node 20 + 22 before publish. # Catches Node-version-specific stdlib mismatches (e.g. globSync added in Node 22) # that local dev (Node 22+) would miss but CI runner Node 20 would hit at import time. audit-matrix: runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: ['20', '22'] steps: - name: Checkout uses: actions/checkout@v5 - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: 10.28.2 - name: Setup Node ${{ matrix.node-version }} uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' - name: Install run: pnpm install --frozen-lockfile - name: Run prepublishOnly gates run: pnpm run prepublishOnly # INFRA-F40 track A: numeric render-verification gate (env-independent # getComputedStyle vs Figma). Runs here (GitHub-hosted runner = root-capable, # `--with-deps` works) rather than Gitea pr-checks (non-root runner, no system # libs). Release-time gate: a true Figma-drift (A_TRUE_DRIFT_CANDIDATE > # baseline) blocks publish. Single Node (browser test is not Node-version # sensitive), separate job so it doesn't double-run on the 20/22 matrix. render-gate: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: 10.28.2 - name: Setup Node 20 uses: actions/setup-node@v5 with: node-version: '20' cache: 'pnpm' - name: Install run: pnpm install --frozen-lockfile - name: Install Playwright chromium (+ system deps) run: pnpm exec playwright install --with-deps chromium - name: Render verification (numeric Figma-conformance) run: pnpm run test:render-verification - name: Render drift gate (A drift must be ≤ baseline) run: pnpm run audit:render-drift-gate # P1-06 (system-review-2026-06-10): release-time a11y report for v1.0 DoD (d). # Non-blocking BY DESIGN until the 43 tracked color-contrast violations are # cleared by design (owner decision 2026-06-10) — publish does NOT depend on # this job. Flip to blocking by removing `continue-on-error` and adding the # job to publish `needs` once `audit:token-contrast` reports 0 fails. a11y-report: runs-on: ubuntu-latest continue-on-error: true steps: - name: Checkout uses: actions/checkout@v5 - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: 10.28.2 - name: Setup Node 20 uses: actions/setup-node@v5 with: node-version: '20' cache: 'pnpm' - name: Install run: pnpm install --frozen-lockfile - name: Token contrast report (non-blocking) run: pnpm run audit:token-contrast - name: Install Playwright chromium (+ system deps) run: pnpm exec playwright install --with-deps chromium - name: Axe-core a11y suite (non-blocking) run: pnpm run test:a11y publish: needs: [audit-matrix, render-gate] # Only publish on real tag pushes; manual workflow_dispatch runs the gates only. if: github.event_name == 'push' runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: 10.28.2 - name: Setup Node + GitHub Packages registry uses: actions/setup-node@v5 with: node-version: '20' registry-url: 'https://npm.pkg.github.com' scope: '@nancyzeng0210' cache: 'pnpm' # P2-01 (system-review-2026-06-10): tag-time guard — a tag cut without # running `pnpm changeset:version` leaves unconsumed .changeset/*.md and a # stale version; fail fast with a clear message instead of a confusing # duplicate-version registry rejection. Deliberately NOT in prepublishOnly: # accumulating changesets on master between releases is the CORRECT state, # so the push-time audit-matrix must not check this. - name: Changesets consumed check run: | leftover=$(find .changeset -maxdepth 1 -name '*.md' ! -name 'README.md' | sort) if [ -n "$leftover" ]; then echo "::error::Unconsumed changesets — run 'pnpm changeset:version', commit, then re-tag:" echo "$leftover" exit 1 fi - name: Install (triggers prepare → typecheck + build) run: pnpm install --frozen-lockfile # prepublishOnly already validated above (audit-matrix dependency). # Run runs strict audit gates again via pnpm publish prepublishOnly hook. # Explicitly write token so pnpm v10 doesn't treat ${NODE_AUTH_TOKEN} as a literal string - name: Publish to GitHub Packages run: | echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc pnpm publish --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}