A production-ready template for creating Terraform modules following the one module per repository best practice, with built-in CI/CD, security scanning, testing, documentation generation, and publishing to public registries.
- One Module Per Repo — Module lives at the root; no nested
modules/directory - Registry Publishing — Auto-publish to Terraform Registry, Artifactory, or GitLab on release
- Native Terraform Testing —
terraform testwith mock providers (no external tools) - Security Scanning — Trivy IaC scanning for HIGH/CRITICAL vulnerabilities
- Linting — TFLint with AWS ruleset (preset "all")
- Auto Documentation — terraform-docs generates README sections on every commit
- GitHub Actions CI/CD — Workflows for the full module lifecycle
- Pre-Commit Hooks — Format, validate, lint, docs, and security on every commit
- Conventional Commits — Enforced commit message format
- Semantic Versioning — Automated version management and releases
- DevContainer — VS Code remote development ready
# Create repo from template (name MUST follow: terraform-<PROVIDER>-<NAME>)
gh repo create PlatformStackPulse/terraform-aws-my-module --template PlatformStackPulse/Terraform-module-base-template --public
# Clone
git clone [email protected]:PlatformStackPulse/terraform-aws-my-module.git
cd terraform-aws-my-module
# Install tools and hooks
make dev-setup
make hooks
# Run all checks
make all- Replace the example S3 resources in
main.tfwith your actual resources - Update
variables.tf,outputs.tf, andversions.tf - Write tests in
tests/unit/main_test.tftest.hcl - Update
examples/complete/with real usage - Update
.github/CODEOWNERS - Update this
README.md
See TEMPLATE_GUIDE.md for detailed instructions.
module "this" {
source = "github.com/PlatformStackPulse/terraform-aws-my-module?ref=v1.0.0"
name = "my-resource"
environment = "dev"
namespace = "myorg"
tags = {
Project = "example"
Owner = "platform-engineering"
}
}module "this" {
source = "PlatformStackPulse/my-module/aws"
version = "~> 1.0"
name = "my-resource"
environment = "dev"
namespace = "myorg"
tags = {
Project = "example"
Owner = "platform-engineering"
}
}├── main.tf # Primary resource definitions
├── variables.tf # Input variables
├── outputs.tf # Output values
├── versions.tf # Terraform and provider version constraints
├── locals.tf # Local values and naming conventions
├── data.tf # Data sources
├── examples/ # Usage examples for consumers
│ └── complete/ # Full-featured example
├── tests/ # Terraform native tests
│ ├── unit/ # Unit tests with mock providers
│ └── integration/ # Integration tests (real AWS)
├── .github/ # GitHub Actions + templates
├── scripts/ # Automation scripts
└── Makefile # Build automation
make help Show all targets
make init Initialize the module
make fmt Format all Terraform files
make fmt-check Check formatting (CI mode)
make validate Validate the module
make lint Run TFLint
make test Run all tests
make test-unit Run unit tests only
make test-integration Run integration tests
make security Run Trivy security scan
make docs Generate terraform-docs
make clean Remove .terraform dirs
make all Run all checks
make dev-setup Install development tools
make hooks Install pre-commit hooks
make changelog Regenerate CHANGELOG.md
make version Show current version
make release Create version tag (BUMP=patch|minor|major)
The Terraform Registry automatically publishes new versions when you create a GitHub Release:
- Name your repo following the convention:
terraform-<PROVIDER>-<NAME>(e.g.,terraform-aws-vpc) - Connect at registry.terraform.io/github/create
- Tag and release — every semver tag (
v1.0.0) is auto-published
- Connect your VCS provider in TFC/TFE settings
- Create a Module in the private registry pointing to this repo
- Semver tags trigger automatic version publication
Set these repository variables/secrets in GitHub:
ARTIFACTORY_ENABLED=true(variable)ARTIFACTORY_URL— e.g.,https://myorg.jfrog.io/artifactory(variable)ARTIFACTORY_REPO— e.g.,terraform-modules(variable)ARTIFACTORY_TOKEN(secret)
Uncomment the publish-gitlab job in .github/workflows/release.yml and set:
GITLAB_TOKEN(secret)GITLAB_PROJECT_ID(variable)
| Workflow | Trigger | Purpose |
|---|---|---|
ci.yml |
Push/PR to main | Format, validate, lint, test, security |
release.yml |
Tag v*.. | Create GitHub Release + publish to registries |
codeql.yml |
Weekly + push main | SAST security analysis |
dependencies.yml |
Weekly | Check for provider updates |
changelog.yml |
Push main | Auto-update CHANGELOG.md |
version-bump.yml |
Manual | Bump patch/minor/major version |
Installed via make hooks. Runs on every commit:
terraform_fmt— Format checkterraform_validate— Syntax validationterraform_tflint— Linting with AWS rulesterraform_docs— Auto-generate documentationterraform_trivy— Security scanning (HIGH/CRITICAL)gitlint— Conventional commit message validation
| Name | Version |
|---|---|
| terraform | >= 1.9.0 |
| aws | >= 5.0.0 |
| Name | Version |
|---|---|
| aws | >= 5.0.0 |
No modules.
| Name | Type |
|---|---|
| aws_s3_bucket.this | resource |
| aws_s3_bucket_public_access_block.this | resource |
| aws_s3_bucket_server_side_encryption_configuration.this | resource |
| aws_s3_bucket_versioning.this | resource |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| environment | Environment name (e.g., dev, staging, prod). | string |
n/a | yes |
| name | Name of the resource. Used in naming convention. | string |
n/a | yes |
| enabled | Set to false to prevent the module from creating any resources. | bool |
true |
no |
| force_destroy | Allow destruction of non-empty S3 bucket. | bool |
false |
no |
| kms_key_arn | ARN of the KMS key for server-side encryption. If null, AES256 is used. | string |
null |
no |
| namespace | Namespace for resource naming (e.g., org name, team). | string |
"" |
no |
| tags | Additional tags to apply to all resources. | map(string) |
{} |
no |
| versioning_enabled | Enable S3 bucket versioning. | bool |
true |
no |
| Name | Description |
|---|---|
| bucket_arn | The ARN of the S3 bucket. |
| bucket_domain_name | The bucket domain name. |
| bucket_id | The ID of the S3 bucket. |
| enabled | Whether the module is enabled. |
| Document | Description |
|---|---|
| docs/TERRAFORM_FLAGS.md | Terraform CLI flags reference (-refresh, -upgrade, etc.) |
| docs/TFENV.md | tfenv version manager guide |
| docs/MAKEFILE_ENV.md | Makefile targets and .env configuration |
| TEMPLATE_GUIDE.md | Step-by-step guide to customise this template |
| WORKFLOW.md | Branching strategy and CI/CD pipeline |
| CONTRIBUTING.md | Development workflow and guidelines |
See CONTRIBUTING.md for development workflow and guidelines.
See SECURITY.md for vulnerability reporting.