Merge fix/duplicate-status-processing: Fix duplicate status processin… #67
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: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - 'v*' | |
| pull_request: | |
| branches: | |
| - main | |
| env: | |
| GO_VERSION: '1.25' | |
| REGISTRY: docker.io/supporttools | |
| jobs: | |
| # Lint job - runs golangci-lint | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Install golangci-lint | |
| run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest | |
| - name: Run golangci-lint | |
| run: golangci-lint run --timeout=5m | |
| # Test job - runs unit and integration tests with Go version matrix | |
| test: | |
| name: Test (Go ${{ matrix.go-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| go-version: ['1.24', '1.25'] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go ${{ matrix.go-version }} | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ matrix.go-version }} | |
| cache: true | |
| - name: Download dependencies | |
| run: go mod download | |
| - name: Run unit tests | |
| run: go test ./pkg/... ./cmd/... -v -race -covermode=atomic -coverprofile=coverage.out -short | |
| - name: Run integration tests | |
| run: | | |
| if [ -d "test/integration" ]; then | |
| go test ./test/integration/... -v -race -covermode=atomic -coverprofile=coverage-integration.out | |
| else | |
| echo "Integration tests not yet implemented - skipping" | |
| fi | |
| - name: Generate coverage report | |
| run: | | |
| go tool cover -func=coverage.out | grep total | awk '{print "Unit test coverage: " $3}' | |
| if [ -f coverage-integration.out ]; then | |
| go tool cover -func=coverage-integration.out | grep total | awk '{print "Integration test coverage: " $3}' | |
| fi | |
| - name: Check coverage threshold | |
| if: matrix.go-version == '1.25' | |
| run: | | |
| if [ ! -f coverage.out ]; then | |
| echo "::error::Coverage file not found" | |
| exit 1 | |
| fi | |
| COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//') | |
| if [ -z "$COVERAGE" ]; then | |
| echo "::error::Failed to extract coverage percentage" | |
| exit 1 | |
| fi | |
| THRESHOLD=80 | |
| echo "Current coverage: ${COVERAGE}%" | |
| echo "Minimum threshold: ${THRESHOLD}%" | |
| if (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then | |
| echo "::error::Coverage ${COVERAGE}% is below minimum threshold of ${THRESHOLD}%" | |
| exit 1 | |
| fi | |
| echo "Coverage check passed!" | |
| - name: Upload coverage to Codecov | |
| if: matrix.go-version == '1.25' | |
| uses: codecov/codecov-action@v4 | |
| continue-on-error: true # Codecov is informational; inline check above is the hard gate | |
| with: | |
| files: ./coverage.out,./coverage-integration.out | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| # Security scan - gosec | |
| security-gosec: | |
| name: Security Scan (gosec) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| security-events: write | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Run gosec | |
| uses: securego/gosec@master | |
| with: | |
| args: '-no-fail -fmt sarif -out gosec-results.sarif ./...' | |
| - name: Upload gosec results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v4 | |
| continue-on-error: true # gosec SARIF format may have compatibility issues | |
| with: | |
| sarif_file: gosec-results.sarif | |
| # Build job - builds the binary | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [lint, test] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Download dependencies | |
| run: go mod download | |
| - name: Build binary | |
| run: | | |
| VERSION=$(date +%s) | |
| GIT_COMMIT=$(git rev-parse HEAD) | |
| BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") | |
| mkdir -p bin | |
| cd cmd/node-doctor | |
| go build \ | |
| -ldflags="-X main.Version=${VERSION} -X main.GitCommit=${GIT_COMMIT} -X main.BuildTime=${BUILD_TIME}" \ | |
| -o ../../bin/node-doctor | |
| - name: Test binary | |
| run: ./bin/node-doctor --version | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: node-doctor-binary | |
| path: bin/node-doctor | |
| retention-days: 7 | |
| # Docker build and push - only on tags | |
| docker: | |
| name: Docker Build & Push | |
| runs-on: ubuntu-latest | |
| needs: [lint, test, build, security-gosec] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| security-events: write | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Extract tag name | |
| id: tag | |
| run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT | |
| - name: Build metadata | |
| id: meta | |
| run: | | |
| VERSION=${{ steps.tag.outputs.TAG }} | |
| GIT_COMMIT=$(git rev-parse HEAD) | |
| BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") | |
| echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "GIT_COMMIT=${GIT_COMMIT}" >> $GITHUB_OUTPUT | |
| echo "BUILD_TIME=${BUILD_TIME}" >> $GITHUB_OUTPUT | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: | | |
| ${{ env.REGISTRY }}/node-doctor:${{ steps.tag.outputs.TAG }} | |
| ${{ env.REGISTRY }}/node-doctor:latest | |
| build-args: | | |
| VERSION=${{ steps.meta.outputs.VERSION }} | |
| GIT_COMMIT=${{ steps.meta.outputs.GIT_COMMIT }} | |
| BUILD_TIME=${{ steps.meta.outputs.BUILD_TIME }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Run Trivy security scan on image | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: ${{ env.REGISTRY }}/node-doctor:${{ steps.tag.outputs.TAG }} | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v4 | |
| with: | |
| sarif_file: trivy-results.sarif | |
| # Summary job - provides overall status | |
| ci-success: | |
| name: CI Success | |
| runs-on: ubuntu-latest | |
| needs: [lint, test, build, security-gosec] | |
| if: always() | |
| steps: | |
| - name: Check job results | |
| run: | | |
| if [[ "${{ needs.lint.result }}" != "success" ]] || \ | |
| [[ "${{ needs.test.result }}" != "success" ]] || \ | |
| [[ "${{ needs.build.result }}" != "success" ]] || \ | |
| [[ "${{ needs.security-gosec.result }}" != "success" ]]; then | |
| echo "One or more CI jobs failed" | |
| exit 1 | |
| fi | |
| echo "All CI jobs passed successfully!" |