Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# ===============================================================
# 🧩 Server Lint & Test - BFF Quality Gate
# 🧩 BFF Typecheck & Unit Tests
# ===============================================================
# - runs typecheck and Vitest for the BFF (server/)
# - runs on PRs and pushes to main
# ---------------------------------------------------------------

name: Server Lint & Test
name: BFF Typecheck & Unit Tests

on:
push:
branches: ["main"]
pull_request:
types: [opened, synchronize, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review]
branches: ["main"]

concurrency:
Expand All @@ -22,32 +22,32 @@ permissions:
contents: read

jobs:
lint-and-test:
typecheck-and-test:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
name: Lint & Test Server
name: BFF typecheck and unit tests
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: server

steps:
- name: ⬇️ Checkout source
- name: Checkout source
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
with:
persist-credentials: false
fetch-depth: 1

- name: 🟩 Setup Node
- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
node-version-file: ".nvmrc"

- name: 📥 Install dependencies
- name: Install dependencies
run: npm ci --no-audit --no-fund

- name: 🔍 Typecheck
run: npm run lint
- name: Typecheck
run: npm run typecheck

- name: 🧪 Run tests with Vitest
run: npm run test:run
- name: Run tests with Vitest
run: npm test
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# ===============================================================
# 🧬 Client Type Generation - verify generated types stay in sync
# 🧬 Client Build & Typecheck - validate generated API code
# ===============================================================
# - regenerates src/generated/ from the committed openapi.json
# - verifies types exist, compile, and the app builds
# ---------------------------------------------------------------

name: Client Type Generation
name: Client Build & Typecheck

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
types: [opened, synchronize, reopened, ready_for_review]
Expand All @@ -21,14 +23,15 @@ concurrency:
cancel-in-progress: true

jobs:
generate-types:
build-client:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
name: Generate, verify, and build types
name: Client build and typecheck
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
- name: Checkout source
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
with:
persist-credentials: false

Expand All @@ -40,16 +43,10 @@ jobs:
- name: Install dependencies
run: npm ci --no-audit --no-fund

- name: Generate types with orval
run: npm run generate
- name: Generate API code, typecheck, and build client
run: npm run build

- name: Verify generated types exist
run: |
test -d src/generated/types || (echo "ERROR: src/generated/types/ not created" && exit 1)
echo "Generated types count: $(find src/generated/types -name '*.ts' | wc -l)"

- name: Verify generated types compile
run: npx tsc -b --noEmit

- name: Build
run: npm run build
28 changes: 14 additions & 14 deletions .github/workflows/client-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
# - triggered on PRs and pushes to main
# ---------------------------------------------------------------

name: Client E2E (Playwright)
name: Client E2E (Mocked API)

on:
push:
branches: ["main"]
pull_request:
types: [opened, synchronize, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review]
branches: ["main"]

concurrency:
Expand All @@ -26,7 +26,7 @@ permissions:
jobs:
playwright:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
name: Playwright smoke + auth
name: Playwright mocked API tests
runs-on: ubuntu-latest
timeout-minutes: 30

Expand All @@ -35,24 +35,24 @@ jobs:
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.playwright-browsers

steps:
- name: ⬇️ Checkout source
- name: Checkout source
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
with:
persist-credentials: false
fetch-depth: 1

- name: 🟩 Setup Node
- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version-file: ".nvmrc"

- name: 📥 Install dependencies
- name: Install dependencies
run: npm ci --no-audit --no-fund

- name: ⚙️ Generate types with orval
run: npm run generate
- name: Generate API code
run: npm run api:generate

- name: 🎭 Cache Playwright browsers
- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
Expand All @@ -61,18 +61,18 @@ jobs:
restore-keys: |
${{ runner.os }}-playwright-

- name: 🎭 Install Playwright browsers
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps chromium

- name: 🎭 Install Playwright system deps (cached browsers)
- name: Install Playwright system deps (cached browsers)
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: npx playwright install-deps chromium

- name: 🧪 Run Playwright tests
- name: Run Playwright tests
run: npm run e2e

