name: Code Check on: push: branches: - dev pull_request: branches: - dev workflow_dispatch: inputs: run_lint: description: "Run lint/format checks for Go, Flutter, adminfront, devfront" required: true type: boolean default: true run_backend_tests: description: "Run backend Go tests" required: true type: boolean default: true run_userfront_tests: description: "Run userfront Flutter tests" required: true type: boolean default: true run_userfront_e2e_tests: description: "Run userfront WASM Playwright E2E tests" required: true type: boolean default: true run_adminfront_tests: description: "Run adminfront Playwright tests" required: true type: boolean default: true run_devfront_tests: description: "Run devfront Playwright tests" required: true type: boolean default: true jobs: lint: if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_lint == true }} runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: i18n resource check run: | mkdir -p reports node tools/i18n-scanner/index.js node tools/i18n-scanner/report.js cat reports/i18n-report.txt - name: i18n value quality check run: | mkdir -p reports node tools/i18n-scanner/value-check.js cat reports/i18n-value-report.txt - name: Setup Go uses: actions/setup-go@v5 with: go-version: "1.25" cache-dependency-path: backend/go.sum - name: Setup Flutter uses: subosito/flutter-action@v2 with: channel: "stable" cache: true - name: Install adminfront dependencies run: | cd adminfront npm ci - name: Biome check adminfront (lint + format) run: | cd adminfront npx biome check . --formatter-enabled=false --organize-imports-enabled=false npx biome check . --linter-enabled=false --organize-imports-enabled=false - name: Install devfront dependencies run: | cd devfront npm ci - name: Biome check devfront (lint + format) run: | cd devfront npx biome check . --formatter-enabled=false --organize-imports-enabled=false npx biome check . --linter-enabled=false --organize-imports-enabled=false - name: Lint Go backend run: | docker run --rm \ -v "${PWD}/backend:/app" \ -w /app \ golangci/golangci-lint:v2.10.1 \ golangci-lint fmt -E gofmt -E gofumpt -d - name: Sync userfront locales run: | /bin/sh ./scripts/sync_userfront_locales.sh - name: Install Userfront dependencies run: | cd userfront flutter pub get - name: Format Flutter userfront run: | cd userfront dart format --output=none --set-exit-if-changed lib test - name: Analyze Flutter userfront run: | cd userfront flutter analyze --no-fatal-warnings --no-fatal-infos backend-tests: needs: lint if: ${{ always() && (github.event_name != 'workflow_dispatch' || inputs.run_backend_tests == true) }} runs-on: ubuntu-latest services: redis: image: redis:7-alpine options: > --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 clickhouse: image: clickhouse/clickhouse-server:24.6 options: > --health-cmd "wget -qO- 'http://localhost:8123/ping'" --health-interval 10s --health-timeout 5s --health-retries 5 env: REDIS_ADDR: redis:6379 CLICKHOUSE_HOST: clickhouse CLICKHOUSE_PORT_NATIVE: 9000 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Go uses: actions/setup-go@v5 with: go-version: "1.25" cache-dependency-path: backend/go.sum - name: Run backend tests run: | mkdir -p reports set +e cd backend go test -v ./... 2>&1 | tee ../reports/backend-test.log test_exit_code=${PIPESTATUS[0]} cd .. if [ "$test_exit_code" -ne 0 ]; then { echo "# Backend Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`backend-tests\`" echo "- Exit Code: \`$test_exit_code\`" echo echo "## Command" echo "\`go test -v ./...\`" echo echo "## Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/backend-test.log echo '```' } > reports/backend-test-failure-report.md fi exit "$test_exit_code" - name: Publish backend failure summary if: ${{ failure() }} run: | if [ -f reports/backend-test-failure-report.md ]; then cat reports/backend-test-failure-report.md >> "$GITHUB_STEP_SUMMARY" fi - name: Upload backend failure report artifact if: ${{ failure() }} uses: actions/upload-artifact@v3 continue-on-error: true with: name: backend-test-failure-report path: | reports/backend-test-failure-report.md reports/backend-test.log if-no-files-found: ignore userfront-tests: needs: lint if: ${{ always() && (github.event_name != 'workflow_dispatch' || inputs.run_userfront_tests == true) }} runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Flutter uses: subosito/flutter-action@v2 with: channel: "stable" cache: true - name: Sync userfront locales run: | /bin/sh ./scripts/sync_userfront_locales.sh - name: Run userfront tests run: | cd userfront if [ -d test ]; then mkdir -p ../reports set +e flutter test 2>&1 | tee ../reports/userfront-test.log test_exit_code=${PIPESTATUS[0]} set -e if [ "$test_exit_code" -ne 0 ]; then { echo "# Userfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-tests\`" echo "- Exit Code: \`$test_exit_code\`" echo echo "## Command" echo "\`flutter test\`" echo if [ -f ../reports/userfront-test.log ]; then echo "## Test Log Tail (last 200 lines)" echo '```text' tail -n 200 ../reports/userfront-test.log echo '```' fi } > ../reports/userfront-test-failure-report.md exit 1 fi else echo "No userfront tests: skipping (test/ directory not found)." fi - name: Ensure userfront failure report exists if: ${{ failure() }} run: | mkdir -p reports if [ -f reports/userfront-test-failure-report.md ]; then exit 0 fi { echo "# Userfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-tests\`" echo "- Reason: \`Job failed before detailed report generation\`" echo if [ -f reports/userfront-test.log ]; then echo "## Test Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-test.log echo '```' fi } > reports/userfront-test-failure-report.md - name: Publish userfront failure summary if: ${{ failure() }} run: | if [ -f reports/userfront-test-failure-report.md ]; then cat reports/userfront-test-failure-report.md >> "$GITHUB_STEP_SUMMARY" fi - name: Upload userfront failure report artifact if: ${{ failure() }} uses: actions/upload-artifact@v3 continue-on-error: true with: name: userfront-test-failure-report path: | reports/userfront-test-failure-report.md reports/userfront-test.log if-no-files-found: ignore userfront-e2e-tests: needs: lint if: ${{ always() && (github.event_name != 'workflow_dispatch' || inputs.run_userfront_e2e_tests == true) }} runs-on: ubuntu-latest timeout-minutes: 40 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" cache-dependency-path: userfront-e2e/package-lock.json - name: Setup Flutter uses: subosito/flutter-action@v2 with: channel: "stable" cache: true - name: Sync userfront locales run: | /bin/sh ./scripts/sync_userfront_locales.sh - name: Install userfront-e2e dependencies run: | mkdir -p reports set +e cd userfront-e2e npm ci 2>&1 | tee ../reports/userfront-e2e-install.log install_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$install_exit_code" -ne 0 ]; then { echo "# Userfront E2E Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-e2e-tests\`" echo "- Reason: \`Dependency install failed\`" echo "- Exit Code: \`$install_exit_code\`" echo echo "## Command" echo "\`cd userfront-e2e && npm ci\`" echo echo "## Install Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-install.log echo '```' } > reports/userfront-e2e-test-failure-report.md exit 1 fi - name: Build userfront WASM run: | mkdir -p reports set +e cd userfront flutter build web --wasm --release 2>&1 | tee ../reports/userfront-e2e-build.log build_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$build_exit_code" -ne 0 ]; then { echo "# Userfront E2E Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-e2e-tests\`" echo "- Reason: \`WASM build failed\`" echo "- Exit Code: \`$build_exit_code\`" echo echo "## Command" echo "\`cd userfront && flutter build web --wasm --release\`" echo echo "## Build Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-build.log echo '```' } > reports/userfront-e2e-test-failure-report.md exit 1 fi - name: Provision browsers for userfront-e2e tests run: | set +e cd userfront-e2e npx playwright install --with-deps chromium 2>&1 | tee ../reports/userfront-e2e-provision.log provision_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$provision_exit_code" -ne 0 ]; then { echo "# Userfront E2E Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-e2e-tests\`" echo "- Reason: \`Browser provisioning failed\`" echo "- Exit Code: \`$provision_exit_code\`" echo echo "## Command" echo "\`cd userfront-e2e && npx playwright install --with-deps chromium\`" echo echo "## Provision Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-provision.log echo '```' } > reports/userfront-e2e-test-failure-report.md exit 1 fi - name: Run userfront-e2e tests run: | mkdir -p reports set +e cd userfront-e2e npm test 2>&1 | tee ../reports/userfront-e2e-test.log test_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$test_exit_code" -ne 0 ]; then { echo "# Userfront E2E Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-e2e-tests\`" echo "- Exit Code: \`$test_exit_code\`" echo echo "## Commands" echo "1. \`cd userfront-e2e\`" echo "2. \`npm ci\`" echo "3. \`cd ../userfront && flutter build web --wasm --release\`" echo "4. \`cd ../userfront-e2e && npx playwright install --with-deps chromium\`" echo "5. \`npm test\`" echo echo "## Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-test.log echo '```' } > reports/userfront-e2e-test-failure-report.md fi exit "$test_exit_code" - name: Ensure userfront-e2e failure report exists if: ${{ failure() }} run: | mkdir -p reports if [ -f reports/userfront-e2e-test-failure-report.md ]; then exit 0 fi { echo "# Userfront E2E Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`userfront-e2e-tests\`" echo "- Reason: \`Job failed before detailed report generation\`" echo if [ -f reports/userfront-e2e-install.log ]; then echo "## Install Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-install.log echo '```' echo fi if [ -f reports/userfront-e2e-build.log ]; then echo "## Build Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-build.log echo '```' echo fi if [ -f reports/userfront-e2e-provision.log ]; then echo "## Provision Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-provision.log echo '```' echo fi if [ -f reports/userfront-e2e-test.log ]; then echo "## Test Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/userfront-e2e-test.log echo '```' fi } > reports/userfront-e2e-test-failure-report.md - name: Publish userfront-e2e failure summary if: ${{ failure() }} run: | if [ -f reports/userfront-e2e-test-failure-report.md ]; then cat reports/userfront-e2e-test-failure-report.md >> "$GITHUB_STEP_SUMMARY" fi - name: Upload userfront-e2e failure report artifact if: ${{ failure() }} uses: actions/upload-artifact@v3 continue-on-error: true with: name: userfront-e2e-test-failure-report path: | reports/userfront-e2e-test-failure-report.md reports/userfront-e2e-install.log reports/userfront-e2e-build.log reports/userfront-e2e-provision.log reports/userfront-e2e-test.log userfront-e2e/playwright-report userfront-e2e/test-results if-no-files-found: ignore adminfront-tests: needs: lint if: ${{ always() && (github.event_name != 'workflow_dispatch' || inputs.run_adminfront_tests == true) }} runs-on: playwright timeout-minutes: 30 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" cache-dependency-path: adminfront/package-lock.json - name: Run adminfront tests run: | scripts/run_adminfront_ci_tests.sh adminfront-tests - name: Ensure adminfront failure report exists if: ${{ failure() }} run: | mkdir -p reports if [ -f reports/adminfront-test-failure-report.md ]; then exit 0 fi { echo "# Adminfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`adminfront-tests\`" echo "- Reason: \`Job failed before detailed report generation\`" echo if [ -f reports/adminfront-install.log ]; then echo "## Install Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/adminfront-install.log echo '```' echo fi if [ -f reports/adminfront-provision.log ]; then echo "## Provision Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/adminfront-provision.log echo '```' echo fi if [ -f reports/adminfront-test.log ]; then echo "## Test Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/adminfront-test.log echo '```' fi } > reports/adminfront-test-failure-report.md - name: Publish adminfront failure summary if: ${{ failure() }} run: | if [ -f reports/adminfront-test-failure-report.md ]; then cat reports/adminfront-test-failure-report.md >> "$GITHUB_STEP_SUMMARY" fi - name: Upload adminfront failure report artifact if: ${{ failure() }} uses: actions/upload-artifact@v3 continue-on-error: true with: name: adminfront-test-failure-report path: | reports/adminfront-test-failure-report.md reports/adminfront-install.log reports/adminfront-provision.log reports/adminfront-test.log adminfront/playwright-report adminfront/test-results if-no-files-found: ignore devfront-tests: needs: lint if: ${{ always() && (github.event_name != 'workflow_dispatch' || inputs.run_devfront_tests == true) }} runs-on: playwright steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" cache-dependency-path: devfront/package-lock.json - name: Install devfront dependencies run: | mkdir -p reports set +e cd devfront npm ci 2>&1 | tee ../reports/devfront-install.log install_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$install_exit_code" -ne 0 ]; then { echo "# Devfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`devfront-tests\`" echo "- Reason: \`Dependency install failed\`" echo "- Exit Code: \`$install_exit_code\`" echo echo "## Command" echo "\`cd devfront && npm ci\`" echo echo "## Install Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/devfront-install.log echo '```' } > reports/devfront-test-failure-report.md exit 1 fi - name: Provision browsers for devfront tests run: | set +e cd devfront npx playwright install --with-deps 2>&1 | tee ../reports/devfront-provision.log provision_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$provision_exit_code" -ne 0 ]; then { echo "# Devfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`devfront-tests\`" echo "- Reason: \`Browser provisioning failed\`" echo "- Exit Code: \`$provision_exit_code\`" echo echo "## Command" echo "\`cd devfront && npx playwright install --with-deps\`" echo echo "## Provision Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/devfront-provision.log echo '```' } > reports/devfront-test-failure-report.md exit 1 fi - name: Run devfront tests run: | mkdir -p reports set +e cd devfront npm test 2>&1 | tee ../reports/devfront-test.log test_exit_code=${PIPESTATUS[0]} cd .. set -e if [ "$test_exit_code" -ne 0 ]; then { echo "# Devfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`devfront-tests\`" echo "- Exit Code: \`$test_exit_code\`" echo echo "## Commands" echo "1. \`cd devfront\`" echo "2. \`npm ci\`" echo "3. \`npx playwright install --with-deps\`" echo "4. \`npm test\`" echo echo "## Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/devfront-test.log echo '```' } > reports/devfront-test-failure-report.md fi exit "$test_exit_code" - name: Ensure devfront failure report exists if: ${{ failure() }} run: | mkdir -p reports if [ -f reports/devfront-test-failure-report.md ]; then exit 0 fi { echo "# Devfront Test Failure Report" echo echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" echo "- Job: \`devfront-tests\`" echo "- Reason: \`Job failed before detailed report generation\`" echo if [ -f reports/devfront-install.log ]; then echo "## Install Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/devfront-install.log echo '```' echo fi if [ -f reports/devfront-provision.log ]; then echo "## Provision Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/devfront-provision.log echo '```' echo fi if [ -f reports/devfront-test.log ]; then echo "## Test Log Tail (last 200 lines)" echo '```text' tail -n 200 reports/devfront-test.log echo '```' fi } > reports/devfront-test-failure-report.md - name: Publish devfront failure summary if: ${{ failure() }} run: | if [ -f reports/devfront-test-failure-report.md ]; then cat reports/devfront-test-failure-report.md >> "$GITHUB_STEP_SUMMARY" fi - name: Upload devfront failure report artifact if: ${{ failure() }} uses: actions/upload-artifact@v3 continue-on-error: true with: name: devfront-test-failure-report path: | reports/devfront-test-failure-report.md reports/devfront-install.log reports/devfront-provision.log reports/devfront-test.log devfront/playwright-report devfront/test-results if-no-files-found: ignore