name: Build and Deploy Log Center on: push: branches: - main - master jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 with: config-inline: | [registry."docker.io"] mirrors = ["https://docker.m.daocloud.io", "https://docker.1panel.live", "https://hub.rat.dev"] - name: Login to Huawei Cloud SWR uses: docker/login-action@v2 with: registry: ${{ secrets.SWR_SERVER }} username: ${{ secrets.SWR_USERNAME }} password: ${{ secrets.SWR_PASSWORD }} # Build API Image - name: Build and Push API id: build-api run: | set -o pipefail docker buildx build \ --push \ --provenance=false \ --tag ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/log-center-api:latest \ -f ./Dockerfile \ . 2>&1 | tee /tmp/build-api.log # Build Web Image - name: Build and Push Web id: build-web run: | set -o pipefail docker buildx build \ --push \ --provenance=false \ --build-arg VITE_API_BASE_URL=https://qiyuan-log-center-api.airlabs.art \ --tag ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/log-center-web:latest \ -f ./web/Dockerfile \ ./web 2>&1 | tee /tmp/build-web.log # Build K8s Monitor Image - name: Build and Push K8s Monitor id: build-monitor run: | set -o pipefail docker buildx build \ --push \ --provenance=false \ --tag ${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/k8s-pod-monitor:latest \ -f ./k8s-monitor/Dockerfile \ ./k8s-monitor 2>&1 | tee /tmp/build-monitor.log - name: Setup Kubectl run: | curl -LO "https://files.m.daocloud.io/dl.k8s.io/release/v1.28.2/bin/linux/amd64/kubectl" chmod +x kubectl mv kubectl /usr/local/bin/ - name: Deploy to K3s uses: Azure/k8s-set-context@v3 with: method: kubeconfig kubeconfig: ${{ secrets.KUBE_CONFIG }} - name: Update K8s Manifests id: deploy run: | echo "Environment: Production" # Replace image placeholders sed -i "s|\${CI_REGISTRY_IMAGE}/log-center-api:latest|${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/log-center-api:latest|g" k8s/api-deployment-prod.yaml sed -i "s|\${CI_REGISTRY_IMAGE}/log-center-web:latest|${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/log-center-web:latest|g" k8s/web-deployment-prod.yaml sed -i "s|\${CI_REGISTRY_IMAGE}/k8s-pod-monitor:latest|${{ secrets.SWR_SERVER }}/${{ secrets.SWR_ORG }}/k8s-pod-monitor:latest|g" k8s/monitor-cronjob.yaml # Apply configurations and capture output set -o pipefail { kubectl apply -f k8s/api-deployment-prod.yaml kubectl apply -f k8s/web-deployment-prod.yaml kubectl apply -f k8s/ingress.yaml kubectl apply -f k8s/monitor-cronjob.yaml # Restart deployments kubectl rollout restart deployment/log-center-api kubectl rollout restart deployment/log-center-web } 2>&1 | tee /tmp/deploy.log # ==================== CI/CD 错误上报 ==================== - name: Report failure to Log Center if: failure() run: | # 收集各阶段日志(取最后 50 行) BUILD_API_LOG="" BUILD_WEB_LOG="" BUILD_MONITOR_LOG="" DEPLOY_LOG="" FAILED_STEP="unknown" PROJECT_ID="log_center_api" if [[ "${{ steps.build-api.outcome }}" == "failure" ]]; then FAILED_STEP="build-api" PROJECT_ID="log_center_api" if [ -f /tmp/build-api.log ]; then BUILD_API_LOG=$(tail -50 /tmp/build-api.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') fi elif [[ "${{ steps.build-web.outcome }}" == "failure" ]]; then FAILED_STEP="build-web" PROJECT_ID="log_center_web" if [ -f /tmp/build-web.log ]; then BUILD_WEB_LOG=$(tail -50 /tmp/build-web.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') fi elif [[ "${{ steps.build-monitor.outcome }}" == "failure" ]]; then FAILED_STEP="build-monitor" PROJECT_ID="log_center_api" if [ -f /tmp/build-monitor.log ]; then BUILD_MONITOR_LOG=$(tail -50 /tmp/build-monitor.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') fi elif [[ "${{ steps.deploy.outcome }}" == "failure" ]]; then FAILED_STEP="deploy" PROJECT_ID="log_center_api" if [ -f /tmp/deploy.log ]; then DEPLOY_LOG=$(tail -50 /tmp/deploy.log | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g') fi fi # 合并错误日志 ERROR_LOG="${BUILD_API_LOG}${BUILD_WEB_LOG}${BUILD_MONITOR_LOG}${DEPLOY_LOG}" if [ -z "$ERROR_LOG" ]; then ERROR_LOG="No captured output. Check Gitea Actions UI for details." fi # 判断 source if [[ "$FAILED_STEP" == "deploy" ]]; then SOURCE="deployment" ERROR_TYPE="DeployError" else SOURCE="cicd" ERROR_TYPE="DockerBuildError" fi curl -s -X POST "https://qiyuan-log-center-api.airlabs.art/api/v1/logs/report" \ -H "Content-Type: application/json" \ -d "{ \"project_id\": \"${PROJECT_ID}\", \"environment\": \"${{ github.ref_name }}\", \"level\": \"ERROR\", \"source\": \"${SOURCE}\", \"commit_hash\": \"${{ github.sha }}\", \"repo_url\": \"https://gitea.airlabs.art/zyc/log-center.git\", \"error\": { \"type\": \"${ERROR_TYPE}\", \"message\": \"[${FAILED_STEP}] Build and Deploy Log Center failed on branch ${{ github.ref_name }}\", \"stack_trace\": [\"${ERROR_LOG}\"] }, \"context\": { \"job_name\": \"build-and-deploy\", \"step_name\": \"${FAILED_STEP}\", \"workflow\": \"${{ github.workflow }}\", \"run_id\": \"${{ github.run_number }}\", \"branch\": \"${{ github.ref_name }}\", \"actor\": \"${{ github.actor }}\", \"commit\": \"${{ github.sha }}\", \"run_url\": \"https://gitea.airlabs.art/${{ github.repository }}/actions/runs/${{ github.run_number }}\" } }" || true