Skip to content

docs: document theme bootstrap invariant #276

docs: document theme bootstrap invariant

docs: document theme bootstrap invariant #276

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
JAVA_VERSION: '17'
NODE_VERSION: '22.x'
PNPM_VERSION: '10'
jobs:
# --- Changes detection ---
changes:
name: Detect Changes
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
backend: ${{ steps.filter.outputs.backend }}
console: ${{ steps.filter.outputs.console }}
management: ${{ steps.filter.outputs.management }}
docker: ${{ steps.filter.outputs.docker }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Detect changed paths
id: filter
uses: dorny/paths-filter@v4
with:
filters: |
backend:
- 'backend-spring/**'
- 'init-db/migrations/**'
- '.github/workflows/ci.yml'
console:
- 'console/**'
- 'shared/**'
- '.github/workflows/ci.yml'
management:
- 'management/**'
- 'shared/**'
- '.github/workflows/ci.yml'
docker:
- 'backend-spring/Dockerfile'
- 'console/Dockerfile'
- 'management/Dockerfile'
- 'docker-compose*.yml'
- '.dockerignore'
- 'console/nginx.conf'
- 'management/nginx.conf'
- '.github/workflows/ci.yml'
# --- Backend: Build ---
backend-build:
name: Backend Build
needs: changes
if: needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup JDK 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Grant Maven wrapper execute permission
run: chmod +x backend-spring/mvnw
- name: Build with Maven
run: cd backend-spring && ./mvnw compile -B
# --- Backend: Test ---
backend-test:
name: Backend Test
needs: [changes, backend-build]
if: needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
services:
mysql:
image: mysql:9.1
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: ulticode
MYSQL_USER: ulticode
MYSQL_PASSWORD: ulticode
ports:
- 23306:3306
options: >-
--health-cmd="mysqladmin ping -h localhost -u root -proot"
--health-interval=10s
--health-timeout=5s
--health-retries=5
redis:
image: redis:7-alpine
ports:
- 26379:6379
options: >-
--health-cmd="redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5
env:
DB_HOST: localhost
DB_PORT: 23306
DB_USER: ulticode
DB_PASSWORD: ulticode
DB_NAME: ulticode
REDIS_HOST: localhost
REDIS_PORT: 26379
JWT_SECRET: test-jwt-secret-key-for-ci-minimum-32-characters-long
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup JDK 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: ${{ env.JAVA_VERSION }}
cache: 'maven'
- name: Grant Maven wrapper execute permission
run: chmod +x backend-spring/mvnw
- name: Run tests with CI profile
run: cd backend-spring && ./mvnw test -Dspring.profiles.active=ci -Dtest='!*IT' -B
- name: Upload test results on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: test-results-backend
path: backend-spring/target/surefire-reports/
retention-days: 7
# --- Backend: Validate Migrations ---
migrate-validate:
name: Validate Migrations
needs: changes
if: needs.changes.outputs.backend == 'true'
runs-on: ubuntu-latest
services:
mysql:
image: mysql:9.1
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: ulticode_test
MYSQL_USER: ulticode
MYSQL_PASSWORD: ulticode
ports:
- 23306:3306
options: >-
--health-cmd="mysqladmin ping -h localhost -u root -proot"
--health-interval=10s
--health-timeout=5s
--health-retries=5
env:
DB_HOST: localhost
DB_PORT: 23306
DB_USER: ulticode
DB_PASSWORD: ulticode
DB_NAME: ulticode_test
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Wait for MySQL
run: |
for i in $(seq 1 30); do
if mysqladmin ping -h localhost -P 23306 -u ulticode -pulticode 2>/dev/null; then
echo "MySQL is ready"
break
fi
echo "Waiting for MySQL... ($i/30)"
sleep 2
done
- name: Run and validate migrations
run: |
docker run --rm --network host \
-v "$PWD/init-db/migrations:/flyway/sql:ro" \
flyway/flyway:10.17.0 \
-url="jdbc:mysql://127.0.0.1:23306/ulticode?allowPublicKeyRetrieval=true&useSSL=false" \
-user=ulticode -password=ulticode -connectRetries=10 migrate
docker run --rm --network host \
-v "$PWD/init-db/migrations:/flyway/sql:ro" \
flyway/flyway:10.17.0 \
-url="jdbc:mysql://127.0.0.1:23306/ulticode?allowPublicKeyRetrieval=true&useSSL=false" \
-user=ulticode -password=ulticode validate
secret-scan:
name: Secret Scan
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Run Gitleaks
run: |
docker run --rm \
-v "$PWD:/repo:ro" \
zricethezav/gitleaks:v8.24.2 \
dir /repo --config=/repo/.gitleaks.toml --redact --no-banner
# --- Frontend: Lint ---
frontend-lint:
name: Lint (${{ matrix.app }})
needs: changes
if: needs.changes.outputs.console == 'true' || needs.changes.outputs.management == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
app: [console, management]
steps:
- name: Check if app changed
id: should-run
if: (matrix.app == 'console' && needs.changes.outputs.console == 'true') || (matrix.app == 'management' && needs.changes.outputs.management == 'true')
run: echo "run=true" >> $GITHUB_OUTPUT
- name: Checkout repository
if: steps.should-run.outputs.run == 'true'
uses: actions/checkout@v6
- name: Enable pnpm via corepack
if: steps.should-run.outputs.run == 'true'
run: corepack enable && corepack prepare pnpm@${{ env.PNPM_VERSION }} --activate
- name: Setup Node.js
if: steps.should-run.outputs.run == 'true'
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
cache-dependency-path: ${{ matrix.app }}/pnpm-lock.yaml
- name: Install dependencies
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
env:
CI: "false"
GITHUB_ACTIONS: "false"
run: pnpm install
- name: Run lint
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
run: pnpm lint
# --- Frontend: Type Check ---
frontend-type-check:
name: Type Check (${{ matrix.app }})
needs: changes
if: needs.changes.outputs.console == 'true' || needs.changes.outputs.management == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
app: [console, management]
steps:
- name: Check if app changed
id: should-run
if: (matrix.app == 'console' && needs.changes.outputs.console == 'true') || (matrix.app == 'management' && needs.changes.outputs.management == 'true')
run: echo "run=true" >> $GITHUB_OUTPUT
- name: Checkout repository
if: steps.should-run.outputs.run == 'true'
uses: actions/checkout@v6
- name: Enable pnpm via corepack
if: steps.should-run.outputs.run == 'true'
run: corepack enable && corepack prepare pnpm@${{ env.PNPM_VERSION }} --activate
- name: Setup Node.js
if: steps.should-run.outputs.run == 'true'
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
cache-dependency-path: ${{ matrix.app }}/pnpm-lock.yaml
- name: Install dependencies
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
env:
CI: "false"
GITHUB_ACTIONS: "false"
run: pnpm install
- name: Run type-check
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
run: pnpm type-check
# --- Frontend: Test ---
frontend-test:
name: Test (${{ matrix.app }})
needs: changes
if: needs.changes.outputs.console == 'true' || needs.changes.outputs.management == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
app: [console, management]
steps:
- name: Check if app changed
id: should-run
if: (matrix.app == 'console' && needs.changes.outputs.console == 'true') || (matrix.app == 'management' && needs.changes.outputs.management == 'true')
run: echo "run=true" >> $GITHUB_OUTPUT
- name: Checkout repository
if: steps.should-run.outputs.run == 'true'
uses: actions/checkout@v6
- name: Enable pnpm via corepack
if: steps.should-run.outputs.run == 'true'
run: corepack enable && corepack prepare pnpm@${{ env.PNPM_VERSION }} --activate
- name: Setup Node.js
if: steps.should-run.outputs.run == 'true'
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
cache-dependency-path: ${{ matrix.app }}/pnpm-lock.yaml
- name: Install dependencies
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
env:
CI: "false"
GITHUB_ACTIONS: "false"
run: pnpm install
- name: Run tests
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
run: pnpm test
- name: Audit production dependencies
if: steps.should-run.outputs.run == 'true'
working-directory: ${{ matrix.app }}
run: pnpm audit --prod --audit-level high
shared-auth-test:
name: Test shared auth core
needs: changes
if: needs.changes.outputs.console == 'true' || needs.changes.outputs.management == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Enable pnpm via corepack
run: corepack enable && corepack prepare pnpm@${{ env.PNPM_VERSION }} --activate
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
cache-dependency-path: shared/auth-core/pnpm-lock.yaml
- name: Install dependencies
working-directory: shared/auth-core
run: pnpm install --frozen-lockfile
- name: Test and type-check
working-directory: shared/auth-core
run: pnpm test && pnpm type-check
# --- Frontend: i18n Check (management only) ---
frontend-i18n-check:
name: i18n Check (management)
needs: changes
if: needs.changes.outputs.management == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Enable pnpm via corepack
run: corepack enable && corepack prepare pnpm@${{ env.PNPM_VERSION }} --activate
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
cache-dependency-path: management/pnpm-lock.yaml
- name: Install dependencies
working-directory: management
env:
CI: "false"
GITHUB_ACTIONS: "false"
run: pnpm install
- name: Run i18n completeness check
working-directory: management
run: pnpm check:i18n --json
- name: Run i18n tests
working-directory: management
run: pnpm vitest run -- src/i18n/__tests__/
# --- Docker Build Verification ---
docker-verify:
name: Docker Build (${{ matrix.service.name }})
needs: changes
if: needs.changes.outputs.docker == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service:
- name: backend
dockerfile: ./backend-spring/Dockerfile
- name: console
dockerfile: ./console/Dockerfile
- name: management
dockerfile: ./management/Dockerfile
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build Docker image (no push)
uses: docker/build-push-action@v7
with:
context: .
file: ${{ matrix.service.dockerfile }}
push: false
cache-from: type=gha
cache-to: type=gha,mode=max