Skip to content

Latest commit

 

History

History
597 lines (451 loc) · 12.3 KB

File metadata and controls

597 lines (451 loc) · 12.3 KB

Terraform Module Repository Setup Guide

Complete guide to setting up a new Terraform module repository for DTLR using these templates.

Quick Start

# 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"

Detailed Setup Instructions

Step 1: Repository Creation

Create a new repository following the naming convention:

Format: terraform-<provider>-<name>

Examples:

  • terraform-cloudflare-worker-resources
  • terraform-neon-database-branch
  • terraform-azuread-app-registration
# Using GitHub CLI
gh repo create dtlr/terraform-<provider>-<name> \
  --private \
  --description "Terraform module for <description>" \
  --clone

cd terraform-<provider>-<name>

Step 2: Copy Template Files

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

Step 3: Customize Module Files

Create main.tf

# 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}"
}

Create variables.tf

# 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"
  }
}

Create outputs.tf

# 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
  }
}

Create versions.tf

# versions.tf - Terraform and provider version constraints

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = ">= 4.0"
    }
  }
}

Step 4: Customize README

Edit README-TEMPLATE.mdREADME.md:

  1. Replace [Provider] and [Name] with your module's provider and name
  2. Update the description
  3. List actual features
  4. Add real usage examples
  5. Update requirements table
  6. Add provider-specific documentation links

Step 5: Create Examples

Basic Example

cd examples/basic

Create 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 plan

Advanced Example

cd examples/advanced

Create 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
    }
  }
}

Step 6: Configure GitHub Secrets

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"

Step 7: Customize TFLint Configuration

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"
# }

Step 8: Set Up Pre-Commit Hooks

# 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-files

Step 9: Create Integration Tests

cd 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

Step 10: Generate Documentation

# Generate terraform-docs
terraform-docs markdown table --output-file README.md --output-mode inject .

# Verify documentation
cat README.md

Step 11: Create CHANGELOG

cat > 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
EOF

Step 12: Add LICENSE

cat > 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

Step 13: Initial Commit and Release

# 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)"

Step 14: Verify CI/CD

  1. 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
  2. Review Security Tab:

    • Check for any security findings
    • Review tfsec, Checkov, and Trivy results
  3. 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

Post-Setup Tasks

1. Update Module Catalog

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
EOF

2. Configure GitHub Topics

gh repo edit dtlr/terraform-<provider>-<name> \
  --add-topic terraform \
  --add-topic terraform-module \
  --add-topic <provider> \
  --add-topic dtlr-infrastructure

3. Set Up Branch Protection

gh 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=true

4. Enable Dependabot

Create .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"

5. Configure Code Owners

Create .github/CODEOWNERS:

# Terraform module owners
*       @dtlr/infrastructure-team
*.tf    @dtlr/infrastructure-team

# Examples
/examples/  @dtlr/infrastructure-team

# CI/CD
/.github/   @dtlr/platform-team

Troubleshooting

Issue: Pre-commit hooks failing

# Update hooks
pre-commit autoupdate

# Run specific hook
pre-commit run terraform_fmt --all-files

Issue: GitHub Actions failing

Check:

  1. Secrets are configured correctly
  2. Workflow syntax is valid: actionlint .github/workflows/*.yml
  3. Terraform syntax: terraform validate

Issue: Module not found during terraform init

Ensure:

  1. Repository is accessible (check permissions)
  2. Git authentication is configured (SSH or HTTPS)
  3. Tag exists: git tag -l

Next Steps

  1. Migrate existing module - Follow MIGRATION-GUIDE.md
  2. Write tests - Add integration tests in tests/integration/
  3. Document - Expand README with usage patterns
  4. Iterate - Release v1.1, v1.2 as features are added
  5. Promote - Share with team, update internal docs

Resources


Last Updated: 2025-11-14 Maintainer: DTLR Engineering Team