preview-workflow.spec.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import { readFileSync } from 'node:fs'
  2. import { resolve } from 'node:path'
  3. import * as yaml from 'js-yaml'
  4. import { describe, expect, it } from 'vitest'
  5. const workflow = yaml.load(readFileSync(resolve(import.meta.dirname, '../.github/workflows/build-preview-cloudflare.yml'), 'utf8')) as {
  6. on: unknown
  7. permissions: unknown
  8. concurrency: unknown
  9. env: Record<string, string>
  10. jobs: Record<'preview', {
  11. 'runs-on': string
  12. steps: Array<{ name?: string; uses?: string; run?: string; with?: Record<string, unknown>; env?: Record<string, string> }>
  13. }>
  14. }
  15. const preview = workflow.jobs.preview
  16. describe('PR preview workflow', () => {
  17. it('keeps every PR author on the selected GitHub-hosted runner', () => {
  18. expect(Object.keys(workflow.jobs)).toEqual(['preview'])
  19. expect(preview['runs-on']).toBe('ubuntu-24.04')
  20. expect(workflow.on).toEqual({ pull_request: { types: ['opened', 'synchronize', 'reopened'] } })
  21. expect(workflow.permissions).toEqual({ contents: 'read', 'pull-requests': 'write' })
  22. expect(preview.steps.find(step => step.uses === 'actions/checkout@v6')?.with).toEqual({ 'persist-credentials': false })
  23. })
  24. it('keeps the immutable full build and restore-only dependency cache', () => {
  25. expect(workflow.env.PRIMARY_NODE_VERSION).toBe('24')
  26. expect(workflow.env.DSH_TELEMETRY_DISABLED).toBe('1')
  27. const commands = preview.steps.map(step => step.run)
  28. expect(commands).toContain('pnpm install --frozen-lockfile')
  29. expect(commands).toContain('pnpm run build')
  30. expect(commands).toContain('pnpm --filter @deepseek-ai/dsh-web-frontend run build:preview')
  31. expect(commands.indexOf('pnpm run build')).toBeLessThan(commands.indexOf('pnpm --filter @deepseek-ai/dsh-web-frontend run build:preview'))
  32. expect(preview.steps.filter(step => step.uses?.startsWith('actions/cache'))).toHaveLength(1)
  33. expect(preview.steps.find(step => step.uses === 'actions/cache/restore@v4')?.with).toMatchObject({
  34. key: "${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}",
  35. })
  36. })
  37. it('retains per-PR deployment, protected image verification, and idempotent URL comments', () => {
  38. expect(workflow.concurrency).toEqual({
  39. group: 'build-preview-cloudflare-${{ github.event.pull_request.number }}',
  40. 'cancel-in-progress': true,
  41. })
  42. expect(workflow.env.CF_PROJECT).toBe('dsh-build-preview')
  43. const shape = preview.steps.find(step => step.name === 'Shape the upload')!
  44. expect(shape.run).toContain("find apps/web/dist -name '*.map' -delete")
  45. expect(shape.run).toContain('cp apps/web/dist/preview.html apps/web/dist/index.html')
  46. const deploy = preview.steps.find(step => step.name === 'Upload to Cloudflare Pages')!
  47. expect(deploy.run).toContain('npx --yes wrangler@4 pages deploy apps/web/dist')
  48. expect(deploy.run).toContain('--branch "pr-${{ github.event.pull_request.number }}"')
  49. const verify = preview.steps.find(step => step.name === 'Verify the protected deployment serves the image')!
  50. expect(verify.run).toContain('/preview/vfs-image.tar.gz')
  51. expect(verify.run).toContain('"$code" != "200"')
  52. expect(verify.run).toContain('content-encoding:')
  53. expect(verify.run).toContain('"$magic" != "1f8b"')
  54. expect(verify.env?.CF_ACCESS_CLIENT_SECRET).toBe('${{ secrets.CF_ACCESS_CLIENT_SECRET }}')
  55. const comment = preview.steps.find(step => step.name === 'Comment the preview URL')!
  56. expect(comment.run).toContain('<!-- dsh-preview-url -->')
  57. expect(comment.run).toContain('gh pr comment "$PR" --body-file -')
  58. })
  59. })