- name: 📦 Upload Playwright HTML report
- name: Upload Playwright HTML report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
Expand All @@ -81,7 +81,7 @@ jobs:
retention-days: 7
if-no-files-found: ignore

- name: 📦 Upload Playwright traces on failure
- name: Upload Playwright traces on failure
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,30 +49,30 @@ jobs:
id-token: write # Cosign keyless (OIDC) signing

steps:
- name: ⬇️ Checkout source
- name: Checkout source
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
with:
persist-credentials: false

- name: 🔡 Set image name lowercase
- name: Set image name lowercase
run: |
IMAGE_NAME_LC=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
echo "IMAGE_NAME_LC=${IMAGE_NAME_LC}" >> "${GITHUB_ENV}"

- name: 🧰 Set up QEMU (arm64 emulation)
- name: Set up QEMU (arm64 emulation)
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0

- name: 🧰 Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

- name: 🔐 Log in to GHCR
- name: Log in to GHCR
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: 🏷️ Extract image metadata
- name: Extract image metadata
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
Expand All @@ -84,15 +84,15 @@ jobs:
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}

- name: ✅ Validate derived tags
- name: Validate derived tags
run: |
set -euo pipefail
if [ -z "${{ steps.meta.outputs.tags }}" ]; then
echo "::error::No image tags derived from ref '${{ github.ref_name }}'. Expected strict semver (vX.Y.Z or vX.Y.Z-prerelease)."
exit 1
fi

- name: 🏗️ Build & push image
- name: Build & push image
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
Expand All @@ -112,10 +112,10 @@ jobs:
build-args: |
${{ github.event.inputs.nodejs_image && format('NODEJS_IMAGE={0}', github.event.inputs.nodejs_image) || '' }}

- name: 🔏 Install Cosign
- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: 🔏 Sign published tags (keyless OIDC)
- name: Sign published tags (keyless OIDC)
env:
COSIGN_EXPERIMENTAL: "1"
run: |
Expand All @@ -125,14 +125,14 @@ jobs:
echo "Signing ${IMAGE}@${DIGEST}"
cosign sign --yes "${IMAGE}@${DIGEST}"

- name: 📋 Generate SBOM
- name: Generate SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}@${{ steps.build.outputs.digest }}
output-file: sbom.spdx.json
upload-artifact: false

- name: 📦 Create GitHub Release
- name: Create GitHub Release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ github.ref_name }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# ===============================================================
# ⚛️ Client Lint & Test - React Frontend Quality Gate
# ⚛️ Repository Quality & Client Unit Tests
# ===============================================================
# - runs ESLint, Prettier, and Vitest for the React client
# - runs repository-wide ESLint and Prettier, plus client Vitest coverage
# - ensures code quality and test coverage for frontend
# - runs on PRs and pushes to main
# ---------------------------------------------------------------

name: Client Lint & Test
name: Repository Quality & Client Unit Tests

on:
push:
branches: ["main"]
pull_request:
types: [opened, synchronize, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review]
branches: ["main"]

concurrency:
Expand All @@ -23,35 +23,35 @@ permissions:
contents: read

jobs:
lint-and-test:
quality-and-client-tests:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
name: Lint & Test Client
name: Repository quality and client unit tests
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- name: ⬇️ Checkout source
- name: Checkout source
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
with:
persist-credentials: false
fetch-depth: 1

- name: 🟩 Setup Node
- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version-file: ".nvmrc"

- name: 📥 Install dependencies
- name: Install dependencies
run: npm ci --no-audit --no-fund

- name: ⚙️ Generate types with orval
run: npm run generate
- name: Generate API code
run: npm run api:generate

- name: 🎨 Check code formatting with Prettier
- name: Check code formatting with Prettier
run: npm run format:check

- name: 🔍 Lint code with ESLint
- name: Lint code with ESLint
run: npm run lint

- name: 🧪 Run tests with Vitest
- name: Run tests with Vitest
run: npm run test:coverage
Loading
Loading