fix: convert apps/website from submodule to regular directory

This commit is contained in:
yeuimu
2026-07-16 01:42:45 +08:00
parent f12ae12ad3
commit 9595030625
341 changed files with 50808 additions and 1 deletions
@@ -0,0 +1,265 @@
# CI Workflows
## Basic CI
```yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm lint
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm typecheck
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm test
```
## Matrix Testing
```yaml
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest]
node: [20, 22, 24]
include:
- os: macos-latest
node: 24
- os: windows-latest
node: 24
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- run: pnpm install
- run: pnpm test
```
## Skip Docs-Only Changes
```yaml
jobs:
changed:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.check.outputs.only_changed == 'true' }}
steps:
- uses: tj-actions/changed-files@v47
id: check
with:
files: |
docs/**
**.md
test:
needs: changed
if: needs.changed.outputs.should_skip != 'true'
# ... rest of job
```
## Auto-fix Commits
```yaml
- run: pnpm lint:fix
- uses: stefanzweifel/git-auto-commit-action@v5
if: github.event_name == 'push'
with:
commit_message: 'chore: lint fix'
```
## Release on Tag (Token-based)
```yaml
# .github/workflows/release.yml
name: Release
on:
push:
tags: ['v*']
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
registry-url: https://registry.npmjs.org
- run: pnpm install
- run: pnpm build
- run: pnpm publish --access public --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
## Release on Tag (OIDC - Recommended)
No NPM_TOKEN needed. Uses GitHub OIDC for tokenless auth with provenance.
```yaml
name: Release
permissions:
id-token: write
contents: write
actions: read
on:
push:
tags: ['v*']
jobs:
wait-for-ci:
runs-on: ubuntu-latest
steps:
- uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.sha }}
check-name: ci
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
release:
needs: wait-for-ci
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24 # Required: npm 11.5.1+
cache: pnpm
registry-url: https://registry.npmjs.org
- run: pnpm install
- run: pnpm build
- run: pnpm dlx changelogithub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: pnpm publish --access public --no-git-checks --provenance
```
### OIDC Setup Steps
1. Open `https://www.npmjs.com/package/<PACKAGE_NAME>/access`
2. Scroll to "Publishing access" section
3. Click "Add GitHub Actions" under Trusted Publishers
4. Fill: Owner, Repository, Workflow file (`release.yml`), Environment (empty)
5. Click "Add"
### OIDC Requirements
1. **Node.js 24+** (npm 11.5.1+ required - Node 22 has npm 10.x which fails)
2. **Permissions**: `id-token: write`
3. **Publish flag**: `--provenance`
4. **package.json**: must have `repository` field
5. **npm 2FA**: "Require 2FA or granular access token" (allows OIDC)
### Troubleshooting
| Error | Cause | Fix |
| ------------------------------------- | -------------------- | ----------------------------------------- |
| "Access token expired" E404 | npm too old | Use Node.js 24 |
| ENEEDAUTH | Missing registry-url | Add `registry-url` to setup-node |
| "repository.url is empty" E422 | Missing field | Add `repository` to package.json |
| "not configured as trusted publisher" | Config mismatch | Check owner, repo, workflow match exactly |
## Monorepo Matrix
```yaml
jobs:
test:
strategy:
matrix:
package: [core, utils, cli]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm --filter ${{ matrix.package }} test
```
## Concurrency Control
Cancel outdated runs:
```yaml
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: true
```
## pkg-pr-new for PRs
```yaml
# .github/workflows/pkg-pr-new.yml
name: Publish PR
on: pull_request
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm build
- run: pnpm dlx pkg-pr-new publish --compact --pnpm
```
## Package Validation in CI
```yaml
- run: pnpm build
- run: pnpm dlx publint
- run: pnpm dlx @arethetypeswrong/cli --pack .
```
@@ -0,0 +1,180 @@
# Release Workflow
## Tools
| Tool | Purpose |
| ----------- | --------------------------------- |
| bumpp | Interactive version bumping |
| changelogen | Changelog generation from commits |
| pkg-pr-new | PR preview packages |
## bumpp (Version Bumping)
```bash
pnpm add -D bumpp
```
```json
{
"scripts": {
"release": "bumpp"
}
}
```
Interactive prompt for patch/minor/major. Options:
```json
{
"scripts": {
"release": "bumpp --commit --tag --push"
}
}
```
For monorepos:
```bash
bumpp -r # Recursive
bumpp packages/*/package.json # Specific packages
```
## changelogen (Changelog)
```bash
pnpm add -D changelogen
```
```json
{
"scripts": {
"changelog": "changelogen --release"
}
}
```
Combined workflow:
```json
{
"scripts": {
"release": "changelogen --release && bumpp"
}
}
```
## Full Release Flow
```json
{
"scripts": {
"release": "pnpm lint && pnpm test && changelogen --release && bumpp --commit --tag --push"
}
}
```
CI publishes to npm on tag push.
## pkg-pr-new (PR Previews)
For publishable packages. Creates install links on PRs.
```yaml
# .github/workflows/pkg-pr-new.yml
name: Publish PR
on: pull_request
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install
- run: pnpm build
- run: pnpm dlx pkg-pr-new publish --compact --pnpm
```
For monorepos:
```bash
pnpm dlx pkg-pr-new publish --compact --pnpm './packages/*'
```
PR comment shows:
```
pnpm add https://pkg.pr.new/your-org/your-package@123
```
## Conventional Commits
For changelogen to work:
```
feat: add dark mode support
fix: resolve memory leak in parser
docs: update README
chore: update dependencies
```
## npm Publishing
### Token-based (legacy)
```yaml
- run: pnpm publish --access public --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
### OIDC (Recommended)
No token needed. See ci-workflows.md for full setup.
```yaml
- run: pnpm publish --access public --no-git-checks --provenance
```
## Monorepo Publishing
With pnpm:
```bash
pnpm -r publish --access public
```
With bumpp:
```bash
bumpp -r && pnpm -r publish
```
## Pre-release Versions
```bash
bumpp --preid beta # 1.0.0 -> 1.0.1-beta.0
bumpp --preid alpha # 1.0.0 -> 1.0.1-alpha.0
```
## Package.json Requirements
```json
{
"name": "@scope/package",
"version": "1.0.0",
"repository": {
"type": "git",
"url": "git+https://github.com/org/repo.git"
},
"publishConfig": {
"access": "public"
}
}
```
`repository` required for npm provenance.
@@ -0,0 +1,201 @@
# Testing
## Vitest Setup
```bash
pnpm add -D vitest
```
### Basic Config
```typescript
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
include: ['test/**/*.test.ts'],
testTimeout: 30_000,
reporters: 'dot',
},
})
```
### With Coverage
```typescript
export default defineConfig({
test: {
coverage: {
provider: 'v8',
include: ['src/**/*.ts'],
exclude: ['src/types.ts'],
reporter: ['text', 'lcovonly', 'html'],
},
},
})
```
## Workspace Projects
For monorepos, test packages separately:
```typescript
export default defineConfig({
test: {
projects: [
'packages/*/vitest.config.ts',
{
extends: './vitest.config.ts',
test: { name: 'unit', environment: 'node' },
},
{
extends: './vitest.config.ts',
test: { name: 'browser', browser: { enabled: true } },
},
],
},
})
```
## Fixture-Based Testing
Test transforms with file fixtures:
```typescript
import { describe, expect, it } from 'vitest'
import { transform } from '../src'
const fixtures = import.meta.glob('./fixtures/*.ts', { as: 'raw' })
describe('transform', () => {
for (const [path, getContent] of Object.entries(fixtures)) {
it(path, async () => {
const content = await getContent()
const result = await transform(content)
expect(result).toMatchSnapshot()
})
}
})
```
## Idempotency Testing
Ensure transforms are stable:
```typescript
it('transform is idempotent', async () => {
const pass1 = (await transform(fixture))?.code ?? fixture
expect(pass1).toMatchSnapshot()
const pass2 = (await transform(pass1))?.code ?? pass1
expect(pass2).toBe(pass1) // Should not change
})
```
## Type-Level Testing
Test TypeScript types:
```typescript
// vitest.config.ts
export default defineConfig({
test: {
typecheck: { enabled: true },
},
})
```
```typescript
// test/types.test-d.ts
import { describe, expectTypeOf, it } from 'vitest'
import type { Input, Output } from '../src'
describe('types', () => {
it('infers input correctly', () => {
expectTypeOf<Input<typeof schema>>().toEqualTypeOf<{ id: string }>()
})
})
```
## Multi-TS Version Testing
Test across TypeScript versions (TanStack pattern):
```yaml
# .github/workflows/ci.yml
jobs:
test-types:
strategy:
matrix:
ts: ['5.0', '5.2', '5.4', '5.6', '5.8']
steps:
- run: pnpm add -D typescript@${{ matrix.ts }}
- run: pnpm typecheck
```
## Package Validation
Validate published package:
```bash
# Check exports are correct
pnpm dlx publint
# Check types work in different moduleResolutions
pnpm dlx @arethetypeswrong/cli --pack .
```
Add to tsdown config:
```typescript
export default defineConfig({
attw: { profile: 'esm-only' }, // or 'node16'
})
```
## Test Scripts
```json
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage",
"test:types": "vitest typecheck"
}
}
```
## Mocking
```typescript
import { vi } from 'vitest'
vi.mock('fs', () => ({
readFileSync: vi.fn(() => 'mocked content'),
}))
// Spy on method
const spy = vi.spyOn(console, 'log')
expect(spy).toHaveBeenCalledWith('expected')
```
## Testing Plugins
Dogfood your own plugin in tests:
```typescript
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import MyPlugin from './src/vite'
export default defineConfig({
plugins: [
MyPlugin({ /* options */ }),
],
test: {
include: ['test/**/*.test.ts'],
},
})
```