Skip to content

test: AI 리뷰와 통합 CI smoke 검증 #5

test: AI 리뷰와 통합 CI smoke 검증

test: AI 리뷰와 통합 CI smoke 검증 #5

Workflow file for this run

name: CI
on:
pull_request:
branches:
- main
- develop
concurrency:
group: ci-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: read
jobs:
changes:
name: detect changes
runs-on: ubuntu-latest
outputs:
ai: ${{ steps.filter.outputs.ai }}
server: ${{ steps.filter.outputs.server }}
web: ${{ steps.filter.outputs.web }}
steps:
- name: Detect changed parts
id: filter
uses: actions/github-script@v9
with:
script: |
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
per_page: 100,
});
const paths = files.flatMap((file) =>
[file.filename, file.previous_filename].filter(Boolean),
);
const shared = paths.some((path) =>
[".editorconfig", ".gitattributes", ".github/workflows/ci.yml"].includes(path) ||
path.startsWith(".github/scripts/") ||
path.startsWith(".github/prompts/"),
);
core.setOutput("ai", shared || paths.some((path) => path.startsWith("ai/")));
core.setOutput("server", shared || paths.some((path) => path.startsWith("server/")));
core.setOutput("web", shared || paths.some((path) => path.startsWith("web/")));
ai:
name: ai quality
needs: changes
if: needs.changes.outputs.ai == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: ai
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up uv
uses: astral-sh/setup-uv@v9.0.0
with:
enable-cache: true
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version-file: ai/pyproject.toml
- name: Install dependencies
run: uv sync --frozen --dev
- name: Lint
run: uv run ruff check .
- name: Format check
run: uv run ruff format --check .
- name: Build Docker image
run: docker build -t whylog-ai .
server:
name: server quality
needs: changes
if: needs.changes.outputs.server == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: server
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
- name: Grant execute permission for Gradle
run: chmod +x ./gradlew
- name: Build with Gradle
run: ./gradlew clean build
web:
name: web quality
needs: changes
if: needs.changes.outputs.web == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up pnpm
uses: pnpm/action-setup@v6
with:
version: 10
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint and format check
run: pnpm exec biome ci .
- name: Type check and build
run: pnpm build
review_harness:
name: review harness quality
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout pull request revision
uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.13"
- name: Test review harness
run: |
python -m unittest discover -s .github/scripts -p "test_*.py"
python -m compileall -q .github/scripts
ai-review:
name: AI review
needs:
- changes
- ai
- server
- web
- review_harness
if: >-
always() &&
github.event.pull_request.head.repo.full_name == github.repository &&
needs.changes.result == 'success' &&
(needs.ai.result == 'success' || needs.ai.result == 'skipped') &&
(needs.server.result == 'success' || needs.server.result == 'skipped') &&
(needs.web.result == 'success' || needs.web.result == 'skipped') &&
needs.review_harness.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Checkout trusted base revision
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.base.sha }}
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.13"
- name: Review pull request
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSITORY_IS_PRIVATE: ${{ github.event.repository.private }}
PYTHONUNBUFFERED: "1"
run: python .github/scripts/ai_review.py
quality:
name: quality gate
if: always()
needs:
- changes
- ai
- server
- web
- review_harness
- ai-review
runs-on: ubuntu-latest
steps:
- name: Verify machine checks
env:
CHANGES_RESULT: ${{ needs.changes.result }}
AI_RESULT: ${{ needs.ai.result }}
SERVER_RESULT: ${{ needs.server.result }}
WEB_RESULT: ${{ needs.web.result }}
REVIEW_HARNESS_RESULT: ${{ needs.review_harness.result }}
AI_REVIEW_RESULT: ${{ needs.ai-review.result }}
run: |
if [ "$CHANGES_RESULT" != "success" ]; then
echo "Change detection failed: $CHANGES_RESULT"
exit 1
fi
for result in "$AI_RESULT" "$SERVER_RESULT" "$WEB_RESULT"; do
if [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
echo "Machine check failed: $result"
exit 1
fi
done
if [ "$REVIEW_HARNESS_RESULT" != "success" ]; then
echo "Review harness check failed: $REVIEW_HARNESS_RESULT"
exit 1
fi
if [ "$AI_REVIEW_RESULT" != "success" ]; then
echo "AI review failed or did not run: $AI_REVIEW_RESULT"
exit 1
fi
echo "All required machine checks and AI review passed."