-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add integration tests for Docker client and update CI workflow #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces integration tests for the Docker client and updates the CI workflow to run both unit and integration tests separately with merged coverage reporting. The changes improve test coverage for Docker operations and ensure that Docker is available during CI runs.
Key Changes:
- Added comprehensive integration tests for Docker client operations including container lifecycle, image management, and volume operations
- Created a platform-aware shell script to facilitate running integration tests locally
- Updated GitHub Actions workflow to run unit and integration tests separately, then merge coverage reports using
gocovmerge
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
internal/docker/docker_client_integration_test.go |
Adds 14 integration tests covering Docker client functionality including container creation, image pulling, volume mounting, and container lifecycle management |
run_integration_tests.sh |
Provides a platform-aware script that detects OS (macOS, Linux, Windows), configures Docker host, verifies Docker daemon accessibility, and runs integration tests |
.github/workflows/publish-coverage.yaml |
Updates CI workflow to start Docker service, run unit and integration tests separately, merge coverage reports, and upload to Codecov with error handling |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 16 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| echo "Running: go test $TEST_FLAGS $suite" | ||
| echo "" | ||
|
|
||
| if ! go test $TEST_FLAGS "$suite"; then |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TEST_FLAGS variable is used unquoted in the command, which will cause word splitting issues. While this may work currently, it's a shell scripting anti-pattern that can lead to unexpected behavior if flags contain spaces. Consider using an array instead:
TEST_FLAGS=(-v -tags=integration -timeout 5m)
# Then use: go test "${TEST_FLAGS[@]}" "$suite"Or if keeping as a string, quote it properly in the command.
| // Setup test languages on first test run | ||
| if len(testLanguages) == 0 { | ||
| setupTestLanguages() | ||
| } |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check if len(testLanguages) == 0 and call to setupTestLanguages() is repeated in multiple test functions (here and in TestEnsureImage_AllSupportedLanguages). This logic should be consolidated to avoid duplication. Consider using sync.Once with a package-level var once sync.Once to ensure setup happens exactly once, or move this to TestMain.
| ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) | ||
| defer cancel() | ||
|
|
||
| err = dc.EnsureImage(ctx, testImageName) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test uses testImageName without ensuring it's initialized. Add initialization check at the beginning of the test.
| run: go test -tags=integration -coverprofile=coverage-integration.txt -covermode=atomic ./... | ||
|
|
||
| - name: Merge coverage reports | ||
| run: | |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The merge coverage reports step could fail silently if one of the coverage files doesn't exist. Consider adding error checking to ensure both coverage files were generated before attempting to merge them:
- name: Merge coverage reports
run: |
if [ ! -f coverage-unit.txt ] || [ ! -f coverage-integration.txt ]; then
echo "Error: One or more coverage files are missing"
exit 1
fi
go install github.com/wadey/gocovmerge@latest
gocovmerge coverage-unit.txt coverage-integration.txt > coverage.txt| run: | | |
| run: | | |
| if [ ! -f coverage-unit.txt ] || [ ! -f coverage-integration.txt ]; then | |
| echo "Error: One or more coverage files are missing" | |
| exit 1 | |
| fi |
| - name: Run tests | ||
| run: go test -coverprofile=coverage.txt ./... | ||
| - name: Run unit tests with coverage | ||
| run: go test -coverprofile=coverage-unit.txt -covermode=atomic ./... |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unit tests will also execute integration tests because the -tags=integration build tag only controls which files are compiled, not which tests run. Running go test ./... without excluding the integration tag will compile and run ALL tests including integration tests (since files without build tags are always compiled). This means:
- Integration tests will run twice (once in line 39, once in line 44)
- The "unit" coverage report will actually include integration test coverage
To fix this, you should either:
- Skip integration tests in the unit test step using:
go test -short -coverprofile=coverage-unit.txt -covermode=atomic ./...(and ensure all integration tests checktesting.Short()) - Or exclude integration test files explicitly from the unit test run
| run: go test -coverprofile=coverage-unit.txt -covermode=atomic ./... | |
| run: go test -short -coverprofile=coverage-unit.txt -covermode=atomic ./... |
| image: docker:dind | ||
| options: >- | ||
| --privileged | ||
| --health-cmd="docker ps" |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The health check command docker ps will not work correctly with the Docker-in-Docker setup as configured. Inside the docker:dind container, the docker CLI client may not be available or properly configured to connect to the daemon. The default health check for docker:dind is typically dockerd-healthcheck or you can use wget -O- http://localhost:2375/_ping if exposing the Docker API. Consider using the image's built-in health check or a more appropriate command.
| --health-cmd="docker ps" | |
| --health-cmd="dockerd-healthcheck" |
| func setupTestLanguages() { | ||
| // Get all supported languages | ||
| supportedLangs := languages.GetSupportedLanguages() | ||
| for _, langStr := range supportedLangs { | ||
| if lang, err := languages.ParseLanguageType(langStr); err == nil { | ||
| testLanguages = append(testLanguages, lang) | ||
| } | ||
| } | ||
|
|
||
| // Use the first language's image for basic tests | ||
| if len(testLanguages) > 0 { | ||
| if image, err := testLanguages[0].GetDockerImage(""); err == nil { | ||
| testImageName = image | ||
| } | ||
| } | ||
| } |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setupTestLanguages() function modifies global variables (testLanguages and testImageName) without any synchronization. If tests are run in parallel (Go's default behavior with go test), this could lead to race conditions. Multiple tests may call this function simultaneously, causing concurrent writes to these global slices and strings.
Consider one of these solutions:
- Use
sync.Onceto ensure the setup only happens once - Call
t.Parallel()carefully only in tests that don't mutate these globals - Move the setup to a
TestMainfunction that runs before any tests
| ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) | ||
| defer cancel() | ||
|
|
||
| err = dc.EnsureImage(ctx, testImageName) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test uses testImageName without ensuring it's initialized. Since Go test execution order is not guaranteed, if this test runs before TestNewDockerClient_Success, testImageName will be empty and cause the test to fail. Add initialization check similar to lines 59-62.
| ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) | ||
| defer cancel() | ||
|
|
||
| err = dc.EnsureImage(ctx, testImageName) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test uses testImageName without ensuring it's initialized. Add initialization check at the beginning of the test.
| ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) | ||
| defer cancel() | ||
|
|
||
| err = dc.EnsureImage(ctx, testImageName) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test uses testImageName without ensuring it's initialized. Add initialization check at the beginning of the test.
This pull request improves the testing and coverage reporting workflow by separating unit and integration tests, ensuring Docker is available for integration tests, and merging coverage reports for comprehensive coverage analysis. It also introduces a script to run integration tests in a platform-aware manner.
Testing and coverage workflow improvements:
.github/workflows/publish-coverage.yamlnow starts a Docker service (docker:dind) for integration tests, ensuring Docker is available during CI runs.coverage-unit.txtandcoverage-integration.txt). These reports are then merged usinggocovmergefor unified coverage reporting.Integration test automation:
run_integration_tests.shthat detects the platform (macOS, Linux, Windows), configures theDOCKER_HOSTenvironment variable as needed, checks Docker daemon accessibility, and runs integration tests with appropriate flags.