Skip to content

Conversation

@pilat
Copy link
Owner

@pilat pilat commented Dec 21, 2025

  • Rewrite tests to Golang
  • Run E2E tests as part of CI/CD

Summary by CodeRabbit

Release Notes

  • New Features

    • Added automated CI/CD pipeline with linting, unit testing, and end-to-end testing
    • Added build automation targets via Makefile
  • Tests

    • Migrated end-to-end test suite from Python to Go-based implementation
    • Added comprehensive test coverage for project initialization, operations, and cleanup workflows
  • Chores

    • Removed legacy Python test framework and dependencies

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

Walkthrough

Migrates end-to-end tests from Python (pytest) to Go (testify suite pattern), introduces a GitHub Actions CI workflow for automated linting and testing, and adds a Makefile for development task automation.

Changes

Cohort / File(s) Summary
CI and Build Infrastructure
\\.github/workflows/ci.yaml, Makefile
Adds GitHub Actions workflow with lint-and-test and e2e jobs; configures Go 1.23 caching, golangci-lint checks, unit tests with race detector, and e2e tests with 10-minute timeout. Introduces Makefile with targets for tidy, vendor, lint, test, test-e2e, build, and clean.
E2E Test Suite (Go)
tests/e2e/e2e_test.go
Adds comprehensive Go-based E2E test suite with E2ESuite type, SetupSuite/TearDownSuite lifecycle methods, and test cases (Test10_ProjectInitialization through Test90_ProjectCleanup). Includes helper methods for git operations, directory management, devbox CLI invocation, docker/container checks, HTTP validation, and docker-compose manipulation.
Test Fixture Configuration
tests/e2e/fixtures/manifest/docker-compose.yml
Updates x-devbox-sources.service-1.branch from master to main.
Deleted Python Test Infrastructure
tests/e2e/conftest.py, tests/e2e/helpers.py, tests/e2e/pytest.ini, tests/e2e/requirements.txt, tests/e2e/run_tests.sh, tests/e2e/test_10_init.py, tests/e2e/test_30_info.py, tests/e2e/test_40_project_context.py, tests/e2e/test_50_mount_context.py, tests/e2e/test_55_mount_for_build.py, tests/e2e/test_57_mount_for_volume.py, tests/e2e/test_60_operations.py, tests/e2e/test_90_cleanup.py
Removes pytest configuration, Python helper utilities, virtual environment runner script, and nine individual Python test modules. All E2E test scenarios (initialization, info operations, context detection, mount operations, build/volume interactions, lifecycle operations, and cleanup) are consolidated into the new Go suite.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Key areas requiring attention:

  • tests/e2e/e2e_test.go: Review the comprehensive test suite for correctness of helper methods, setup/teardown procedures, git/docker operations, and assertions; verify all Python test scenarios are functionally equivalent in the new Go implementation.
  • CI workflow structure: Validate Go caching, golangci-lint configuration, race detector flags, and e2e test timeout settings.
  • Test fixture updates: Confirm the branch change from master to main aligns with repository configuration.
  • Python-to-Go migration completeness: Cross-reference deleted Python tests against new Go test methods to ensure no test coverage is lost.

Poem

🐰 The tests have hopped from Python's nest,
Into Go's embrace for the final quest,
With workflows spinning and Makefile's might,
CI pipelines dancing from day into night,
A leaner, swifter way to test—burrow approved!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: converting Python-based e2e tests to Go and integrating them into the CI workflow.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ci/tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pilat pilat self-assigned this Dec 21, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
Makefile (1)

1-24: Well-structured Makefile for Go project automation.

The targets align well with the CI workflow. A couple of observations:

  1. The test-e2e target doesn't include the -race flag, unlike test. This is likely intentional for E2E tests (performance reasons), but worth confirming.
  2. Consider adding a dependency on build for test-e2e to ensure the binary is built before running E2E tests locally.
🔎 Optional: Add build dependency for test-e2e
-test-e2e:
+test-e2e: build
 	go test -v ./tests/e2e/ -timeout 10m
.github/workflows/ci.yaml (2)

28-31: Consider pinning golangci-lint version for reproducible builds.

Using version: latest may cause unexpected CI failures when new linter rules are introduced. Pinning to a specific version ensures consistent behavior.

🔎 Suggested fix
       - name: Lint
         uses: golangci/golangci-lint-action@v6
         with:
-          version: latest
+          version: v1.62

53-57: Minor inconsistency: git default branch config.

The init.defaultBranch is set to master, but the E2E tests explicitly use main branch (via git branch -M main). While this works because the tests override the branch name, consider aligning the config with the actual branch used:

🔎 Suggested fix for consistency
       - name: Configure git
         run: |
           git config --global user.email "ci@test.test"
           git config --global user.name "CI"
-          git config --global init.defaultBranch master
+          git config --global init.defaultBranch main
tests/e2e/e2e_test.go (4)

143-160: Consider preserving file permissions in copyDir.

The helper uses hardcoded permissions (0755 for dirs, 0644 for files). If any fixture files require executable permissions, they'll be lost. For test fixtures this is likely acceptable, but worth noting.

🔎 Optional: Preserve file permissions
 func (s *E2ESuite) copyDir(src, dst string) {
 	entries, err := os.ReadDir(src)
 	s.Require().NoError(err)

 	for _, entry := range entries {
 		srcPath := filepath.Join(src, entry.Name())
 		dstPath := filepath.Join(dst, entry.Name())

 		if entry.IsDir() {
 			s.Require().NoError(os.MkdirAll(dstPath, 0755))
 			s.copyDir(srcPath, dstPath)
 		} else {
+			info, err := entry.Info()
+			s.Require().NoError(err)
 			data, err := os.ReadFile(srcPath)
 			s.Require().NoError(err)
-			s.Require().NoError(os.WriteFile(dstPath, data, 0644))
+			s.Require().NoError(os.WriteFile(dstPath, data, info.Mode()))
 		}
 	}
 }

