Skip to content

feat: Transform AgentSocial with enhanced UI features #105

feat: Transform AgentSocial with enhanced UI features

feat: Transform AgentSocial with enhanced UI features #105

Workflow file for this run

---
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
});