Complete guide to setting up a new Terraform module repository for DTLR using these templates.
# 1. Create new repository
gh repo create dtlr/terraform-<provider>-<name> --private --clone
cd terraform-<provider>-<name>
# 2. Copy templates
cp -r /path/to/terraform-module-templates/* .
cp /path/to/terraform-module-templates/.* . 2>/dev/null || true
# 3. Customize for your module
# Edit main.tf, variables.tf, outputs.tf, README.md
# 4. Set up GitHub secrets
gh secret set MODULE_NAME --body "<your-module-name>"
gh secret set MODULE_PROVIDER --body "<provider-name>"
# 5. Install pre-commit and initialize
pip install pre-commit
pre-commit install
pre-commit install --hook-type commit-msg
# 6. Make first commit
git add .
git commit -m "feat: initial module setup"
git push origin main
# 7. Create first release
git tag v1.0.0
git push origin v1.0.0
gh release create v1.0.0 --title "v1.0.0" --notes "Initial release"Create a new repository following the naming convention:
Format: terraform-<provider>-<name>
Examples:
terraform-cloudflare-worker-resourcesterraform-neon-database-branchterraform-azuread-app-registration
# Using GitHub CLI
gh repo create dtlr/terraform-<provider>-<name> \
--private \
--description "Terraform module for <description>" \
--clone
cd terraform-<provider>-<name>Copy all template files to your new repository:
# Set template directory path
TEMPLATE_DIR="/path/to/repo-ssibility/terraform-module-templates"
# Copy all files
cp -r $TEMPLATE_DIR/* .
# Copy hidden files (dot files)
cp $TEMPLATE_DIR/.terraform-docs.yml .
cp $TEMPLATE_DIR/.pre-commit-config.yaml .
cp $TEMPLATE_DIR/.tflint.hcl .
cp $TEMPLATE_DIR/.releaserc.json .
cp $TEMPLATE_DIR/.gitignore . 2>/dev/null || cat > .gitignore << 'EOF'
# Terraform
.terraform/
.terraform.lock.hcl
*.tfstate
*.tfstate.*
*.tfvars
!*.tfvars.example
crash.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Test artifacts
tests/integration/.terraform/
EOF# main.tf - Your module implementation
# Example structure:
terraform {
required_version = ">= 1.5.0"
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = ">= 4.0"
}
}
}
# Your resources here
resource "cloudflare_kv_namespace" "this" {
for_each = var.kv_namespaces
account_id = var.account_id
title = "${var.environment}-${each.key}"
}# variables.tf - Input variable definitions
variable "account_id" {
description = "The account ID for the provider"
type = string
validation {
condition = length(var.account_id) > 0
error_message = "Account ID must not be empty"
}
}
variable "environment" {
description = "Environment name (e.g., production, staging, development)"
type = string
default = "production"
validation {
condition = can(regex("^(production|staging|development|test)$", var.environment))
error_message = "Environment must be production, staging, development, or test"
}
}# outputs.tf - Output value definitions
output "resource_ids" {
description = "Map of resource names to their IDs"
value = {
for k, v in cloudflare_kv_namespace.this : k => v.id
}
}# versions.tf - Terraform and provider version constraints
terraform {
required_version = ">= 1.5.0"
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = ">= 4.0"
}
}
}Edit README-TEMPLATE.md → README.md:
- Replace
[Provider]and[Name]with your module's provider and name - Update the description
- List actual features
- Add real usage examples
- Update requirements table
- Add provider-specific documentation links
cd examples/basicCreate a working example that demonstrates minimum configuration:
# examples/basic/main.tf
module "example" {
source = "../../"
account_id = var.account_id
environment = "dev"
# Minimal resource configuration
kv_namespaces = {
cache = {}
}
}Test it:
terraform init
terraform validate
terraform plancd examples/advancedCreate a complex example showing production patterns:
# examples/advanced/main.tf
module "example" {
source = "../../"
account_id = var.account_id
environment = "production"
# Complex configuration
kv_namespaces = {
cache = {
# Advanced settings
}
sessions = {
# Advanced settings
}
}
}Set up required secrets for CI/CD:
# Module metadata
gh secret set MODULE_NAME --body "worker-resources"
gh secret set MODULE_PROVIDER --body "cloudflare"
# Provider credentials (for integration tests)
gh secret set CLOUDFLARE_API_TOKEN --body "your-token"
gh secret set CLOUDFLARE_ACCOUNT_ID --body "your-account-id"
# For GitLab registry publishing (optional)
gh secret set GITLAB_TOKEN --body "your-gitlab-token"
gh secret set GITLAB_PROJECT_ID --body "your-project-id"
# For Snyk scanning (optional)
gh secret set SNYK_TOKEN --body "your-snyk-token"Edit .tflint.hcl to uncomment your provider plugin:
# For Cloudflare modules
plugin "terraform" {
enabled = true
preset = "recommended"
}
# No specific Cloudflare plugin, use base rules
# For AWS modules - uncomment:
# plugin "aws" {
# enabled = true
# version = "0.32.0"
# source = "github.com/terraform-linters/tflint-ruleset-aws"
# }
# For Azure modules - uncomment:
# plugin "azurerm" {
# enabled = true
# version = "0.27.0"
# source = "github.com/terraform-linters/tflint-ruleset-azurerm"
# }# Install pre-commit framework
pip install pre-commit
# Install hooks
pre-commit install
pre-commit install --hook-type commit-msg
# Test hooks
pre-commit run --all-filescd tests/integration
# Initialize Go module
go mod init github.com/dtlr/terraform-<provider>-<name>
# Add dependencies
go get github.com/gruntwork-io/terratest/modules/terraform
go get github.com/stretchr/testify/assert
# Create test file (copy from template)
# Edit module_test.go to match your module# Generate terraform-docs
terraform-docs markdown table --output-file README.md --output-mode inject .
# Verify documentation
cat README.mdcat > CHANGELOG.md << 'EOF'
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - $(date +%Y-%m-%d)
### Added
- Initial module release
- Support for <feature 1>
- Support for <feature 2>
- Comprehensive examples (basic and advanced)
- Integration tests with Terratest
- CI/CD with GitHub Actions
### Documentation
- Complete README with usage examples
- Migration guide from monorepo
- Architecture decisions
[1.0.0]: https://github.com/dtlr/terraform-<provider>-<name>/releases/tag/v1.0.0
EOFcat > LICENSE << 'EOF'
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
[Full Apache 2.0 license text]
EOF
# Or use GitHub CLI to add a license
gh repo edit --add-license apache-2.0# Add all files
git add .
# Commit with conventional commit format
git commit -m "feat: initial module release
- Add support for <resource type>
- Include basic and advanced examples
- Set up CI/CD pipelines
- Add comprehensive documentation
BREAKING CHANGE: Initial release"
# Push to GitHub
git push origin main
# Create first release
git tag v1.0.0
git push origin v1.0.0
# Create GitHub release
gh release create v1.0.0 \
--title "v1.0.0 - Initial Release" \
--notes "Initial release of terraform-<provider>-<name> module
## Features
- Resource type 1 support
- Resource type 2 support
- Idempotent operations
- Comprehensive validation
## Usage
\`\`\`hcl
module \"example\" {
source = \"github.com/dtlr/terraform-<provider>-<name>?ref=v1.0.0\"
version = \"~> 1.0\"
# Configuration
}
\`\`\`
## Documentation
- [README](https://github.com/dtlr/terraform-<provider>-<name>#readme)
- [Examples](https://github.com/dtlr/terraform-<provider>-<name>/tree/main/examples)
- [Migration Guide](https://github.com/dtlr/terraform-<provider>-<name>/blob/main/docs/MIGRATION-GUIDE.md)"-
Check GitHub Actions:
- Go to
https://github.com/dtlr/terraform-<provider>-<name>/actions - Verify CI workflow passes
- Verify security scans complete
- Check release workflow created release
- Go to
-
Review Security Tab:
- Check for any security findings
- Review tfsec, Checkov, and Trivy results
-
Test Module Consumption:
# In a test directory cat > main.tf << 'EOF' module "test" { source = "github.com/dtlr/terraform-<provider>-<name>?ref=v1.0.0" # ... } EOF terraform init terraform validate
Add your module to the central catalog:
# In dtlr/terraform-modules repository
cat >> README.md << EOF
### <Provider>
- [terraform-<provider>-<name>](https://github.com/dtlr/terraform-<provider>-<name>) - Description
EOFgh repo edit dtlr/terraform-<provider>-<name> \
--add-topic terraform \
--add-topic terraform-module \
--add-topic <provider> \
--add-topic dtlr-infrastructuregh api repos/dtlr/terraform-<provider>-<name>/branches/main/protection \
-X PUT \
-f required_status_checks[strict]=true \
-f required_status_checks[contexts][]=validate \
-f required_status_checks[contexts][]=lint \
-f required_status_checks[contexts][]=security \
-f required_pull_request_reviews[required_approving_review_count]=1 \
-f required_pull_request_reviews[dismiss_stale_reviews]=true \
-f enforce_admins=trueCreate .github/dependabot.yml:
version: 2
updates:
- package-ecosystem: "terraform"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- "terraform"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
- "github-actions"Create .github/CODEOWNERS:
# Terraform module owners
* @dtlr/infrastructure-team
*.tf @dtlr/infrastructure-team
# Examples
/examples/ @dtlr/infrastructure-team
# CI/CD
/.github/ @dtlr/platform-team
# Update hooks
pre-commit autoupdate
# Run specific hook
pre-commit run terraform_fmt --all-filesCheck:
- Secrets are configured correctly
- Workflow syntax is valid:
actionlint .github/workflows/*.yml - Terraform syntax:
terraform validate
Ensure:
- Repository is accessible (check permissions)
- Git authentication is configured (SSH or HTTPS)
- Tag exists:
git tag -l
- Migrate existing module - Follow MIGRATION-GUIDE.md
- Write tests - Add integration tests in
tests/integration/ - Document - Expand README with usage patterns
- Iterate - Release v1.1, v1.2 as features are added
- Promote - Share with team, update internal docs
Last Updated: 2025-11-14 Maintainer: DTLR Engineering Team