Skip to content

fix(admin): restrict admin-only routes to administrators #8507

fix(admin): restrict admin-only routes to administrators

fix(admin): restrict admin-only routes to administrators #8507

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
typecheck:
name: Typecheck
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm typecheck
- run: pnpm run --filter emdash-demo --filter @emdash-cms/demo-cloudflare typecheck
- run: pnpm typecheck:templates
- run: node scripts/typecheck-public-source.mjs
- run: pnpm run --filter @emdash-cms/release-service --filter @emdash-cms/release-verifier --filter @emdash-cms/release-action typecheck
- run: pnpm run --filter @emdash-cms/release-service --filter @emdash-cms/release-verifier --filter @emdash-cms/release-action build
- run: git diff --exit-code -- apps/release-action/dist/index.js
- run: pnpm --dir apps/release-service exec wrangler types --check
- run: pnpm --dir apps/release-verifier exec wrangler types --check
- run: pnpm --dir apps/release-service exec wrangler deploy --dry-run
- run: pnpm --dir apps/release-verifier exec wrangler deploy --dry-run
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm lint
version-check:
name: Version Check
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
- run: node .github/scripts/check-no-major.mjs
changeset-validate:
name: Changeset Validation
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# changeset status --since diffs against origin/main; needs full history.
fetch-depth: 0
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Validate changesets
# GitHub tests pull_request events as a merge commit, so the working tree
# can contain changesets already on main. Diff against the merge base.
run: |
base=$(git merge-base origin/main HEAD)
added=$(git diff --name-only --diff-filter=d "$base" -- '.changeset/*.md' ':(exclude).changeset/README.md')
if [ -n "$added" ]; then
pnpm changeset status --since=origin/main
else
echo "No changesets added since origin/main; skipping validation."
fi
test-shards:
name: Test Shard (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
services:
postgres:
image: postgres:17
env:
POSTGRES_PASSWORD: test
POSTGRES_DB: emdash_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22.16.0
cache: pnpm
- run: pnpm install --frozen-lockfile
# Build emdash + its deps AND the plugin-cli + registry packages.
# They aren't deps of `emdash`, so the `emdash...` filter would
# leave them unbuilt and their tests would fail to resolve workspace
# links to dist/.
- run: pnpm run --filter emdash... --filter "@emdash-cms/aggregator" --filter "@emdash-cms/labeler" --filter "@emdash-cms/plugin-cli" --filter "@emdash-cms/registry-*" --filter "@emdash-cms/plugin-types" build
- run: pnpm --filter emdash exec vitest run --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
EMDASH_TEST_PG: postgres://postgres:test@localhost:5432/emdash_test
- name: Test other packages
if: matrix.shardIndex == 1
run: pnpm run --filter @emdash-cms/aggregator --filter @emdash-cms/auth --filter @emdash-cms/blocks --filter @emdash-cms/gutenberg-to-portable-text --filter @emdash-cms/labeler --filter @emdash-cms/marketplace --filter @emdash-cms/plugin-cli --filter @emdash-cms/plugin-forms --filter @emdash-cms/plugin-types --filter @emdash-cms/registry-client --filter @emdash-cms/registry-lexicons --filter @emdash-cms/registry-moderation test
env:
EMDASH_TEST_PG: postgres://postgres:test@localhost:5432/emdash_test
# Render tests use the Astro Vite plugin (vitest.repro.config.ts);
# they can't run under the plain-node config in test:unit.
- if: matrix.shardIndex == 1
run: pnpm --filter emdash exec vitest run --config vitest.repro.config.ts
- if: matrix.shardIndex == 1
run: pnpm run --filter @emdash-cms/release-service --filter @emdash-cms/release-verifier --filter @emdash-cms/release-action test
test:
name: Tests
if: always()
needs: [test-shards]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check test shard results
run: |
if [ "${{ needs.test-shards.result }}" != "success" ]; then
echo "Tests failed or were cancelled"
exit 1
fi
test-smoke:
name: Smoke Tests
runs-on: ubuntu-latest
timeout-minutes: 30
services:
postgres:
image: postgres:17
env:
POSTGRES_PASSWORD: test
POSTGRES_DB: emdash_smoke
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --filter emdash exec vitest run --config vitest.smoke.config.ts
env:
DATABASE_URL: postgres://postgres:test@localhost:5432/emdash_smoke
test-integration:
name: Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --filter emdash exec vitest run --config vitest.integration.config.ts
test-workerd:
name: D1 Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
# The suite imports the Cloudflare package, which resolves `emdash`
# through its published entry points rather than source.
- run: pnpm run --filter emdash... build
- run: pnpm --filter emdash exec vitest run --config vitest.workerd.config.ts
test-browser:
name: Browser Tests
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run --filter @emdash-cms/admin... --filter @emdash-cms/release-service... build
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm exec playwright install --with-deps chromium
if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: pnpm --filter @emdash-cms/release-service test:browser
- run: pnpm run --filter @emdash-cms/admin test
test-e2e-rollup:
name: E2E Tests
if: always()
needs: [test-e2e, test-e2e-table, test-e2e-cloudflare, test-e2e-playground]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check E2E results
run: |
if [ "${{ needs.test-e2e.result }}" != "success" ] ||
[ "${{ needs.test-e2e-table.result }}" != "success" ] ||
[ "${{ needs.test-e2e-cloudflare.result }}" != "success" ] ||
[ "${{ needs.test-e2e-playground.result }}" != "success" ]; then
echo "E2E tests failed or were cancelled"
exit 1
fi
test-e2e:
name: E2E tests (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
shardTotal: [8]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run --filter emdash... build
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm exec playwright install --with-deps chromium
if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: pnpm exec playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure()
with:
name: playwright-report-${{ matrix.shardIndex }}
path: |
playwright-report/
test-results/
retention-days: 7
test-e2e-table:
name: Table E2E (${{ matrix.browser }})
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run --filter emdash... build
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ matrix.browser }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm exec playwright install ${{ matrix.browser }}
if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: pnpm exec playwright install-deps ${{ matrix.browser }}
- run: pnpm run test:e2e:table --project=${{ matrix.browser }}
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure()
with:
name: playwright-table-${{ matrix.browser }}
path: |
playwright-report/
test-results/
retention-days: 7
test-e2e-playground:
name: Playground E2E
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run --filter "@emdash-cms/playground^..." build
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm exec playwright install --with-deps chromium
if: steps.playwright-cache.outputs.cache-hit != 'true'
- run: pnpm run test:e2e:playground
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure()
with:
name: playwright-report-playground
path: test-results/
retention-days: 7
test-e2e-cloudflare:
name: E2E Cloudflare (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
runs-on: ubuntu-latest
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
shardTotal: [8]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run --filter "emdash-e2e-fixture-cloudflare..." build
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm exec playwright install --with-deps chromium
if: steps.playwright-cache.outputs.cache-hit != 'true'
# Runs the full e2e suite against the workerd runtime. Sharded like the Node
# lane: per-shard setup (dev-server boot + seed) is ~30s, so wall-clock is
# dominated by test execution and shards parallelize it near-linearly.
- run: pnpm exec playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
EMDASH_E2E_TARGET: cloudflare
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure()
with:
name: playwright-report-cloudflare-${{ matrix.shardIndex }}
path: |
playwright-report/
test-results/
retention-days: 7