Add pixiu-admin CI test #7
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
| # Licensed to the Apache Software Foundation (ASF) under one or more | |
| # contributor license agreements. See the NOTICE file distributed with | |
| # this work for additional information regarding copyright ownership. | |
| # The ASF licenses this file to You under the Apache License, Version 2.0 | |
| # (the "License"); you may not use this file except in compliance with | |
| # the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| name: Pixiu-Admin CI | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| paths: | |
| - 'admin/**' | |
| - 'docker-compose.yml' | |
| - '.github/workflows/pixiu-admin-ci.yml' | |
| pull_request: | |
| branches: [ main, develop ] | |
| paths: | |
| - 'admin/**' | |
| - 'docker-compose.yml' | |
| - '.github/workflows/pixiu-admin-ci.yml' | |
| # cancel in-progress runs for the same branch or PR | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Build and test backend | |
| backend-build: | |
| name: Build Admin Backend | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: 'go.mod' | |
| cache: true | |
| - name: Download dependencies | |
| run: | | |
| go mod download | |
| go mod verify | |
| - name: Build admin binary | |
| run: | | |
| go build -v -o pixiu-admin ./cmd/admin/admin.go | |
| - name: Run Go tests | |
| run: | | |
| go test -v -race -coverprofile=coverage.out -covermode=atomic ./admin/... | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4 | |
| with: | |
| files: ./coverage.out | |
| flags: admin-backend | |
| name: admin-backend-coverage | |
| # Build and test frontend | |
| frontend-build: | |
| name: Build Admin Frontend | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| admin/web/node_modules | |
| ~/.yarn | |
| key: ${{ runner.os }}-yarn-${{ hashFiles('admin/web/yarn.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-yarn- | |
| - name: Install dependencies | |
| run: | | |
| cd admin/web | |
| yarn install --ignore-engines | |
| - name: Run unit tests | |
| run: | | |
| cd admin/web | |
| yarn test:unit | |
| - name: Build frontend | |
| run: | | |
| cd admin/web | |
| yarn build | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: frontend-dist | |
| path: admin/web/dist/ | |
| retention-days: 7 | |
| # Docker Compose deployment test | |
| docker-compose-test: | |
| name: Docker Compose Deployment Test | |
| runs-on: ubuntu-latest | |
| needs: [backend-build, frontend-build] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Check if docker-compose.yml exists | |
| run: | | |
| if [ ! -f docker-compose.yml ]; then | |
| echo "⚠️ docker-compose.yml not found in root directory" | |
| echo "Skipping docker-compose tests" | |
| exit 0 | |
| fi | |
| - name: Start services with docker-compose | |
| run: | | |
| # Start etcd and any other services defined in docker-compose | |
| docker-compose up -d | |
| - name: Wait for etcd to be ready | |
| run: | | |
| echo "Waiting for etcd to be ready..." | |
| timeout 60 bash -c 'until docker ps | grep etcd | grep -q "Up"; do sleep 2; done' | |
| # Test etcd health | |
| sleep 10 | |
| curl -sf http://localhost:2379/health || exit 1 | |
| - name: Show running containers | |
| run: | | |
| echo "=== Running Docker Containers ===" | |
| docker ps | |
| - name: Show docker-compose services | |
| if: always() | |
| run: | | |
| docker-compose ps || true | |
| - name: Show service logs on failure | |
| if: failure() | |
| run: | | |
| echo "=== Docker Compose Logs ===" | |
| docker-compose logs || true | |
| - name: Stop services | |
| if: always() | |
| run: | | |
| docker-compose down -v | |
| # Integration tests with database | |
| # NOTE: These tests are temporarily marked as non-blocking because pixiu admin is not fully functional | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: [backend-build] | |
| continue-on-error: true # Allow CI to pass even if integration tests fail | |
| services: | |
| mysql: | |
| image: mysql:8.0 | |
| env: | |
| MYSQL_ROOT_PASSWORD: root | |
| MYSQL_DATABASE: pixiu | |
| ports: | |
| - 3306:3306 | |
| options: >- | |
| --health-cmd="mysqladmin ping" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=3 | |
| etcd: | |
| image: quay.io/coreos/etcd:v3.6.1 | |
| env: | |
| ETCD_LISTEN_CLIENT_URLS: http://0.0.0.0:2379 | |
| ETCD_ADVERTISE_CLIENT_URLS: http://localhost:2379 | |
| ports: | |
| - 2379:2379 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: 'go.mod' | |
| cache: true | |
| - name: Initialize database | |
| run: | | |
| mysql -h 127.0.0.1 -u root -proot pixiu < admin/resources/sql/pixiu_demo.sql | |
| - name: Create test config | |
| run: | | |
| cat > /tmp/test-config.yaml <<EOF | |
| server: | |
| address: "127.0.0.1:8081" | |
| etcd: | |
| address: "127.0.0.1:2379" | |
| path: "/pixiu/config/api" | |
| mysql: | |
| username: "root" | |
| password: "root" | |
| host: "127.0.0.1" | |
| port: "3306" | |
| dbname: "pixiu" | |
| EOF | |
| - name: Test API operations | |
| run: | | |
| # Ensure cleanup on exit | |
| cleanup() { | |
| if [ -n "$ADMIN_PID" ]; then | |
| kill $ADMIN_PID 2>/dev/null || true | |
| fi | |
| } | |
| trap cleanup EXIT | |
| # Start admin server in background | |
| go run ./cmd/admin/admin.go -c /tmp/test-config.yaml & | |
| ADMIN_PID=$! | |
| # Wait for server to start | |
| for i in {1..30}; do | |
| if curl -sf http://localhost:8081/config/api/base >/dev/null 2>&1; then | |
| echo "Admin server is ready" | |
| break | |
| fi | |
| echo "Waiting for admin server... attempt $i/30" | |
| sleep 2 | |
| done | |
| # Test resource creation | |
| cat > /tmp/resource.yaml <<'EOFRESOURCE' | |
| path: '/test' | |
| type: restful | |
| description: test resource | |
| EOFRESOURCE | |
| curl -f -X POST http://localhost:8081/config/api/resource \ | |
| -H "Content-Type: multipart/form-data" \ | |
| -F "content=@/tmp/resource.yaml" | |
| # Test resource list and validate response | |
| RESPONSE=$(curl -sf http://localhost:8081/config/api/resource/list) | |
| if [ -z "$RESPONSE" ]; then | |
| echo "Error: Empty response from resource list endpoint" | |
| exit 1 | |
| fi | |
| echo "Resource list response: $RESPONSE" | |
| # Manual deployment test (following README instructions) | |
| # NOTE: Temporarily marked as non-blocking because pixiu admin is not fully functional | |
| manual-deployment-test: | |
| name: Manual Deployment Test | |
| runs-on: ubuntu-latest | |
| needs: [backend-build] | |
| continue-on-error: true # Allow CI to pass even if this test fails | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: 'go.mod' | |
| cache: true | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| - name: Start etcd service | |
| run: | | |
| docker run -d -p 2379:2379 \ | |
| --env ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \ | |
| --env ETCD_ADVERTISE_CLIENT_URLS=http://localhost:2379 \ | |
| --name etcd \ | |
| quay.io/coreos/etcd:v3.6.1 | |
| - name: Wait for etcd to be ready | |
| run: | | |
| echo "Waiting for etcd..." | |
| timeout 60 bash -c 'until curl -sf http://localhost:2379/health 2>/dev/null; do sleep 2; done' | |
| echo "✅ Etcd is ready" | |
| - name: Create test config file | |
| run: | | |
| mkdir -p /tmp/admin-test | |
| cat > /tmp/admin-test/conf.yaml <<'EOF' | |
| server: | |
| address: "127.0.0.1:8081" | |
| etcd: | |
| address: "127.0.0.1:2379" | |
| path: "/pixiu/config/api" | |
| mysql: | |
| username: "root" | |
| password: "root" | |
| host: "127.0.0.1" | |
| port: "3306" | |
| dbname: "pixiu" | |
| zap: | |
| level: "info" | |
| format: "console" | |
| prefix: "[PIXIU-ADMIN]" | |
| director: "/tmp/logs" | |
| linkName: "latest.log" | |
| showLine: true | |
| encodeLevel: "LowercaseColorLevelEncoder" | |
| stacktraceKey: "stacktrace" | |
| logInConsole: true | |
| system: | |
| env: "develop" | |
| addr: 8081 | |
| dbType: "mysql" | |
| EOF | |
| - name: Build admin binary | |
| run: | | |
| go build -v -o /tmp/admin-test/pixiu-admin ./cmd/admin/admin.go | |
| - name: Start admin service in background | |
| run: | | |
| cd /tmp/admin-test | |
| mkdir -p /tmp/logs | |
| nohup ./pixiu-admin -c conf.yaml > /tmp/logs/admin.log 2>&1 & | |
| echo $! > /tmp/admin.pid | |
| echo "Admin PID: $(cat /tmp/admin.pid)" | |
| - name: Wait for admin service to be ready | |
| run: | | |
| echo "Waiting for admin service..." | |
| for i in {1..30}; do | |
| if curl -f http://localhost:8081/config/api/base 2>/dev/null; then | |
| echo "✅ Admin service is ready" | |
| exit 0 | |
| fi | |
| echo "Attempt $i/30 - waiting..." | |
| sleep 2 | |
| done | |
| echo "❌ Admin service failed to start" | |
| cat /tmp/logs/admin.log | |
| exit 1 | |
| - name: Test admin API endpoints | |
| run: | | |
| echo "Testing base info endpoint..." | |
| BASE_RESPONSE=$(curl -sf http://localhost:8081/config/api/base) | |
| if [ -z "$BASE_RESPONSE" ]; then | |
| echo "Error: Empty response from base endpoint" | |
| exit 1 | |
| fi | |
| echo "Base response: $BASE_RESPONSE" | |
| echo -e "\nTesting resource list endpoint..." | |
| RESOURCE_RESPONSE=$(curl -sf http://localhost:8081/config/api/resource/list) | |
| if [ -z "$RESOURCE_RESPONSE" ]; then | |
| echo "Error: Empty response from resource list endpoint" | |
| exit 1 | |
| fi | |
| echo "Resource list response: $RESOURCE_RESPONSE" | |
| echo -e "\nTesting cluster list endpoint..." | |
| CLUSTER_RESPONSE=$(curl -sf http://localhost:8081/config/api/cluster/list) | |
| if [ -z "$CLUSTER_RESPONSE" ]; then | |
| echo "Error: Empty response from cluster list endpoint" | |
| exit 1 | |
| fi | |
| echo "Cluster list response: $CLUSTER_RESPONSE" | |
| echo -e "\nTesting listener list endpoint..." | |
| LISTENER_RESPONSE=$(curl -sf http://localhost:8081/config/api/listener/list) | |
| if [ -z "$LISTENER_RESPONSE" ]; then | |
| echo "Error: Empty response from listener list endpoint" | |
| exit 1 | |
| fi | |
| echo "Listener list response: $LISTENER_RESPONSE" | |
| - name: Build frontend | |
| run: | | |
| cd admin/web | |
| yarn install | |
| yarn build | |
| - name: Verify frontend build output | |
| run: | | |
| ls -la admin/web/dist/ | |
| test -d admin/web/dist/ || exit 1 | |
| - name: Show logs on failure | |
| if: failure() | |
| run: | | |
| echo "=== Admin Service Logs ===" | |
| cat /tmp/logs/admin.log || echo "No logs found" | |
| echo -e "\n=== Etcd Status ===" | |
| docker logs etcd || echo "No etcd logs" | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| if [ -f /tmp/admin.pid ]; then | |
| kill $(cat /tmp/admin.pid) || true | |
| fi | |
| docker stop etcd || true | |
| docker rm etcd || true | |
| # Security and code quality checks | |
| code-quality: | |
| name: Code Quality & Security | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: 'go.mod' | |
| cache: true | |
| - name: golangci-lint | |
| uses: golangci/golangci-lint-action@v8 # NOSONAR | |
| with: | |
| version: v2.4.0 | |
| args: ./admin/... | |
| - name: Run gosec security scanner | |
| run: | | |
| go install github.com/securego/gosec/v2/cmd/gosec@latest | |
| gosec -fmt=json -out=gosec-report.json ./admin/... || true | |
| - name: Upload security report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: gosec-report | |
| path: gosec-report.json | |
| - name: Check for SQL injection vulnerabilities | |
| run: | | |
| # Use gosec report to detect SQL injection issues (rules G20x) | |
| if [ ! -f gosec-report.json ]; then | |
| echo "gosec-report.json not found. Ensure 'Run gosec security scanner' step completed successfully." | |
| exit 1 | |
| fi | |
| if grep -q '"rule_id":"G20' gosec-report.json; then | |
| echo "Potential SQL injection vulnerabilities detected by gosec (rules G20x)." | |
| grep -n '"rule_id":"G20' gosec-report.json || true | |
| exit 1 | |
| else | |
| echo "No SQL injection vulnerabilities (G20x rules) detected by gosec." | |
| fi | |
| # Performance tests | |
| # NOTE: Temporarily marked as non-blocking because pixiu admin is not fully functional | |
| performance-tests: | |
| name: Performance Tests | |
| runs-on: ubuntu-latest | |
| needs: [manual-deployment-test] | |
| continue-on-error: true # Allow CI to pass even if performance tests fail | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: 'go.mod' | |
| cache: true | |
| - name: Start etcd | |
| run: | | |
| docker run -d -p 2379:2379 \ | |
| --env ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \ | |
| --env ETCD_ADVERTISE_CLIENT_URLS=http://localhost:2379 \ | |
| --name etcd \ | |
| quay.io/coreos/etcd:v3.6.1 | |
| sleep 10 | |
| - name: Build and start admin service | |
| run: | | |
| go build -o /tmp/pixiu-admin ./cmd/admin/admin.go | |
| cat > /tmp/conf.yaml <<EOF | |
| server: | |
| address: "127.0.0.1:8081" | |
| etcd: | |
| address: "127.0.0.1:2379" | |
| path: "/pixiu/config/api" | |
| EOF | |
| nohup /tmp/pixiu-admin -c /tmp/conf.yaml > /tmp/admin.log 2>&1 & | |
| sleep 15 | |
| - name: Install Apache Bench | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y apache2-utils | |
| - name: Run load tests | |
| run: | | |
| echo "Testing base info endpoint..." | |
| ab -n 100 -c 5 http://localhost:8081/config/api/base | |
| echo -e "\nTesting resource list endpoint..." | |
| ab -n 100 -c 5 http://localhost:8081/config/api/resource/list | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| pkill -f pixiu-admin || true | |
| docker stop etcd || true | |
| docker rm etcd || true | |
| # Documentation check | |
| docs-check: | |
| name: Documentation Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Check API documentation exists | |
| run: | | |
| test -f admin/API.md || exit 1 | |
| test -f admin/API_CN.md || exit 1 | |
| test -f admin/README.md || exit 1 | |
| test -f admin/README_CN.md || exit 1 | |
| - name: Check Swagger documentation | |
| run: | | |
| test -f admin/doc/swagger.json || exit 1 | |
| test -f admin/doc/swagger.yaml || exit 1 | |
| - name: Verify API documentation completeness | |
| run: | | |
| # Check if all controller methods have Swagger annotations | |
| cd admin | |
| grep -r "@Tags\|@Summary\|@Router" controller/ | wc -l | |
| # Final status check | |
| ci-success: | |
| name: CI Success | |
| runs-on: ubuntu-latest | |
| needs: | |
| - backend-build | |
| - frontend-build | |
| - docker-compose-test | |
| # Temporarily skip deployment/integration tests as pixiu admin is not fully functional | |
| # - manual-deployment-test | |
| # - integration-tests | |
| # - performance-tests | |
| - code-quality | |
| - docs-check | |
| steps: | |
| - name: All tests passed | |
| run: | | |
| echo "✅ All Pixiu-Admin CI checks passed successfully!" |