diff --git a/.gitea/workflows/code_check.yml b/.gitea/workflows/code_check.yml index 31ed2f6b..18bd0473 100644 --- a/.gitea/workflows/code_check.yml +++ b/.gitea/workflows/code_check.yml @@ -24,6 +24,16 @@ on: 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: @@ -100,8 +110,49 @@ jobs: - name: Run backend tests run: | + mkdir -p reports + set +e cd backend - go test -v ./... + 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@v4 + 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 @@ -119,32 +170,269 @@ jobs: - name: Ensure browser for Flutter web tests run: | - if command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1 || command -v chromium-browser >/dev/null 2>&1 || command -v chromium >/dev/null 2>&1; then - echo "Chrome/Chromium already installed." + has_runnable_browser=false + for candidate in google-chrome google-chrome-stable chromium chromium-browser; do + if command -v "$candidate" >/dev/null 2>&1 && "$candidate" --version >/dev/null 2>&1; then + has_runnable_browser=true + break + fi + done + + if [ "$has_runnable_browser" = true ]; then + echo "Runnable Chrome/Chromium already installed." exit 0 fi if command -v sudo >/dev/null 2>&1; then sudo apt-get update - sudo apt-get install -y chromium-browser || sudo apt-get install -y chromium + sudo apt-get install -y chromium || sudo apt-get install -y chromium-browser else apt-get update - apt-get install -y chromium-browser || apt-get install -y chromium + apt-get install -y chromium || apt-get install -y chromium-browser fi + for candidate in google-chrome google-chrome-stable chromium chromium-browser; do + if command -v "$candidate" >/dev/null 2>&1 && "$candidate" --version >/dev/null 2>&1; then + echo "Installed browser: $candidate" + exit 0 + fi + done + + echo "No runnable Chrome/Chromium found after install." + exit 1 + - name: Run userfront tests run: | cd userfront if [ -d test ]; then - CHROME_BIN="$(command -v google-chrome || command -v google-chrome-stable || command -v chromium-browser || command -v chromium || true)" + CHROME_BIN="" + for candidate in google-chrome google-chrome-stable chromium chromium-browser; do + if command -v "$candidate" >/dev/null 2>&1 && "$candidate" --version >/dev/null 2>&1; then + CHROME_BIN="$(command -v "$candidate")" + break + fi + done if [ -z "$CHROME_BIN" ]; then echo "Chrome/Chromium not found for web tests." exit 1 fi + echo "Using browser: $CHROME_BIN" export CHROME_EXECUTABLE="$CHROME_BIN" - flutter test - flutter test --platform chrome test/locale_storage_platform_test.dart + mkdir -p ../reports + set +e + flutter test 2>&1 | tee ../reports/userfront-test-vm.log + vm_test_exit_code=${PIPESTATUS[0]} + + web_test_exit_code=0 + if [ "$vm_test_exit_code" -eq 0 ]; then + flutter test --platform chrome test/locale_storage_platform_test.dart 2>&1 | tee ../reports/userfront-test-web.log + web_test_exit_code=${PIPESTATUS[0]} + fi + set -e + + if [ "$vm_test_exit_code" -ne 0 ] || [ "$web_test_exit_code" -ne 0 ]; then + { + echo "# Userfront Test Failure Report" + echo + echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" + echo "- Job: \`userfront-tests\`" + echo "- Browser: \`$CHROME_BIN\`" + echo "- VM Test Exit Code: \`$vm_test_exit_code\`" + echo "- Web Test Exit Code: \`$web_test_exit_code\`" + echo + echo "## Commands" + echo "1. \`flutter test\`" + echo "2. \`flutter test --platform chrome test/locale_storage_platform_test.dart\`" + echo + if [ -f ../reports/userfront-test-vm.log ]; then + echo "## VM Test Log Tail (last 200 lines)" + echo '```text' + tail -n 200 ../reports/userfront-test-vm.log + echo '```' + echo + fi + if [ -f ../reports/userfront-test-web.log ]; then + echo "## Web Test Log Tail (last 200 lines)" + echo '```text' + tail -n 200 ../reports/userfront-test-web.log + echo '```' + fi + } > ../reports/userfront-test-failure-report.md + exit 1 + fi else echo "No userfront tests: skipping (test/ directory not found)." fi + + - 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@v4 + with: + name: userfront-test-failure-report + path: | + reports/userfront-test-failure-report.md + reports/userfront-test-vm.log + reports/userfront-test-web.log + if-no-files-found: ignore + + adminfront-tests: + needs: lint + if: ${{ always() && (github.event_name != 'workflow_dispatch' || inputs.run_adminfront_tests == 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" + cache: "npm" + cache-dependency-path: adminfront/package-lock.json + + - name: Install adminfront dependencies + run: | + cd adminfront + npm ci + + - name: Provision browsers for adminfront tests + run: | + cd adminfront + npx playwright install --with-deps + + - name: Run adminfront tests + run: | + mkdir -p reports + set +e + cd adminfront + npm test 2>&1 | tee ../reports/adminfront-test.log + test_exit_code=${PIPESTATUS[0]} + cd .. + set -e + + if [ "$test_exit_code" -ne 0 ]; then + { + echo "# Adminfront Test Failure Report" + echo + echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`" + echo "- Job: \`adminfront-tests\`" + echo "- Exit Code: \`$test_exit_code\`" + echo + echo "## Commands" + echo "1. \`cd adminfront\`" + 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/adminfront-test.log + echo '```' + } > reports/adminfront-test-failure-report.md + fi + + exit "$test_exit_code" + + - 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@v4 + with: + name: adminfront-test-failure-report + path: | + reports/adminfront-test-failure-report.md + 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: ubuntu-latest + 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: | + cd devfront + npm ci + + - name: Provision browsers for devfront tests + run: | + cd devfront + npx playwright install --with-deps + + - 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: 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@v4 + with: + name: devfront-test-failure-report + path: | + reports/devfront-test-failure-report.md + reports/devfront-test.log + devfront/playwright-report + devfront/test-results + if-no-files-found: ignore diff --git a/README.md b/README.md index f0ed1c14..8d08715a 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,51 @@ KETO_WRITE_URL = "http://keto:4467" - **Flutter(User)**: `userfront/lib/i18n.dart`에서 `tr(key, fallback, params)` 사용. `locales/*.toml`을 `tools/i18n-scanner/gen-flutter-i18n.js`로 `userfront/lib/i18n_data.dart`에 사전 생성합니다. - **검증**: `node tools/i18n-scanner/index.js`로 코드-키-로케일 동기화 상태를 점검합니다. +## 🧪 Code Check CI +워크플로우 파일: `.gitea/workflows/code_check.yml` + +### 트리거 +- `push` (`dev` 브랜치) +- `pull_request` (`dev` 대상) +- `workflow_dispatch` (수동 실행) + +### workflow_dispatch 입력값 +- `run_lint`: Go/Flutter lint 실행 여부 +- `run_backend_tests`: backend 테스트 실행 여부 +- `run_userfront_tests`: userfront 테스트 실행 여부 +- `run_adminfront_tests`: adminfront 테스트 실행 여부 +- `run_devfront_tests`: devfront 테스트 실행 여부 + +### 실행 잡 +- `lint` +- `backend-tests` +- `userfront-tests` +- `adminfront-tests` +- `devfront-tests` + +### 프런트 테스트 브라우저 프리비저닝 정책 +- `userfront-tests` + - 실행 가능한 Chrome/Chromium을 탐지하고, 없으면 설치 후 테스트 실행 + - `CHROME_EXECUTABLE` 지정 후 웹 테스트를 실행 +- `adminfront-tests`, `devfront-tests` + - Playwright 기반 테스트 + - `npx playwright install --with-deps`로 브라우저/OS 의존성을 사전 설치 + +### 실패 보고서 확인 방법 +테스트가 실패하면 다음이 자동 생성됩니다. +- Job Summary: 실패 원인 요약(Markdown) 즉시 확인 +- Artifact: 상세 로그/리포트 다운로드 + - `backend-test-failure-report` + - `userfront-test-failure-report` + - `adminfront-test-failure-report` + - `devfront-test-failure-report` + +### userfront의 `skipped` 테스트 안내 +- `locale_storage_platform_test.dart`는 웹 전용 테스트(`kIsWeb`)를 포함합니다. +- 따라서 일반 `flutter test`(VM)에서는 일부 테스트가 `skipped` 되는 것이 정상입니다. +- 실제 웹 실행 검증은 별도 단계에서 수행합니다. + - `flutter test --platform chrome test/locale_storage_platform_test.dart` + ### 로컬 개발 (Manual) Docker 없이는 개발할 수 없지만 Backend 및 [user/admin/dev]Front 코드는 개발모드로 수정하며 개발가능. 백그라운드로 infra 및 ory stack이 구동중이라는 가정