223-234: Add timeout to HTTP client.

http.Get uses the default client with no timeout. If the service hangs on a request, the individual check could block longer than expected. Consider using a client with a short timeout.

🔎 Suggested fix
 func (s *E2ESuite) checkServiceResponse(url, expected string) bool {
-	resp, err := http.Get(url)
+	client := &http.Client{Timeout: 5 * time.Second}
+	resp, err := client.Get(url)
 	if err != nil {
 		return false
 	}
 	defer resp.Body.Close()
 	body, err := io.ReadAll(resp.Body)
 	if err != nil {
 		return false
 	}
 	return strings.Contains(string(body), expected)
 }

421-521: Test55 and Test57 share significant code duplication.

These tests are nearly identical except for removeVolumeFromDockerCompose() vs removeBuildContextFromDockerCompose(). Consider refactoring to a table-driven test or extracting the common logic.


553-573: Test90_ProjectCleanup has redundant check.

Lines 563-564 and 570-572 perform the same check (verifying project directory doesn't exist). The second check is redundant.

🔎 Suggested fix
 func (s *E2ESuite) Test90_ProjectCleanup() {
 	s.cleanupProject()

 	// Initialize and start project
 	s.devboxRun("init", s.manifestRepo, "--name", "test-app", "--branch", "main")
 	s.devboxRun("up", "--name", "test-app")

 	// Test project destroy
 	s.devboxRun("destroy", "--name", "test-app")

 	_, err := os.Stat(s.projectDir)
 	s.True(os.IsNotExist(err), "Project directory should be removed")

 	// Verify no containers
 	out, _ := exec.Command("docker", "ps", "-q", "--filter", "name=test-app").Output()
 	s.Empty(strings.TrimSpace(string(out)), "No containers should be running")
-
-	// Make sure files were removed
-	_, err = os.Stat(s.projectDir)
-	s.True(os.IsNotExist(err), "Project files should be removed")
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f822770 and f83d7da.

📒 Files selected for processing (17)
  • .github/workflows/ci.yaml (1 hunks)
  • Makefile (1 hunks)
  • tests/e2e/conftest.py (0 hunks)
  • tests/e2e/e2e_test.go (1 hunks)
  • tests/e2e/fixtures/manifest/docker-compose.yml (1 hunks)
  • tests/e2e/helpers.py (0 hunks)
  • tests/e2e/pytest.ini (0 hunks)
  • tests/e2e/requirements.txt (0 hunks)
  • tests/e2e/run_tests.sh (0 hunks)
  • tests/e2e/test_10_init.py (0 hunks)
  • tests/e2e/test_30_info.py (0 hunks)
  • tests/e2e/test_40_project_context.py (0 hunks)
  • tests/e2e/test_50_mount_context.py (0 hunks)
  • tests/e2e/test_55_mount_for_build.py (0 hunks)
  • tests/e2e/test_57_mount_for_volume.py (0 hunks)
  • tests/e2e/test_60_operations.py (0 hunks)
  • tests/e2e/test_90_cleanup.py (0 hunks)
💤 Files with no reviewable changes (13)
  • tests/e2e/test_60_operations.py
  • tests/e2e/conftest.py
  • tests/e2e/run_tests.sh
  • tests/e2e/test_40_project_context.py
  • tests/e2e/pytest.ini
  • tests/e2e/helpers.py
  • tests/e2e/test_30_info.py
  • tests/e2e/test_10_init.py
  • tests/e2e/test_57_mount_for_volume.py
  • tests/e2e/test_90_cleanup.py
  • tests/e2e/requirements.txt
  • tests/e2e/test_55_mount_for_build.py
  • tests/e2e/test_50_mount_context.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: E2E Tests
🔇 Additional comments (7)
tests/e2e/fixtures/manifest/docker-compose.yml (1)

4-4: LGTM!

The branch change to main is consistent with the Go E2E test suite setup that pushes to the main branch.

.github/workflows/ci.yaml (1)

36-60: E2E job structure looks good.

The job properly builds the binary, adds it to PATH, configures git for test repo operations, and runs tests with appropriate timeout.

tests/e2e/e2e_test.go (5)

16-28: Well-designed E2ESuite struct.

The struct captures all necessary state for the test lifecycle. Good separation of concerns with dedicated fields for repos, directories, and fixtures.


34-109: SetupSuite is comprehensive and well-structured.

Good practices observed:

  • Cleanup of leftover temp directories from previous runs
  • Proper git repo initialization with bare repos
  • Clear separation between manifest and source repos

111-132: TearDownSuite handles cleanup properly.

The empty string check on line 116 correctly handles the case where no containers exist.


236-256: Hardcoded YAML snippets are fragile but acceptable for tests.

The string replacement approach for modifying docker-compose.yml relies on exact whitespace matching. Any change to the fixture file's formatting could break these helpers. This is a reasonable tradeoff for E2E test simplicity.


288-313: Good test structure with proper isolation.

Each test starts with cleanupProject() ensuring proper isolation. The numbered naming (Test10_, Test30_, etc.) ensures consistent execution order with testify's alphabetical sorting.

@pilat pilat merged commit c45da7b into main Dec 21, 2025
2 of 3 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Dec 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants