Files
2025-12-27 03:49:20 +00:00

442 lines
11 KiB
YAML

name: Gated Tree CI/CD
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
permissions:
contents: read
security-events: write
actions: read
jobs:
# Gate 1: Code Quality and Linting
lint-cpp:
name: Lint C++ Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format
- name: Check C++ formatting
run: |
# Check if there are any C++ files to format
if find backend frontends/qt6 frontends/cli -name "*.cpp" -o -name "*.h" -o -name "*.hpp" | grep -q .; then
echo "Checking C++ code formatting..."
# Run clang-format in check mode (dry-run)
find backend frontends/qt6 frontends/cli -name "*.cpp" -o -name "*.h" -o -name "*.hpp" | \
xargs clang-format --dry-run --Werror || \
(echo "❌ C++ code formatting issues found. Run 'clang-format -i' on the files." && exit 1)
else
echo "No C++ files found to check."
fi
lint-typescript:
name: Lint TypeScript Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies
working-directory: frontends/nextjs
run: bun install
- name: Lint TypeScript
working-directory: frontends/nextjs
run: |
# Run TypeScript compiler check
bun run tsc --noEmit
lint-python:
name: Lint Python Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install ruff
run: pip install ruff
- name: Lint Python scripts
run: |
# Check if there are any Python files
if find scripts -name "*.py" | grep -q .; then
echo "Linting Python code..."
ruff check scripts/
else
echo "No Python files found to lint."
fi
# Gate 2: Build Components (depends on linting passing)
build-backend:
name: Build C++ Backend
runs-on: ubuntu-latest
needs: [lint-cpp, lint-python]
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
ninja-build \
g++ \
libssl-dev \
zlib1g-dev \
libjsoncpp-dev \
uuid-dev \
libcurl4-openssl-dev
- name: Setup Python for Conan
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Conan
run: pip install conan
- name: Build backend
working-directory: backend
run: |
# Create build directory
mkdir -p build
cd build
# Configure with CMake
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
# Build
ninja
- name: Upload backend artifacts
uses: actions/upload-artifact@v4
with:
name: backend-build
path: backend/build/wizardmerge-cli
retention-days: 1
build-cli:
name: Build CLI Frontend
runs-on: ubuntu-latest
needs: [lint-cpp]
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
ninja-build \
g++ \
libcurl4-openssl-dev
- name: Build CLI
working-directory: frontends/cli
run: |
mkdir -p build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja
- name: Upload CLI artifacts
uses: actions/upload-artifact@v4
with:
name: cli-build
path: frontends/cli/build/wizardmerge-cli-frontend
retention-days: 1
build-qt6:
name: Build Qt6 Frontend
runs-on: ubuntu-latest
needs: [lint-cpp]
steps:
- uses: actions/checkout@v6
- name: Install Qt6
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
ninja-build \
g++ \
qt6-base-dev \
qt6-declarative-dev \
libqt6svg6-dev
- name: Build Qt6 Frontend
working-directory: frontends/qt6
run: |
mkdir -p build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja
- name: Upload Qt6 artifacts
uses: actions/upload-artifact@v4
with:
name: qt6-build
path: frontends/qt6/build/wizardmerge-qt6
retention-days: 1
build-nextjs:
name: Build Next.js Frontend
runs-on: ubuntu-latest
needs: [lint-typescript]
steps:
- uses: actions/checkout@v6
- name: Setup bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies
working-directory: frontends/nextjs
run: bun install
- name: Build Next.js
working-directory: frontends/nextjs
run: bun run build
- name: Upload Next.js artifacts
uses: actions/upload-artifact@v4
with:
name: nextjs-build
path: frontends/nextjs/.next
retention-days: 1
# Gate 3: Testing (depends on builds passing)
test-backend:
name: Test C++ Backend
runs-on: ubuntu-latest
needs: [build-backend]
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
ninja-build \
g++ \
libssl-dev \
zlib1g-dev \
libjsoncpp-dev \
uuid-dev \
libcurl4-openssl-dev \
libgtest-dev
- name: Setup Python for Conan
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Conan
run: pip install conan
- name: Build and run tests
working-directory: backend
run: |
mkdir -p build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON
ninja
# Run tests if they exist
if [ -f "wizardmerge_tests" ]; then
./wizardmerge_tests
else
echo "No tests found, skipping test execution"
fi
test-tlaplus:
name: TLA+ Specification Verification
runs-on: ubuntu-latest
needs: [lint-python]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Run TLC verification
run: |
python3 scripts/tlaplus.py run
- name: Upload TLC results
if: always()
uses: actions/upload-artifact@v4
with:
name: tlc-results
path: ci-results/
retention-days: 7
# Gate 4: Security Scanning (depends on tests passing)
security-codeql:
name: CodeQL Security Analysis
runs-on: ubuntu-latest
needs: [test-backend, test-tlaplus]
permissions:
security-events: write
actions: read
contents: read
steps:
- uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: cpp, python, javascript
- name: Install dependencies for C++
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
ninja-build \
g++ \
libssl-dev \
zlib1g-dev \
libjsoncpp-dev \
uuid-dev \
libcurl4-openssl-dev
- name: Setup Python for Conan
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Conan
run: pip install conan
- name: Build for CodeQL
working-directory: backend
run: |
mkdir -p build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:cpp,python,javascript"
# Gate 5: Integration Tests (depends on security scanning)
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: [security-codeql]
steps:
- uses: actions/checkout@v6
- name: Download backend artifact
uses: actions/download-artifact@v4
with:
name: backend-build
path: backend/build
- name: Make backend executable
run: chmod +x backend/build/wizardmerge-cli
- name: Run integration tests
run: |
echo "Starting backend server..."
backend/build/wizardmerge-cli &
SERVER_PID=$!
# Wait for server to start
sleep 5
# Test API endpoint
echo "Testing merge API endpoint..."
curl -X POST http://localhost:8080/api/merge \
-H "Content-Type: application/json" \
-d '{
"base": "line1\nline2\nline3",
"ours": "line1\nmodified by us\nline3",
"theirs": "line1\nmodified by them\nline3"
}' || echo "API test completed"
# Clean up
kill $SERVER_PID || true
# Gate 6: Deployment Gate (only on main branch, depends on all tests)
deployment-ready:
name: Deployment Ready
runs-on: ubuntu-latest
needs: [integration-tests]
if: github.ref == 'refs/heads/main'
steps:
- name: Deployment gate passed
run: |
echo "✅ All gates passed!"
echo "✅ Code quality checks passed"
echo "✅ All components built successfully"
echo "✅ Tests passed"
echo "✅ Security scan completed"
echo "✅ Integration tests passed"
echo ""
echo "🚀 Ready for deployment!"
# Optional: Publish results to ci/test-results branch
publish-results:
name: Publish Test Results
runs-on: ubuntu-latest
needs: [integration-tests]
if: github.ref == 'refs/heads/main'
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download TLC results
uses: actions/download-artifact@v4
with:
name: tlc-results
path: ci-results
- name: Push results to ci/test-results branch
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git fetch origin
git checkout -B ci/test-results
mkdir -p ci/test-results
cp -r ci-results/* ci/test-results/ || true
git add ci/test-results
git commit -m "CI results from run ${GITHUB_RUN_NUMBER}" || echo "No changes to commit"
git push origin ci/test-results