Skip to content

Conversation

@james00012
Copy link
Contributor

@james00012 james00012 commented Nov 25, 2025

Summary

This PR converts Terratest from a monolithic Go module into 28 independent submodules, allowing users to import only the modules they need without pulling in unnecessary dependencies.

Changes

  • Created 28 independent Go modules under modules/ and internal/
  • Set up Go workspace (go.work) for local development
  • Added GitHub Action to automatically tag submodules on release

Backward Compatibility Testing

Extensive testing was performed using a fork repository (james00012/terratest-modularization-test) to validate backward compatibility:

1. Consumer Simulation Test

Created an external project importing 13+ modules simultaneously:

  • modules/terraform, modules/terragrunt, modules/aws, modules/k8s, modules/docker, modules/helm, modules/collections, modules/random, modules/logger, modules/shell, modules/retry, modules/files, modules/environment

Result: PASS - No ambiguous import errors

2. Backward Compatibility Tests

Validated that existing user code works without modification:

Module Test Result
terraform Existing terraform.Options{}, terraform.Init, terraform.Apply PASS
aws Existing aws.GetRandomRegion, aws.CreateS3Bucket PASS
k8s Existing k8s.KubectlOptions{}, k8s.GetPod PASS
docker Existing docker.Options{}, docker.Build, docker.Run PASS
helm Existing helm.Options{}, helm.Install PASS

Migration for Users

No changes required. Existing import paths continue to work:

import (
    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/gruntwork-io/terratest/modules/aws"
)

Release Process

A new GitHub Action (.github/workflows/release-modules.yml) handles submodule tagging:

How It Works

  1. Create a GitHub Release (e.g., v0.55.0) through the GitHub UI or API
  2. Workflow automatically triggers when the release is published
  3. Auto-discovers all modules by finding go.mod files (excludes root and test directories)
  4. Creates tags for all submodules:
    • modules/terraform/v0.55.0
    • modules/aws/v0.55.0
    • modules/k8s/v0.55.0
    • ... (all modules)
  5. Pushes tags to the repository

Setup Required

Add GH_TOKEN as a repository secret:

  1. Go to SettingsSecrets and variablesActions
  2. Create a new secret named GH_TOKEN
  3. Use a Personal Access Token with contents: write permission

Manual Trigger

The workflow can also be triggered manually:

  1. Go to ActionsRelease Module Tags
  2. Click Run workflow
  3. Enter the version (e.g., 0.55.0)

Auto-Discovery

The workflow automatically discovers modules - no need to update the workflow when adding new modules:

find . -name "go.mod" -not -path "./go.mod" -not -path "./test/*"

Why Submodule Tags?

Go modules require tags in the format <path>/v<version> for submodules. Without these tags, users cannot pin specific versions:

go get github.com/gruntwork-io/terratest/modules/[email protected]

Tested On Fork

The workflow was tested on james00012/terratest-modularization-test:

  • Successfully created tags for v0.55.0
  • All 28 submodule tags created and pushed correctly via auto-discovery

Benefits

  • Reduced dependencies: Import only what you need
  • Faster builds: Smaller dependency trees
  • Future-proof: New modules automatically tagged without workflow changes

Test plan

  • Consumer simulation test passes (no ambiguous imports)
  • Backward compatibility tests pass (existing code works unchanged)
  • CI pipeline passes
  • Release workflow tested on fork (v0.55.0)
  • Auto-discovery tested (28 modules found)
  • Add GH_TOKEN secret after merge
  • Manual verification of release workflow on first production release

@james00012 james00012 force-pushed the feature/complete-modularization branch 4 times, most recently from d67bf0c to d38cd1e Compare November 25, 2025 05:12
Implements complete modularization with no root go.mod, eliminating
dependency bloat and fixing ambiguous import errors.

Fixes gruntwork-io#1613

## Changes

- Remove root go.mod
- Add go.work workspace for local development
- Create go.mod for each of 27 modules + internal/lib
- Comprehensive test suite in test/modularization/
- Documentation in MODULARIZATION.md

## Impact

**Before:** Importing any module pulls entire ~50MB library with all cloud SDKs

**After:** Import only what you need (~5MB for terraform module)

## Benefits

- **No ambiguous imports** - Each package has exactly one source
- **Reduced dependencies** - Import only needed modules
- **Independent versioning** - Each module versions separately
- **Cleaner dependency graphs** - No hidden transitive deps from root

## Usage

```go
import "github.com/gruntwork-io/terratest/modules/terraform"
```

```go
require github.com/gruntwork-io/terratest/modules/terraform v0.1.0
```

No replace directives needed - Go fetches from GitHub tags automatically.

## Testing

```bash
cd test/modularization
go test -v ./...
```

Tests validate:
- Dependency isolation
- No ambiguous imports
- All modules build independently
- Workspace builds successfully

## Migration

No breaking changes - import paths stay the same. Consumers automatically
pull only needed modules instead of everything.
@james00012 james00012 force-pushed the feature/complete-modularization branch from d38cd1e to e7959ae Compare November 25, 2025 05:21
james00012 and others added 4 commits November 27, 2025 16:02
When a GitHub release is published, this workflow automatically creates
tags for all 27 submodules in the format `modules/<name>/v<version>`.

This enables Go's module system to resolve submodule versions correctly,
allowing users to import specific modules:
  go get github.com/gruntwork-io/terratest/modules/[email protected]

Features:
- Triggers automatically on release publish
- Can also be triggered manually for testing/re-running
- Skips tags that already exist
- Validates version format (X.Y.Z or X.Y.Z-suffix)
Add permissions.contents: write and explicit token to allow
the workflow to push tags to the repository.
Change from GITHUB_TOKEN to GH_TOKEN for pushing submodule tags.
@james00012 james00012 force-pushed the feature/complete-modularization branch from 29bbfbf to f0363f6 Compare November 28, 2025 01:55
Instead of hardcoding module list, dynamically find all go.mod files.
This way new modules are automatically tagged without workflow changes.

Excludes:
- Root go.mod
- Test directories (test/*)
Update all internal module dependencies to v0.55.0 to match the
upcoming release version.
@james00012 james00012 marked this pull request as ready for review December 1, 2025 14:12
@james00012
Copy link
Contributor Author

Closing this PR from fork. Will reopen from the main repository so CircleCI can run properly.

@james00012 james00012 closed this Dec 1, 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.

1 participant