1
0

ci.yml 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. name: CI
  2. on:
  3. pull_request:
  4. paths:
  5. - "**.go"
  6. - "go.mod"
  7. - "go.sum"
  8. - "frontend/**"
  9. - ".nvmrc"
  10. - ".github/workflows/ci.yml"
  11. push:
  12. branches:
  13. - main
  14. paths:
  15. - "**.go"
  16. - "go.mod"
  17. - "go.sum"
  18. - "frontend/**"
  19. - ".nvmrc"
  20. - ".github/workflows/ci.yml"
  21. permissions:
  22. contents: read
  23. jobs:
  24. go-test:
  25. runs-on: ubuntu-latest
  26. steps:
  27. - uses: actions/checkout@v7
  28. - uses: actions/setup-go@v7
  29. with:
  30. go-version-file: go.mod
  31. cache: true
  32. - name: Stub internal/web/dist for go:embed
  33. run: mkdir -p internal/web/dist && touch internal/web/dist/.gitkeep
  34. - name: Test
  35. run: |
  36. go list ./... | grep -v '/frontend/node_modules/' > /tmp/go-packages.txt
  37. go test -shuffle=on -count=1 $(cat /tmp/go-packages.txt)
  38. postgres-durable-first:
  39. runs-on: ubuntu-latest
  40. services:
  41. postgres:
  42. image: postgres:16
  43. env:
  44. POSTGRES_USER: postgres
  45. POSTGRES_PASSWORD: postgres
  46. POSTGRES_DB: xui_durable
  47. ports:
  48. - 5432:5432
  49. options: >-
  50. --health-cmd "pg_isready -U postgres -d xui_durable"
  51. --health-interval 10s
  52. --health-timeout 5s
  53. --health-retries 5
  54. env:
  55. XUI_DB_TYPE: postgres
  56. XUI_DB_DSN: "host=127.0.0.1 port=5432 user=postgres password=postgres dbname=xui_durable sslmode=disable"
  57. steps:
  58. - uses: actions/checkout@v7
  59. - uses: actions/setup-go@v7
  60. with:
  61. go-version-file: go.mod
  62. cache: true
  63. - name: Stub internal/web/dist for go:embed
  64. run: mkdir -p internal/web/dist && touch internal/web/dist/.gitkeep
  65. - name: PostgreSQL durable-first tests
  66. run: |
  67. set -o pipefail
  68. go test ./internal/web/service -run 'PostgresCommitFailure' -count=1 -v | tee /tmp/postgres-durable-first.log
  69. # Count passes rather than assert no SKIP: a renamed or deleted test
  70. # prints "no tests to run" and exits 0, leaving the step green for nothing.
  71. passed=$(grep -c -- '--- PASS' /tmp/postgres-durable-first.log || true)
  72. if [ "$passed" -lt 1 ]; then
  73. echo "expected at least 1 passing durable-first test, got $passed" >&2
  74. exit 1
  75. fi
  76. - name: PostgreSQL schema and migration tests
  77. run: |
  78. set -o pipefail
  79. go test ./internal/database -run '^(TestHostAutoMigrateCreatesColumns_Postgres|TestMigrate_Postgres)$' -count=1 -v | tee /tmp/postgres-schema.log
  80. # Both must pass. Counting, not SKIP-matching: renaming either test would
  81. # otherwise leave this step green while testing nothing.
  82. passed=$(grep -c -- '--- PASS' /tmp/postgres-schema.log || true)
  83. if [ "$passed" -lt 2 ]; then
  84. echo "expected 2 passing PostgreSQL schema tests, got $passed" >&2
  85. exit 1
  86. fi
  87. codegen:
  88. runs-on: ubuntu-latest
  89. steps:
  90. - uses: actions/checkout@v7
  91. - uses: actions/setup-go@v7
  92. with:
  93. go-version-file: go.mod
  94. cache: true
  95. - uses: actions/setup-node@v7
  96. with:
  97. node-version-file: .nvmrc
  98. - name: Regenerate schemas, examples and OpenAPI
  99. run: npm run gen
  100. working-directory: frontend
  101. - name: Fail if generated files are stale (run 'npm run gen' and commit)
  102. run: git diff --exit-code -- frontend/src/generated frontend/public/openapi.json
  103. govulncheck:
  104. runs-on: ubuntu-latest
  105. steps:
  106. - uses: actions/checkout@v7
  107. - uses: actions/setup-go@v7
  108. with:
  109. go-version-file: go.mod
  110. cache: true
  111. - name: Stub internal/web/dist for go:embed
  112. run: mkdir -p internal/web/dist && touch internal/web/dist/.gitkeep
  113. - name: Install govulncheck
  114. run: go install golang.org/x/vuln/cmd/govulncheck@latest
  115. - name: Run govulncheck
  116. run: govulncheck ./...
  117. # Race + shuffle hygiene gate: data races and order-dependent tests fail the build.
  118. race:
  119. runs-on: ubuntu-latest
  120. steps:
  121. - uses: actions/checkout@v7
  122. - uses: actions/setup-go@v7
  123. with:
  124. go-version-file: go.mod
  125. cache: true
  126. - name: Stub internal/web/dist for go:embed
  127. run: mkdir -p internal/web/dist && touch internal/web/dist/.gitkeep
  128. - name: Race + shuffle
  129. run: |
  130. go list ./... | grep -v '/frontend/node_modules/' > /tmp/go-packages.txt
  131. go test -race -shuffle=on -count=1 $(cat /tmp/go-packages.txt)
  132. # Brief native-fuzz smoke on the security-/parser-critical decoders. Each runs the
  133. # generated corpus plus 30s of exploration; a crash here is a real input-handling bug.
  134. fuzz-smoke:
  135. runs-on: ubuntu-latest
  136. steps:
  137. - uses: actions/checkout@v7
  138. - uses: actions/setup-go@v7
  139. with:
  140. go-version-file: go.mod
  141. cache: true
  142. - name: Stub internal/web/dist for go:embed
  143. run: mkdir -p internal/web/dist && touch internal/web/dist/.gitkeep
  144. - name: Fuzz critical parsers (smoke)
  145. run: |
  146. go test -run '^$' -fuzz 'FuzzParseLink$' -fuzztime=30s ./internal/util/link/
  147. go test -run '^$' -fuzz 'FuzzDecodeCertPin$' -fuzztime=30s ./internal/web/runtime/
  148. golangci:
  149. runs-on: ubuntu-latest
  150. steps:
  151. - uses: actions/checkout@v7
  152. - uses: actions/setup-go@v7
  153. with:
  154. go-version-file: go.mod
  155. cache: true
  156. - name: Stub internal/web/dist for go:embed
  157. run: mkdir -p internal/web/dist && touch internal/web/dist/.gitkeep
  158. - name: golangci-lint
  159. uses: golangci/golangci-lint-action@v9
  160. with:
  161. version: latest
  162. frontend:
  163. runs-on: ubuntu-latest
  164. steps:
  165. - uses: actions/checkout@v7
  166. - uses: actions/setup-node@v7
  167. with:
  168. node-version-file: .nvmrc
  169. cache: npm
  170. cache-dependency-path: frontend/package-lock.json
  171. - name: Install
  172. run: npm ci
  173. working-directory: frontend
  174. - name: Lint
  175. run: npm run lint
  176. working-directory: frontend
  177. - name: Typecheck
  178. run: npm run typecheck
  179. working-directory: frontend
  180. - name: Install Playwright Chromium (Storybook story tests)
  181. run: npx playwright install --with-deps chromium
  182. working-directory: frontend
  183. - name: Test
  184. run: npm test
  185. working-directory: frontend
  186. - name: Build
  187. run: npm run build
  188. working-directory: frontend
  189. - name: Build Storybook
  190. run: npm run build-storybook
  191. working-directory: frontend
  192. - name: Audit
  193. run: npm audit --omit=dev --audit-level=high
  194. working-directory: frontend