# this workflow verifies the generated code is up to date and valid name: Verify on: pull_request: branches: - master push: branches: - master jobs: # setup is now handled by a composite action used by downstream jobs to keep # the workflow DRY. The composite action performs checkout, cache restore and # toolchain setup. verify-generated-code: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Setup Rust, checkout and restore caches uses: ./.github/actions/setup-rust - name: generate entities from migration files run: | cd apps/cli cargo run -- db:migrate_and_generate --output-path ../../public/database/src/generated/entities - name: Check for uncommitted changes in /generated/ run: | if [[ -n $(git status --porcelain --untracked-files=all | grep '/generated/') ]]; then echo "Generated code is not up to date. Please run the code generation locally and commit the changes." git status --porcelain --untracked-files=all | grep '/generated/' exit 1 else echo "Generated code is up to date." fi verify-generated-agent-code: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 - uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' - name: Setup Rust, checkout and restore caches uses: ./.github/actions/setup-rust - name: Setup PNPM uses: pnpm/action-setup@v4 with: version: 10 run_install: false - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: 'pnpm' cache-dependency-path: pnpm-lock.yaml - name: Install root dependencies run: | pnpm install --frozen-lockfile - name: generate agent client code run: | pnpm just generate-agent-client - name: Check for uncommitted changes in agent client code run: | if [[ -n $(git status --porcelain --untracked-files=all | grep 'public/agent-client/') ]]; then echo "Agent client code is not up to date. Please run the agent client code generation locally and commit the changes." git status --porcelain --untracked-files=all | grep 'public/agent-client/' exit 1 else echo "Agent client code is up to date." fi verify-openapi-spec: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Check whether apps/api/src/routes changed id: check_changes run: | if [ "${{ github.event_name }}" = "pull_request" ]; then BASE_SHA=${{ github.event.pull_request.base.sha }} HEAD_SHA=${{ github.event.pull_request.head.sha }} else BASE_SHA=${{ github.event.before }} HEAD_SHA=${{ github.sha }} fi # Provide safe fallbacks when GitHub context values are empty (e.g. when using act) if [ -z "$HEAD_SHA" ]; then HEAD_SHA=$(git rev-parse --verify HEAD 2>/dev/null || echo "") fi if [ -z "$BASE_SHA" ]; then # Try the parent of HEAD, fall back to HEAD if unavailable PREV=$(git rev-parse --verify "${HEAD_SHA}^" 2>/dev/null || true) if [ -n "$PREV" ]; then BASE_SHA=$PREV else BASE_SHA=$HEAD_SHA fi fi echo "Comparing $BASE_SHA..$HEAD_SHA" CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" || true) echo "$CHANGED_FILES" echo "$CHANGED_FILES" | grep -E '^(apps/api/src/routes/?|apps/api/swagger.json)' >/dev/null 2>&1 && echo "changed=true" >> $GITHUB_OUTPUT || echo "changed=false" >> $GITHUB_OUTPUT - name: Setup Rust, checkout and restore caches if: steps.check_changes.outputs.changed == 'true' uses: ./.github/actions/setup-rust - name: Generate dummy frontend build (to satisfy dependencies) if: steps.check_changes.outputs.changed == 'true' run: | mkdir -p apps/frontend/build/client echo "dummy file" > apps/frontend/build/client/dummy.txt - name: Generate OpenAPI spec if: steps.check_changes.outputs.changed == 'true' run: | cd apps/api cargo run -- generate:openapi --output-path ./swagger.json - name: Check for uncommitted changes in swagger.json if: steps.check_changes.outputs.changed == 'true' run: | if [[ -n $(git status --porcelain --untracked-files=all | grep 'apps/api/swagger.json') ]]; then echo "OpenAPI spec is not up to date. Please run the OpenAPI generation locally and commit the changes." git status --porcelain --untracked-files=all | grep 'apps/api/swagger.json' exit 1 else echo "OpenAPI spec is up to date." fi - name: Skip OpenAPI generation (no relevant changes) if: steps.check_changes.outputs.changed == 'false' run: echo "No changes in apps/api/src/routes/ nor apps/api/swagger.json, skipping OpenAPI generation verification." verify-frontend-api-client: runs-on: ubuntu-latest needs: verify-openapi-spec steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Check whether apps/api/swagger.json or apps/frontend/app/generated/api-client changed id: check_swagger_changes run: | if [ "${{ github.event_name }}" = "pull_request" ]; then BASE_SHA=${{ github.event.pull_request.base.sha }} HEAD_SHA=${{ github.event.pull_request.head.sha }} else BASE_SHA=${{ github.event.before }} HEAD_SHA=${{ github.sha }} fi # Provide safe fallbacks when GitHub context values are empty (e.g. when using act) if [ -z "$HEAD_SHA" ]; then HEAD_SHA=$(git rev-parse --verify HEAD 2>/dev/null || echo "") fi if [ -z "$BASE_SHA" ]; then # Try the parent of HEAD, fall back to HEAD if unavailable PREV=$(git rev-parse --verify "${HEAD_SHA}^" 2>/dev/null || true) if [ -n "$PREV" ]; then BASE_SHA=$PREV else BASE_SHA=$HEAD_SHA fi fi echo "Comparing $BASE_SHA..$HEAD_SHA" CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" || true) echo "$CHANGED_FILES" echo "$CHANGED_FILES" | grep -E '^(apps/api/swagger.json|apps/frontend/app/generated/api-client)' >/dev/null 2>&1 && echo "changed=true" >> $GITHUB_OUTPUT || echo "changed=false" >> $GITHUB_OUTPUT - name: Setup PNPM uses: pnpm/action-setup@v4 if: steps.check_swagger_changes.outputs.changed == 'true' with: version: 10 run_install: false - name: Setup Node.js uses: actions/setup-node@v4 if: steps.check_swagger_changes.outputs.changed == 'true' with: node-version: 22 cache: 'pnpm' cache-dependency-path: apps/frontend/pnpm-lock.yaml - name: Install frontend dependencies if: steps.check_swagger_changes.outputs.changed == 'true' run: | cd apps/frontend pnpm install - name: Generate frontend API client if: steps.check_swagger_changes.outputs.changed == 'true' run: | cd apps/frontend pnpm generate:openapi - name: Check for uncommitted changes in frontend API client if: steps.check_swagger_changes.outputs.changed == 'true' run: | if [[ -n $(git status --porcelain --untracked-files=all | grep 'apps/frontend/app/generated/api-client') ]]; then echo "Frontend API client is not up to date. Please run the API client generation locally and commit the changes." git status --porcelain --untracked-files=all | grep 'apps/frontend/app/generated/api-client' exit 1 else echo "Frontend API client is up to date." fi - name: Skip frontend API client generation (no relevant changes) if: steps.check_swagger_changes.outputs.changed == 'false' run: echo "No changes in apps/api/swagger.json nor apps/frontend/app/generated/api-client, skipping frontend API client generation verification."