Skip to content

Commit c589f89

Browse files
Updating WorkFlow with Retries for Failing Tests (#1541)
1 parent 8458cb7 commit c589f89

File tree

1 file changed

+128
-45
lines changed

1 file changed

+128
-45
lines changed

.github/workflows/go.yml

+128-45
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
11
---
22
name: Workflow-Pipeline
33

4+
# Define when this workflow should run
45
on:
6+
# Run on push events to main or development branches
57
push:
68
branches:
79
- main
810
- development
911
paths-ignore:
10-
- 'docs/**'
12+
- 'docs/**' # Ignore changes to docs folder
13+
# Run on pull requests to main or development branches
1114
pull_request:
1215
branches:
1316
- main
1417
- development
1518
paths-ignore:
16-
- 'docs/**'
19+
- 'docs/**' # Ignore changes to docs folder
1720

21+
# Define the jobs that this workflow will run
1822
jobs:
23+
# Job for testing the examples directory
1924
Example-Unit-Testing:
2025
name: Example Unit Testing (v${{ matrix.go-version }})🛠
2126
runs-on: ubuntu-latest
27+
# Define a matrix strategy to test against multiple Go versions
2228
strategy:
2329
matrix:
2430
go-version: ['1.24','1.23', '1.22']
31+
# Continue with other jobs if one version fails
32+
fail-fast: false
2533

34+
# Define service containers that tests depend on
2635
services:
36+
# Kafka service
2737
kafka:
2838
image: bitnami/kafka:3.4
2939
ports:
@@ -41,12 +51,14 @@ jobs:
4151
ALLOW_PLAINTEXT_LISTENER: yes
4252
KAFKA_CFG_NODE_ID: 1
4353

54+
# Redis service
4455
redis:
4556
image: redis:7.0.5
4657
ports:
4758
- "2002:6379"
4859
options: "--entrypoint redis-server"
4960

61+
# MySQL service
5062
mysql:
5163
image: mysql:8.2.0
5264
ports:
@@ -55,12 +67,14 @@ jobs:
5567
MYSQL_ROOT_PASSWORD: "password"
5668
MYSQL_DATABASE: "test"
5769

70+
# Steps to execute for this job
5871
steps:
5972
- name: Checkout code into go module directory
6073
uses: actions/checkout@v4
6174
with:
62-
fetch-depth: 0
75+
fetch-depth: 0 # Full git history for accurate testing
6376

77+
# Set up the Go environment with the specified version
6478
- name: Set up Go ${{ matrix.go-version }}
6579
uses: actions/setup-go@v5
6680
with:
@@ -74,26 +88,38 @@ jobs:
7488
- name: Start Zipkin
7589
run: docker run -d -p 2005:9411 openzipkin/zipkin:latest
7690

77-
- name: Test
78-
run: |
79-
export APP_ENV=test
80-
go test gofr.dev/examples/... -v -short -coverprofile packageWithpbgo.cov -coverpkg=gofr.dev/examples/...
81-
grep -vE '^gofr\.dev\/.*\.pb\.go' packageWithpbgo.cov > profile.cov
82-
go tool cover -func profile.cov
83-
91+
# Run tests with automatic retry on failures
92+
- name: Test with Retry Logic
93+
id: test
94+
uses: nick-fields/retry@v2
95+
with:
96+
timeout_minutes: 5 # Maximum time for the tests to run
97+
max_attempts: 2 # Retry up to 2 times if tests fail
98+
command: |
99+
export APP_ENV=test
100+
# Run tests for the examples directory with coverage
101+
go test gofr.dev/examples/... -v -short -coverprofile packageWithpbgo.cov -coverpkg=gofr.dev/examples/...
102+
# Filter out generated protobuf files from coverage report
103+
grep -vE '^gofr\.dev\/.*\.pb\.go' packageWithpbgo.cov > profile.cov
104+
# Display coverage statistics
105+
go tool cover -func profile.cov
106+
107+
# Upload coverage report for the 1.24 Go version only
84108
- name: Upload Test Coverage
85-
if: ${{ matrix.go-version == '1.22'}}
109+
if: ${{ matrix.go-version == '1.24'}}
86110
uses: actions/upload-artifact@v4
87111
with:
88112
name: Example-Test-Report
89113
path: profile.cov
90114

115+
# Job for testing the pkg directory
91116
PKG-Unit-Testing:
92117
name: PKG Unit Testing (v${{ matrix.go-version }})🛠
93118
runs-on: ubuntu-latest
94119
strategy:
95120
matrix:
96121
go-version: ['1.24','1.23', '1.22']
122+
fail-fast: false
97123

98124
steps:
99125
- name: Checkout code into go module directory
@@ -111,58 +137,74 @@ jobs:
111137
run: |
112138
go mod download
113139
114-
- name: Test
115-
run: |
116-
export APP_ENV=test
117-
go test gofr.dev/pkg/... -v -short -coverprofile package.cov -coverpkg=gofr.dev/pkg/...
118-
grep -v '/mock_' package.cov > profile.cov
119-
go tool cover -func profile.cov
120-
140+
# Run pkg tests with automatic retry logic
141+
- name: Test with Retry Logic
142+
id: test
143+
uses: nick-fields/retry@v2
144+
with:
145+
timeout_minutes: 5
146+
max_attempts: 2
147+
command: |
148+
export APP_ENV=test
149+
# Run tests for the pkg directory with coverage
150+
go test gofr.dev/pkg/... -v -short -coverprofile package.cov -coverpkg=gofr.dev/pkg/...
151+
# Filter out mock files from coverage report
152+
grep -v '/mock_' package.cov > profile.cov
153+
# Display coverage statistics
154+
go tool cover -func profile.cov
155+
156+
# Upload coverage report for the 1.24 Go version only
121157
- name: Upload Test Coverage
122158
if: ${{ matrix.go-version == '1.24'}}
123159
uses: actions/upload-artifact@v4
124160
with:
125161
name: PKG-Coverage-Report
126162
path: profile.cov
127163

164+
# Job for analyzing and reporting code coverage
128165
parse_coverage:
129166
name: Code Coverage
130167
runs-on: ubuntu-latest
131-
needs: [ Example-Unit-Testing,PKG-Unit-Testing]
168+
# This job runs after both Example and PKG testing are complete
169+
needs: [ Example-Unit-Testing,PKG-Unit-Testing ]
132170
steps:
133171
- name: Check out code into the Go module directory
134172
uses: actions/checkout@v4
135173

174+
# Download coverage reports from previous jobs
136175
- name: Download Coverage Report
137176
uses: actions/download-artifact@v4
138177
with:
139178
path: artifacts
140179

141-
180+
# Merge the coverage reports from Example and PKG tests
142181
- name: Merge Coverage Files
143182
working-directory: artifacts
144183
run: |
145184
awk '!/^mode: / && FNR==1{print "mode: set"} {print}' ./Example-Test-Report/profile.cov > merged_profile.cov
146185
tail -n +2 ./PKG-Coverage-Report/profile.cov >> merged_profile.cov
147186
187+
# Calculate and output the total code coverage percentage
148188
- name: Parse code-coverage value
149189
working-directory: artifacts
150190
run: |
151191
codeCoverage=$(go tool cover -func=merged_profile.cov | grep total | awk '{print $3}')
152192
codeCoverage=${codeCoverage%?}
153193
echo "CODE_COVERAGE=$codeCoverage" >> $GITHUB_ENV
154-
155194
# - name: Check if code-coverage is greater than threshold
156195
# run: |
157196
# codeCoverage=${{ env.CODE_COVERAGE }}
158197
# codeCoverage=${codeCoverage%??}
159198
# if [[ $codeCoverage -lt 92 ]]; then echo "code coverage cannot be less than 92%, currently its ${{ env.CODE_COVERAGE }}%" && exit 1; fi;
199+
200+
# Job for testing submodules inside the pkg directory
160201
Submodule-Unit-Testing:
161202
name: Submodule Unit Testing (v${{ matrix.go-version }})🛠
162203
runs-on: ubuntu-latest
163204
strategy:
164205
matrix:
165206
go-version: ['1.24','1.23', '1.22']
207+
fail-fast: false
166208

167209
steps:
168210
- name: Checkout code into go module directory
@@ -176,55 +218,90 @@ jobs:
176218
go-version: ${{ matrix.go-version }}
177219
id: Go
178220

179-
- name: Detect and Test Submodules
221+
# Find all submodules (directories with go.mod files) in the pkg directory
222+
- name: Detect Submodules
223+
id: detect_submodules
180224
run: |
181225
# Find all directories containing a go.mod file within 'pkg'
182-
for module in $(find pkg -name "go.mod" -exec dirname {} \;); do
183-
echo "Testing module: $module"
184-
cd $module
185-
186-
# Extract module name (replace '/' with '_')
187-
module_name=$(echo $module | tr '/' '_')
188-
189-
# Download dependencies for the submodule
190-
go mod download
191-
go mod tidy
226+
SUBMODULES=$(find pkg -name "go.mod" -exec dirname {} \; | jq -R -s -c 'split("\n") | map(select(length > 0))')
227+
echo "submodules=$SUBMODULES" >> $GITHUB_OUTPUT
192228
193-
# Run tests for the submodule and generate coverage
229+
# Test all submodules in parallel with retry logic
230+
- name: Test Submodules with Retry and Parallelism
231+
id: test_submodules
232+
uses: nick-fields/retry@v2
233+
with:
234+
timeout_minutes: 5
235+
max_attempts: 2
236+
command: |
194237
export APP_ENV=test
195-
go test ./... -v -short -coverprofile=${module_name}.cov -coverpkg=./...
196-
197-
# Return to the root directory
198-
cd -
199-
done
200-
238+
# Create a directory for coverage reports
239+
mkdir -p coverage_reports
240+
241+
# Get the list of submodules
242+
SUBMODULES='${{ steps.detect_submodules.outputs.submodules }}'
243+
244+
# Process each submodule in parallel with a maximum of 4 parallel jobs
245+
echo $SUBMODULES | jq -c '.[]' | xargs -I{} -P 4 bash -c '
246+
module={}
247+
echo "Testing module: $module"
248+
cd $module
249+
250+
# Extract module name (replace / with _)
251+
module_name=$(echo $module | tr "/" "_")
252+
253+
# Download dependencies for the submodule
254+
go mod download
255+
go mod tidy
256+
257+
# Run tests with a focus on failed tests first
258+
go test ./... -v -short -coverprofile=${module_name}.cov -coverpkg=./...
259+
260+
# Copy coverage file to the coverage_reports directory
261+
cp ${module_name}.cov ../../../coverage_reports/
262+
263+
cd -
264+
'
265+
266+
# Upload submodule coverage reports as an artifact
201267
- name: Upload Coverage Reports
202268
uses: actions/upload-artifact@v4
203269
with:
204-
name: coverage-reports
205-
path: pkg/**/*.cov
206-
270+
name: submodule-coverage-reports
271+
path: coverage_reports/*.cov
207272

273+
# Job for uploading coverage to external services (CodeClimate)
208274
upload_coverage:
209275
name: Upload Coverage📊
210276
runs-on: ubuntu-latest
211-
needs: [Example-Unit-Testing,PKG-Unit-Testing]
277+
# This job only needs example and pkg test results, not submodules
278+
needs: [Example-Unit-Testing, PKG-Unit-Testing]
279+
# Only run this job on pushes to the development branch
212280
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development'}}
213281
steps:
214282
- name: Check out code into the Go module directory
215283
uses: actions/checkout@v4
216284

285+
# Download coverage artifacts
217286
- name: Download Coverage Report
218287
uses: actions/download-artifact@v4
219288
with:
220289
path: artifacts
221290

291+
# Merge coverage from example and pkg tests only
222292
- name: Merge Coverage Files
223293
working-directory: artifacts
224294
run: |
225-
awk '!/^mode: / && FNR==1{print "mode: set"} {print}' ./Example-Test-Report/profile.cov > merged_profile.cov
295+
echo "mode: set" > merged_profile.cov
296+
tail -n +2 ./Example-Test-Report/profile.cov >> merged_profile.cov
226297
tail -n +2 ./PKG-Coverage-Report/profile.cov >> merged_profile.cov
227-
298+
299+
# Generate and print total coverage percentage
300+
echo "Total Coverage:"
301+
go tool cover -func=merged_profile.cov | tail -n 1
302+
shell: bash
303+
304+
# Upload merged coverage to CodeClimate for analysis
228305
- name: Upload
229306
uses: paambaati/[email protected]
230307
env:
@@ -233,6 +310,7 @@ jobs:
233310
coverageLocations: artifacts/merged_profile.cov:gocov
234311
prefix: gofr.dev
235312

313+
# Job for code quality checks
236314
code_quality:
237315
name: Code Quality🎖️
238316
runs-on: ubuntu-latest
@@ -246,6 +324,7 @@ jobs:
246324
go-version: '1.24'
247325
cache: false
248326

327+
# Install the linting tool
249328
- name: Install golangci-lint
250329
run: |
251330
go install github.com/golangci/golangci-lint/cmd/[email protected]
@@ -254,10 +333,12 @@ jobs:
254333
run: |
255334
go mod tidy
256335
336+
# Run linter on the root module
257337
- name: Lint Root Module
258338
run: |
259339
golangci-lint run --out-format=colored-line-number --timeout=5m
260340
341+
# Run linter on each submodule
261342
- name: Lint Submodules
262343
run: |
263344
echo "Searching for submodules..."
@@ -276,6 +357,7 @@ jobs:
276357
exit 1 # Fail the job if there are linting errors in submodules
277358
fi
278359
360+
# Job for checking filename conventions
279361
linting_party:
280362
name: Linting Party🥳
281363
runs-on: ubuntu-latest
@@ -288,6 +370,7 @@ jobs:
288370
with:
289371
go-version: 1.24
290372

373+
# Check file naming conventions using ls-lint
291374
- name: Check for file names errors
292375
uses: ls-lint/[email protected]
293376
with:

0 commit comments

Comments
 (0)