feat: Transform AgentSocial with enhanced UI features #105
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Pull Request Validation | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review, converted_to_draft] | |
| branches: [main, develop] | |
| workflow_dispatch: | |
| inputs: | |
| skip_tests: | |
| description: 'Skip tests (for draft PRs)' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| packages: read | |
| concurrency: | |
| group: pr-${{ github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Stage 1: Quick validation and change detection | |
| detect-changes: | |
| name: Change Detection & Quick Validation | |
| runs-on: self-hosted | |
| timeout-minutes: 5 | |
| outputs: | |
| python_changed: ${{ steps.changes.outputs.python_changed }} | |
| yaml_changed: ${{ steps.changes.outputs.yaml_changed }} | |
| docker_changed: ${{ steps.changes.outputs.docker_changed }} | |
| bulletin_changed: ${{ steps.changes.outputs.bulletin_changed }} | |
| docs_changed: ${{ steps.changes.outputs.docs_changed }} | |
| files_changed: ${{ steps.changes.outputs.files_changed }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| clean: true | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| ref: ${{ github.head_ref }} | |
| lfs: true | |
| - name: Detect file changes | |
| id: changes | |
| run: | | |
| echo "Analyzing changes..." | |
| # Handle different trigger types | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| echo "PR trigger - comparing with base branch: ${{ github.base_ref }}" | |
| git diff --name-only origin/${{ github.base_ref }}...HEAD > changed_files.txt | |
| elif [ "${{ github.event_name }}" = "push" ]; then | |
| echo "Push trigger - comparing with previous commit" | |
| git diff --name-only HEAD~1..HEAD > changed_files.txt | |
| else | |
| echo "Manual trigger - comparing with main branch" | |
| git diff --name-only origin/main...HEAD > changed_files.txt || git diff --name-only HEAD~5..HEAD > changed_files.txt | |
| fi | |
| # Count different types of changes | |
| python_count=$(grep -E '\.(py)$' changed_files.txt | wc -l || echo "0") | |
| yaml_count=$(grep -E '\.(ya?ml|json)$' changed_files.txt | wc -l || echo "0") | |
| docker_count=$(grep -E '(Dockerfile|docker-compose\.yml|docker-compose\.yaml|\.dockerignore)' changed_files.txt | wc -l || echo "0") | |
| bulletin_count=$(grep -E '(bulletin_board|bulletin-board)' changed_files.txt | wc -l || echo "0") | |
| docs_count=$(grep -E '\.(md|rst|txt)$' changed_files.txt | wc -l || echo "0") | |
| total_files=$(cat changed_files.txt | wc -l) | |
| # Set outputs | |
| echo "python_changed=$([[ $python_count -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "yaml_changed=$([[ $yaml_count -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "docker_changed=$([[ $docker_count -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "bulletin_changed=$([[ $bulletin_count -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "docs_changed=$([[ $docs_count -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT | |
| echo "files_changed=$total_files" >> $GITHUB_OUTPUT | |
| echo "[INFO] Change Summary:" | |
| echo " Python files: $python_count" | |
| echo " YAML/JSON files: $yaml_count" | |
| echo " Docker files: $docker_count" | |
| echo " Bulletin Board files: $bulletin_count" | |
| echo " Documentation: $docs_count" | |
| echo " Total files: $total_files" | |
| # Stage 2: Gemini AI Code Review | |
| gemini-review: | |
| name: Gemini AI Code Review | |
| needs: detect-changes | |
| if: > | |
| github.event.pull_request.draft != true && | |
| needs.detect-changes.outputs.files_changed != '0' | |
| runs-on: self-hosted | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| clean: true | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| ref: ${{ github.head_ref }} | |
| - name: Clear Gemini conversation history | |
| if: github.event.action == 'opened' || github.event.action == 'ready_for_review' | |
| run: | | |
| echo "Clearing Gemini conversation history for fresh review..." | |
| # Clear history to ensure each PR gets fresh review | |
| rm -f /tmp/gemini_conversation_*.json || true | |
| - name: Run Gemini Review | |
| env: | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| run: | | |
| echo "Running Gemini AI code review for PR #$PR_NUMBER..." | |
| python3 automation/review/gemini-pr-review.py \ | |
| --pr-number "$PR_NUMBER" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --focus "bulletin_board" | |
| # Stage 3: Code Quality Checks | |
| lint-stages: | |
| name: Code Quality - ${{ matrix.stage }} | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.python_changed == 'true' || needs.detect-changes.outputs.yaml_changed == 'true' | |
| runs-on: self-hosted | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| stage: | |
| - format | |
| - basic | |
| - full | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| clean: true | |
| - name: Run ${{ matrix.stage }} linting | |
| run: | | |
| echo "Running ${{ matrix.stage }} linting checks..." | |
| ./automation/ci-cd/run-lint-stage.sh ${{ matrix.stage }} | |
| # Stage 4: YAML/JSON Validation | |
| yaml-json-validation: | |
| name: YAML/JSON Validation | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.yaml_changed == 'true' | |
| runs-on: self-hosted | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| clean: true | |
| - name: Validate YAML files | |
| run: | | |
| echo "Validating YAML files..." | |
| docker-compose run --rm python-ci yamllint . | |
| - name: Validate JSON files | |
| run: | | |
| echo "Validating JSON files..." | |
| docker-compose run --rm python-ci bash -c "find . -name '*.json' -not -path './.git/*' -not -path './.mypy_cache/*' -not -path './packages/github_ai_agents/.mypy_cache/*' -print0 | xargs -0 -r -n1 python -m json.tool > /dev/null" | |
| # Stage 5: Bulletin Board Tests | |
| bulletin-board-tests: | |
| name: Bulletin Board Tests | |
| needs: [detect-changes, lint-stages] | |
| if: > | |
| (needs.detect-changes.outputs.python_changed == 'true' || | |
| needs.detect-changes.outputs.bulletin_changed == 'true') && | |
| github.event.inputs.skip_tests != 'true' | |
| runs-on: self-hosted | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| clean: true | |
| - name: Set up test environment | |
| run: | | |
| echo "Setting up test environment..." | |
| export USER_ID=$(id -u) | |
| export GROUP_ID=$(id -g) | |
| echo "USER_ID=$USER_ID" >> $GITHUB_ENV | |
| echo "GROUP_ID=$GROUP_ID" >> $GITHUB_ENV | |
| - name: Run bulletin board tests | |
| run: | | |
| echo "Running bulletin board tests..." | |
| docker-compose run --rm python-ci pytest tests/bulletin_board/ -v --cov=packages/bulletin_board --cov-report=xml | |
| - name: Run bulletin board validation | |
| run: | | |
| echo "Running bulletin board validation..." | |
| docker-compose run --rm python-ci python tests/test_bulletin_board_full.py | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bulletin-board-test-results | |
| path: | | |
| coverage.xml | |
| .coverage | |
| pytest.xml | |
| retention-days: 7 | |
| # Stage 6: Docker Build Test (Bulletin Board only) | |
| docker-build-test: | |
| name: Docker Build Test - Bulletin Board | |
| needs: detect-changes | |
| if: > | |
| needs.detect-changes.outputs.docker_changed == 'true' || | |
| needs.detect-changes.outputs.bulletin_changed == 'true' | |
| runs-on: self-hosted | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| clean: true | |
| - name: Build bulletin board Docker image | |
| run: | | |
| echo "Building bulletin board Docker images sequentially..." | |
| # Use sequential build to avoid docker buildx panic with parallel builds | |
| ./automation/ci-cd/build-bulletin-sequential.sh | |
| - name: Test bulletin board services | |
| run: | | |
| echo "Testing bulletin board services..." | |
| docker-compose --profile bulletin up -d | |
| sleep 10 | |
| docker-compose --profile bulletin ps | |
| curl -f http://localhost:8080/health || exit 1 | |
| docker-compose --profile bulletin down | |
| # Stage 7: Documentation Check | |
| docs-check: | |
| name: Documentation Check | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.docs_changed == 'true' | |
| runs-on: self-hosted | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| clean: true | |
| - name: Check markdown links | |
| run: | | |
| echo "Checking markdown links..." | |
| docker-compose run --rm python-ci python automation/analysis/check-markdown-links.py --internal-only . | |
| # Final Status Check | |
| pr-validation-status: | |
| name: PR Validation Status | |
| needs: | |
| - detect-changes | |
| - gemini-review | |
| - lint-stages | |
| - yaml-json-validation | |
| - bulletin-board-tests | |
| - docker-build-test | |
| - docs-check | |
| if: always() | |
| runs-on: self-hosted | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Check overall status | |
| run: | | |
| echo "PR Validation Summary:" | |
| echo "======================" | |
| # Check if any required jobs failed | |
| failed_jobs="" | |
| if [[ "${{ needs.gemini-review.result }}" == "failure" ]]; then | |
| failed_jobs="${failed_jobs}gemini-review " | |
| fi | |
| if [[ "${{ needs.lint-stages.result }}" == "failure" ]]; then | |
| failed_jobs="${failed_jobs}lint-stages " | |
| fi | |
| if [[ "${{ needs.bulletin-board-tests.result }}" == "failure" ]]; then | |
| failed_jobs="${failed_jobs}bulletin-board-tests " | |
| fi | |
| if [[ "${{ needs.docker-build-test.result }}" == "failure" ]]; then | |
| failed_jobs="${failed_jobs}docker-build-test " | |
| fi | |
| if [[ -n "$failed_jobs" ]]; then | |
| echo "❌ Failed jobs: $failed_jobs" | |
| echo "Please fix the issues and push new commits." | |
| exit 1 | |
| else | |
| echo "✅ All validation checks passed!" | |
| echo "PR is ready for review." | |
| fi | |
| - name: Post summary comment | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const summary = `## 📊 PR Validation Results | |
| | Check | Status | | |
| |-------|--------| | |
| | 🤖 Gemini Review | ${{ needs.gemini-review.result == 'success' && '✅ Passed' || needs.gemini-review.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} | | |
| | 🎨 Code Quality | ${{ needs.lint-stages.result == 'success' && '✅ Passed' || needs.lint-stages.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} | | |
| | 📋 YAML/JSON | ${{ needs.yaml-json-validation.result == 'success' && '✅ Passed' || needs.yaml-json-validation.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} | | |
| | 🧪 Bulletin Board Tests | ${{ needs.bulletin-board-tests.result == 'success' && '✅ Passed' || needs.bulletin-board-tests.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} | | |
| | 🐳 Docker Build | ${{ needs.docker-build-test.result == 'success' && '✅ Passed' || needs.docker-build-test.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} | | |
| | 📚 Documentation | ${{ needs.docs-check.result == 'success' && '✅ Passed' || needs.docs-check.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} | | |
| **Changed Files:** ${{ needs.detect-changes.outputs.files_changed }} | |
| `; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: summary | |
| }); |