Reference
Cross-cutting reference material for the design-system integration workflows.
Auth and tokens
Section titled “Auth and tokens”The @arda-cards scope is hosted in GitHub Packages (https://npm.pkg.github.com), not the public npm registry. Access requires authentication.
ux-prototype (publisher)
Section titled “ux-prototype (publisher)”Publishing uses the workflow’s auto-provided GITHUB_TOKEN with packages: write permission. No manual token configuration is required — both publish.yml and publish-preview.yml declare the permission in their permissions: block.
Consumer apps (e.g. arda-frontend-app)
Section titled “Consumer apps (e.g. arda-frontend-app)”Consumers need a Personal Access Token (PAT) with read:packages scope to install any @arda-cards/* package — stable or preview.
npm reads the auth token from .npmrc, which interpolates an environment variable. The variable name must match between .npmrc and the environment that runs npm install. Two equivalent setups follow; pick one and use it consistently.
Local development:
- Create a PAT at https://github.com/settings/tokens with
read:packagesscope. - Add to your shell profile:
Terminal window export NODE_AUTH_TOKEN=ghp_… - Commit a
.npmrcat the repo root that uses the same variable name:@arda-cards:registry=https://npm.pkg.github.com//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN} - Run
npm installas usual.
CI (GitHub Actions): do not commit a CI-specific .npmrc. Use actions/setup-node with registry-url to generate one at runtime, and pass the PAT as NODE_AUTH_TOKEN. The same committed .npmrc from local dev works because both use ${NODE_AUTH_TOKEN}:
- uses: actions/setup-node@v6 with: node-version: 22 registry-url: https://npm.pkg.github.com scope: '@arda-cards'- run: npm ci env: NODE_AUTH_TOKEN: ${{ secrets.GHP_READ_PACKAGES }}The setup-node step writes its own .npmrc to the runner’s home directory (which takes precedence over the repo-local one for the registry URL); npm ci then sees NODE_AUTH_TOKEN and authenticates.
If you prefer to use ${GITHUB_TOKEN} instead, that’s fine — but change both the shell export and the _authToken= line in .npmrc to match. Mixing the two names is what causes 401 Unauthorized on install.
Token rotation
Section titled “Token rotation”PATs expire. When yours does, install steps will fail with 401 Unauthorized from npm.pkg.github.com. Rotate by generating a new PAT and updating the env var or repo secret.
Version and tag conventions
Section titled “Version and tag conventions”Semver
Section titled “Semver”All published versions are valid semver 2.0. The CHANGELOG.md format and CLQ (Arda-cards/clq-action) enforce that the changelog version matches a valid semver progression.
Stable
Section titled “Stable”A stable version has the form X.Y.Z with no pre-release suffix:
| Example | Bump driver | CLQ status |
|---|---|---|
4.11.5 | Fixed / Security | released |
4.12.0 | Added / Deprecated | released |
5.0.0 | Changed / Removed | released |
Stable versions are published only by publish.yml on push to main, and always carry the npm dist-tag latest.
Pre-release (preview entries)
Section titled “Pre-release (preview entries)”A pre-release version has the form X.Y.Z-<author>-<id>:
| Example | Meaning |
|---|---|
4.12.0-alice-FD42 | Alice’s work toward 4.12.0, ticket FD-42 |
4.12.0-bob-spike-grid-virt | Bob’s spike toward 4.12.0, no ticket |
5.0.0-team-major-rewrite | Team-wide work toward a major version |
The <author>-<id> part is treated opaquely by the publish workflow — anything after the first - becomes the preview’s npm dist-tag.
Published preview artifact
Section titled “Published preview artifact”Each push of a pre-release entry publishes a uniquely versioned artifact by appending github.run_number:
4.12.0-alice-FD42 ← changelog entry (semver pre-release) ↓4.12.0-alice-FD42-7 ← published version (run #7 of publish-preview.yml) dist-tag: alice-FD42The dist-tag alice-FD42 always points at the most recent successful publish in the series.
Naming guidance
Section titled “Naming guidance”| Field | Recommendation |
|---|---|
<author> | Your GitHub username, lowercase. |
<id> | A ticket number (FD42), branch slug (grid-virt), or both. Keep short. Avoid generic names (fix, wip). |
| Combined dist-tag | Should be unique enough that a different dev’s preview can’t accidentally clobber yours. <gh-username>-<ticket> is safe. |
Reserved dist-tags
Section titled “Reserved dist-tags”latest— onlypublish.ymlupdates this. Never use as a preview dist-tag.next,canary,beta— currently unused; reserved for future graduated-preview workflows. Avoid.
Cleanup contract
Section titled “Cleanup contract”The cleanup-preview.yml workflow runs daily at 03:00 UTC (and on-demand via workflow_dispatch). It deletes obsolete preview versions from GitHub Packages.
What gets deleted
Section titled “What gets deleted”Two passes, each producing deletion candidates:
- Obsolete-stable pass: any preview
<base>-<series>-<uid>is marked when stable<base>exists in the registry.- Example: stable
4.12.0shipped → all4.12.0-*-*previews are marked.
- Example: stable
- Retention pass: previews whose stable base has not shipped are grouped by
<base>-<series>. Within each group, only the last 3 by<uid>are kept; the rest are marked.- Example: an active
alice-FD42series with 8 preview versions keeps versions 6, 7, 8 and marks 1-5 for deletion.
- Example: an active
Safety guards (in order)
Section titled “Safety guards (in order)”- Never delete stable: if any candidate has no pre-release suffix (i.e. matches
X.Y.Zonly), the entire job fails before any delete API call. - Pattern conformance: if any candidate doesn’t end in a numeric
-<uid>, the job fails. - 24-hour grace period: any version published less than 24 hours ago is exempt regardless of marking.
- Manual dispatch defaults to dry-run:
workflow_dispatchdefaultsdry_run=true, logging candidates without deleting. Scheduled runs perform real deletions.
Consumer impact
Section titled “Consumer impact”| Consumer state | Outcome of cleanup |
|---|---|
| Migrated to stable promptly after release | No impact |
| Still using a preview after stable shipped | Next install fails (404) within ~24h. Forces upgrade to stable. |
| In-flight CI run during cleanup | Protected by the 24h-since-publish guard |
| Active dev branch using a preview series with last-3 retention | Recent versions remain — re-running npm install @<series> picks the newest |
Operating procedure
Section titled “Operating procedure”- Before the first cron run in a fresh environment, dispatch the workflow manually with
dry_run=trueto validate logic against the actual registry state. - After modifying
cleanup-preview.yml, dry-run again before the next scheduled execution. - If a destructive bug is discovered, disable the workflow (Settings → Actions → Workflows → Disable) until the fix is verified via dry-run.
Related
Section titled “Related”Copyright: © Arda Systems 2025-2026, All rights reserved