This document provides comprehensive information about deploying Kaiord packages and applications.
- Overview
- GitHub Pages Deployment (SPA)
- npm Package Publishing
- CI/CD Workflows
- Security Guidelines
- Troubleshooting
Kaiord uses automated CI/CD pipelines for:
- GitHub Pages: Automatic deployment of the Workout SPA Editor
- npm Publishing: Automated package releases to npm registry
- Security Scanning: Weekly vulnerability audits
- Version Management: Automated versioning with Changesets
All deployments are triggered automatically when changes are pushed to the main branch or when releases are created.
The Workout SPA Editor is deployed at: https://pablo-albaladejo.github.io/kaiord/
The deployment workflow (.github/workflows/deploy-spa-editor.yml) automatically runs when:
- Push to main: Changes are pushed to the
mainbranch - Relevant files changed:
packages/workout-spa-editor/**(SPA source files)packages/core/**(core package files).github/workflows/deploy-spa-editor.yml(workflow file)
- Manual trigger: Via GitHub Actions UI (workflow_dispatch)
1. Checkout code
↓
2. Setup pnpm + Node.js 20
↓
3. Install dependencies (frozen lockfile)
↓
4. Build @kaiord/core package
↓
5. Verify core build artifacts
↓
6. Build SPA with base path
↓
7. Verify SPA build artifacts
↓
8. Upload to GitHub Pages
↓
9. Deploy to production
The application automatically configures the base path based on the repository:
- User/Organization site (
username.github.io): Base path =/ - Project site (
username/repo): Base path =/repo/
For this repository (pablo-albaladejo/kaiord):
- Repository name:
kaiord - Owner:
pablo-albaladejo - Base path:
/kaiord/
To manually trigger a deployment:
- Go to Actions tab
- Select "Deploy Workout SPA Editor to GitHub Pages"
- Click "Run workflow"
- Select branch (usually
main) - Click "Run workflow" button
Test the deployment process locally:
# Make script executable (first time only)
chmod +x scripts/test-ci-workflows.sh
# Run all tests
./scripts/test-ci-workflows.shOr test manually:
# Build with production base path
VITE_BASE_PATH="/kaiord/" pnpm --filter @kaiord/workout-spa-editor build
# Preview locally
cd packages/workout-spa-editor/dist
python3 -m http.server 8000
# Visit http://localhost:8000/kaiord/Kaiord supports two publishing methods:
- Trusted Publishing (Recommended) - No tokens needed
- Token-Based Publishing (Legacy) - Uses npm automation tokens
Trusted Publishing uses OpenID Connect (OIDC) for authentication, eliminating the need for tokens.
- ✅ No secrets needed - Uses OIDC for authentication
- ✅ Automatic verification - npm verifies package origin
- ✅ Provenance attestation - Cryptographic proof of package source
- ✅ No token rotation - No tokens to expire or manage
- ✅ Better security - Eliminates token theft risk
Step 1: First Publish (Bootstrap)
For the first publish, you need to use a token or publish manually:
# Login to npm
npm login
# Build packages
pnpm -r build
# Publish manually
pnpm --filter @kaiord/core publish --access publicStep 2: Enable Trusted Publishing on npm
- Go to your package settings: https://www.npmjs.com/package/@kaiord/core
- Click on "Settings" tab
- Scroll to "Publishing access"
- Click "Configure trusted publishers"
- Add GitHub Actions as trusted publisher:
- Provider: GitHub Actions
- Repository owner:
pablo-albaladejo - Repository name:
kaiord - Workflow name:
release.yml(or leave empty) - Environment: (leave empty)
- Click "Add"
Step 3: Workflow Configuration
The workflow is already configured with:
permissions:
id-token: write # Required for npm provenance
contents: write
packages: write
jobs:
publish:
steps:
- name: Publish package
run: pnpm publish --provenance # Enables trusted publishingCheck if trusted publishing is enabled:
# View provenance for a published package
npm view @kaiord/core --json | jq '.dist.attestations'You should see provenance information with SLSA predicate type.
If you prefer using tokens, follow these steps:
pnpm setup:npmThe script will:
- Check if you're logged in to npm
- Guide you through token creation
- Configure GitHub secrets automatically
- Verify the setup
-
Create npm token:
- Go to https://www.npmjs.com/settings/[YOUR_USERNAME]/tokens/granular-access-tokens/new
- Token name:
kaiord-ci-cd - Expiration: 90 days (recommended)
- Packages: Select
@kaiord/corewith "Read and write" - Organizations: (leave empty)
- IP ranges: (leave empty)
- Click "Generate Token"
-
Add to GitHub:
- Go to repository Settings → Secrets and variables → Actions
- Click "New repository secret"
- Name:
NPM_TOKEN - Value: Paste the token
- Click "Add secret"
Tokens should be rotated every 90 days:
- Create new token with same configuration
- Update GitHub Secret
NPM_TOKENwith new token - Test that CI/CD works
- Revoke old token
Kaiord uses Changesets for version management and changelog generation.
When you make changes that should be included in the next release:
pnpm exec changesetThis will prompt you to:
- Select which packages have changed
- Choose the version bump type (major, minor, patch)
- Write a summary of the changes
-
Major (breaking change):
1.0.0→2.0.0- Breaking API changes
- Removed features
- Incompatible changes
-
Minor (new feature):
1.0.0→1.1.0- New features
- Backward-compatible additions
- New functionality
-
Patch (bug fix):
1.0.0→1.0.1- Bug fixes
- Documentation updates
- Performance improvements
- Create feature branch:
git checkout -b feature/new-feature - Make changes: Implement your feature
- Add changeset:
pnpm exec changeset - Commit:
git commit -am "feat: add new feature" - Push and create PR:
git push origin feature/new-feature - Merge to main: After PR approval
- Automatic PR creation: Changesets workflow creates "Version Packages" PR
- Review and merge: Review the version bumps and changelogs
- Automatic release: Release workflow publishes to npm
Kaiord uses several GitHub Actions workflows for automation:
Purpose: Validates code quality, runs tests, and generates coverage reports.
Triggers:
- Pull requests (opened, synchronize, reopened)
- Push to
mainbranch
Jobs:
detect-changes: Analyzes git diff to determine which packages need testinglint: Runs ESLint and Prettier checkstypecheck: Verifies TypeScript types compile without errorstest: Runs tests with coverage for affected packagesbuild: Verifies packages build successfully
Purpose: Scans dependencies for security vulnerabilities.
Triggers:
- Weekly schedule (Mondays at 9:00 AM UTC)
- Pull requests that modify
package.jsonorpnpm-lock.yaml - Manual dispatch
Behavior by Severity:
| Severity | Workflow Status | GitHub Issue | PR Comment |
|---|---|---|---|
| Critical | ❌ Fail | ✅ Yes | ✅ Yes |
| High | ❌ Fail | ✅ Yes | ✅ Yes |
| Moderate | ❌ No | ✅ Yes | |
| Low | ❌ No | ✅ Yes |
Purpose: Automates version bumping and changelog generation.
Triggers:
- Push to
mainbranch
Jobs:
version: Creates or updates "Version Packages" PR- Generates changelogs based on changeset files
- Triggers release workflow when PR is merged
Purpose: Builds and publishes packages to npm when a release is created.
Triggers:
- Release published event
Jobs:
publish: Builds packages and publishes to npm registry- Creates GitHub deployment
- Updates README badges
┌─────────────────────────────────────────────────────────────┐
│ Pull Request / Push to Main │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ CI Workflow (ci.yml) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ detect- │ │ lint │ │ typecheck │ │
│ │ changes │→ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ test │ │ build │ │
│ │ (matrix) │ │ │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Merge to Main │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Changesets Workflow (changesets.yml) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Creates/Updates "Version Packages" PR │ │
│ │ - Bumps versions │ │
│ │ - Generates changelogs │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Merge "Version Packages" PR │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Create GitHub Release │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Release Workflow (release.yml) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Publishes packages to npm │ │
│ │ - @kaiord/core │ │
│ │ - @kaiord/cli │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Purpose: Authenticates with npm registry for publishing packages.
Required: Only if using token-based publishing (not needed for trusted publishing)
Setup:
- Create npm token (see Token-Based Publishing section)
- Add to GitHub: Settings → Secrets and variables → Actions
- Name:
NPM_TOKEN - Value: Paste the token
Purpose: Uploads coverage reports to Codecov.
Required: Only for private repositories (optional for public)
Setup:
- Sign up at codecov.io
- Add your repository
- Copy the upload token
- Add to GitHub: Settings → Secrets and variables → Actions
- Name:
CODECOV_TOKEN - Value: Paste the token
All workflows use minimal required permissions:
permissions:
contents: read # Read repository contents
pages: write # Deploy to GitHub Pages (SPA only)
id-token: write # OIDC authentication (trusted publishing)
issues: write # Create security issues (audit only)
pull-requests: write # Comment on PRs (audit only)- ✅ Never log secrets - Secrets are masked in workflow logs
- ✅ Use GitHub Secrets - Store tokens in repository secrets
- ✅ Rotate regularly - Rotate tokens every 90 days
- ✅ Least privilege - Use granular tokens with minimal permissions
- ✅ Audit access - Review secret access regularly
The security audit workflow runs weekly and on dependency changes:
# Run audit locally
pnpm audit
# With specific level
pnpm audit --audit-level=moderate
# JSON output
pnpm audit --jsonWhen vulnerabilities are found:
-
Review vulnerabilities:
pnpm audit
-
Update dependencies:
pnpm update
-
Test changes:
pnpm test pnpm build -
Commit and push:
git add package.json pnpm-lock.yaml git commit -m "fix: update dependencies to address security vulnerabilities" git push
Symptom: Site loads but CSS/JS files return 404
Cause: Incorrect base path configuration
Solution:
-
Check base path in workflow:
env: VITE_BASE_PATH: /kaiord/
-
Verify in index.html:
grep 'src="' packages/workout-spa-editor/dist/index.html -
Rebuild with correct base path:
VITE_BASE_PATH="/kaiord/" pnpm --filter @kaiord/workout-spa-editor build
Symptom: SPA build fails with module resolution error
Cause: Core package not built before SPA build
Solution:
# Build core first
pnpm --filter @kaiord/core build
# Then build SPA
pnpm --filter @kaiord/workout-spa-editor buildSymptom: Release workflow fails during package publishing
Possible causes:
- Invalid or expired
NPM_TOKEN - Trusted publishing not configured on npm
- Insufficient permissions on npm package
Solution:
For trusted publishing:
- Go to npm package settings
- Configure trusted publisher (see Trusted Publishing section)
- Re-run the workflow
For token-based:
# Verify token locally
npm whoami --registry https://registry.npmjs.org
# Check package access
npm access list packages
# Regenerate token if needed
npm token create --type=automationSymptom: Workflow fails with 401 error
Cause: Missing id-token: write permission (trusted publishing)
Solution: Verify workflow has:
permissions:
id-token: writeSymptom: Tests succeed on your machine but fail in GitHub Actions
Possible causes:
- Environment differences (Node version, OS)
- Missing environment variables
- Timezone differences
Solution:
# Test with act (local GitHub Actions runner)
brew install act
act -j test
# Or match CI environment
docker run -it node:24-alpine shSymptom: Workflow doesn't start, remains queued indefinitely
Possible causes:
- GitHub Actions quota exceeded (for private repos)
- Too many concurrent workflows
- Runner availability issues
Solution:
- Check Actions usage: Settings → Billing → Actions
- Cancel unnecessary workflow runs
- Wait for runners to become available
- Check GitHub status: githubstatus.com
Symptom: Security workflow fails even though vulnerabilities are low/moderate
Solution:
Review the audit configuration in security.yml:
run: pnpm audit --audit-level=highUpdate dependencies:
pnpm updateCheck for available patches:
pnpm audit fix-
Test locally:
./scripts/test-ci-workflows.sh
-
Run tests:
pnpm -r test -
Check linting:
pnpm -r lint
-
Verify build:
pnpm -r build
- Use feature branches - Don't push directly to
main - Test in PR - Create PR to see CI checks before merging
- Review workflow logs - Check Actions tab after merge
- Verify deployment - Test live site/packages after deployment
- Check deployment status - After each push to
main - Test live site - Verify functionality works correctly
- Monitor errors - Check browser console for JavaScript errors
- Review logs - Periodically review workflow logs for warnings
- Getting Started - Quick start guide
- Architecture - System architecture overview
- Testing - Testing guidelines
- Contributing - Contribution guidelines
- GitHub Pages Documentation
- GitHub Actions Documentation
- npm Publishing Guide
- npm Provenance Documentation
- Changesets Documentation
- Vite Deployment Guide
If you encounter issues not covered in this guide:
- Check workflow logs in GitHub Actions tab
- Search existing issues in the repository
- Review GitHub Actions status page
- Ask in repository discussions
- Contact repository maintainers