feat(ci-cd): refactor testing steps to handle multiple modules in a s… #23
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-cd | |
| on: | |
| push: | |
| branches: [ dev, master ] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| DOCKER_REGISTRY: docker.io | |
| DOCKER_REPOSITORY: marcofontana17/cce_prototipo | |
| jobs: | |
| build-and-test: | |
| name: Run Tests | |
| runs-on: ${{ matrix.os }} | |
| # Force Bash for every `run:` step | |
| defaults: | |
| run: | |
| shell: bash | |
| strategy: | |
| matrix: | |
| os: | |
| - ubuntu-22.04 | |
| - windows-2022 | |
| - macos-12 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.24' | |
| check-latest: true | |
| - name: Cache Go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go- | |
| - name: Test all modules on ${{ matrix.os }} | |
| run: | | |
| # Define modules | |
| modules=("api_gateway:./api_gateway" "service:./service" "utils:./utils") | |
| # Initialize variables for summary | |
| total_coverage=0 | |
| module_count=0 | |
| failed_modules=() | |
| echo "=== Testing all modules on ${{ matrix.os }} ===" | |
| echo "" | |
| # Loop through each module | |
| for module_info in "${modules[@]}"; do | |
| module_name="${module_info%%:*}" | |
| module_path="${module_info##*:}" | |
| echo "========================================" | |
| echo "Testing module: $module_name" | |
| echo "Path: $module_path" | |
| echo "========================================" | |
| cd "$module_path" | |
| # Download and verify dependencies | |
| echo "Downloading dependencies..." | |
| if ! go mod download; then | |
| echo "Failed to download dependencies for $module_name" | |
| failed_modules+=("$module_name:deps") | |
| cd - > /dev/null | |
| continue | |
| fi | |
| echo "Verifying dependencies..." | |
| if ! go mod verify; then | |
| echo "Failed to verify dependencies for $module_name" | |
| failed_modules+=("$module_name:verify") | |
| cd - > /dev/null | |
| continue | |
| fi | |
| # Run basic tests | |
| echo "Running tests..." | |
| if ! go test -v ./...; then | |
| echo "Tests failed for $module_name" | |
| failed_modules+=("$module_name:tests") | |
| cd - > /dev/null | |
| continue | |
| fi | |
| # Run tests with race detector | |
| echo "Running tests with race detector..." | |
| if ! go test -race -short ./...; then | |
| echo "Race detector tests failed for $module_name" | |
| failed_modules+=("$module_name:race") | |
| cd - > /dev/null | |
| continue | |
| fi | |
| # Run tests with coverage | |
| echo "Running tests with coverage..." | |
| if go test -coverprofile=coverage.out ./...; then | |
| if [ -f coverage.out ]; then | |
| echo "Coverage report for $module_name:" | |
| go tool cover -func=coverage.out | |
| # Extract coverage percentage | |
| coverage=$(go tool cover -func=coverage.out | grep total | awk '{print substr($3, 1, length($3)-1)}') | |
| if [ -n "$coverage" ]; then | |
| echo "Total coverage for $module_name: ${coverage}%" | |
| # Add to total for average calculation | |
| total_coverage=$(echo "$total_coverage + $coverage" | bc -l) | |
| module_count=$((module_count + 1)) | |
| else | |
| echo "Could not extract coverage percentage for $module_name" | |
| fi | |
| else | |
| echo "No coverage file generated for $module_name" | |
| fi | |
| else | |
| echo "Coverage tests failed for $module_name" | |
| failed_modules+=("$module_name:coverage-tests") | |
| fi | |
| echo "Completed testing $module_name" | |
| echo "" | |
| cd - > /dev/null | |
| done | |
| # Summary | |
| echo "========================================" | |
| echo "TEST SUMMARY for ${{ matrix.os }}" | |
| echo "========================================" | |
| if [ ${#failed_modules[@]} -eq 0 ]; then | |
| echo "All modules passed all tests!" | |
| else | |
| echo "Some modules had failures:" | |
| for failure in "${failed_modules[@]}"; do | |
| echo " - $failure" | |
| done | |
| fi | |
| if [ $module_count -gt 0 ]; then | |
| average_coverage=$(echo "scale=2; $total_coverage / $module_count" | bc -l) | |
| echo "Average coverage across all modules: ${average_coverage}%" | |
| fi | |
| echo "========================================" | |
| # Exit with error if any module failed | |
| if [ ${#failed_modules[@]} -gt 0 ]; then | |
| echo "Build failed due to module failures" | |
| exit 1 | |
| fi | |
| echo "All tests passed successfully!" | |
| # Optional: Upload coverage reports (commented out as in your example) | |
| # - name: Upload coverage reports | |
| # run: | | |
| # modules=("api_gateway:./api_gateway" "service:./service" "utils:./utils") | |
| # for module_info in "${modules[@]}"; do | |
| # module_name="${module_info%%:*}" | |
| # module_path="${module_info##*:}" | |
| # if [ -f "$module_path/coverage.out" ]; then | |
| # echo "Uploading coverage for $module_name" | |
| # # Upload logic here | |
| # fi | |
| # done | |
| push-docker-images: | |
| runs-on: ubuntu-latest | |
| name: Build and Push Docker Images | |
| needs: build-and-test # This ensures tests must pass before building | |
| strategy: | |
| matrix: | |
| service: | |
| - name: "api_gateway" | |
| dockerfile: "./api_gateway/Dockerfile" | |
| suffix: "api_gateway" | |
| - name: "service" | |
| dockerfile: "./service/Dockerfile" | |
| suffix: "service" | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to DockerHub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_PASSWORD }} | |
| - name: Extract metadata for ${{ matrix.service.name }} | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.DOCKER_REPOSITORY }} | |
| tags: | | |
| type=raw,value=${{ matrix.service.suffix }}-latest,enable=${{ github.ref == 'refs/heads/master' }} | |
| type=raw,value=${{ matrix.service.suffix }}-dev-latest,enable=${{ github.ref == 'refs/heads/dev' }} | |
| type=sha,prefix=${{ github.ref_name }}-,suffix=-${{ matrix.service.suffix }} | |
| - name: Build and push ${{ matrix.service.name }} | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ${{ matrix.service.dockerfile }} | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |