Terraform Module Releaser
A GitHub Action that automates versioning, releasing, and documentation for Terraform modules kept in a monorepo: per-module tags, releases, and wiki docs, cut automatically on every pull request.
GitHub repo sprawl
The same pattern appears inside nearly every large GitHub organization: infrastructure teams publish each Terraform module from its own repository, because that is the only way to give each module its own version history. The modules are small. The overhead around them is not.
An enterprise repository is never just code. Before the first module ships, the repo has to carry the GitHub-specific plumbing that makes it fit for production, and every piece of that plumbing is defined per repository:
- CI workflows
- compliance & security scanning
- pull request templates
- CODEOWNERS
- branch protection rules
- required status checks
- secrets & runner config
- Dependabot policy
Now run the thought experiment. At five module repositories the duplication is an annoyance. At one hundred, it is a standing tax: a hundred copies of every workflow to patch when a scanner changes, a hundred branch-protection policies to audit, a hundred places for a compliance update to land or quietly miss. Platform teams end up writing automation whose only job is keeping repository scaffolding in sync, which is effort spent on plumbing instead of infrastructure.
The Terraform monorepo answer
The structural fix is to keep every Terraform module in one repository. All of the GitHub-specific machinery is defined once: one set of workflows, one pull request template, one CODEOWNERS file, one branch-protection policy, one surface for compliance to review. The modules themselves are just subdirectories, and the hundredth module costs what the fifth did: a new folder and a pull request.
Teams that try it usually hit the same wall, and it is the reason the polyrepo pattern survives: release granularity. Git tags and GitHub releases are repository-wide, not per-directory, while Terraform consumers pin modules by tag. A monorepo with a single version stream either lies about what changed or forces every module to move in lockstep. What was missing was never the monorepo — it was the release pipeline that lets one repository behave like a hundred small ones.
What the GitHub Action automates
Terraform Module Releaser is that pipeline, packaged as a single GitHub Action and driven entirely by pull requests. When a pull request opens or updates, the Action detects exactly which modules changed and computes each one's next semantic version from conventional commits: breaking changes bump major, features bump minor, fixes and chores bump patch. It then comments the release plan on the pull request, so versioning becomes part of code review rather than an afterthought.
When the pull request merges, it cuts the releases. Each changed module receives its own Git tag and GitHub release, scoped to just that module's directory contents, so consumers fetch a small, precise artifact instead of the whole repository and Terraform's module retrieval stays fast. The Action also generates a per-module wiki with usage examples, terraform-docs input and output tables, and a full changelog, and it removes tags and releases for modules that have been deleted, so the repository stays clean as it evolves.
The release pipeline
on: pull_request
- detect which modules changed in the monorepo
- calculate each module's semver bump from conventional commits
- comment the release plan on the pull request
- tag + release on merge, scoped to each module's directory
- generate per-module wiki docs + changelog
- clean up tags for deleted modules
Setup is one workflow file, taken directly from the project README:
name: Terraform Module Releaser
on:
pull_request:
types: [opened, reopened, synchronize, closed] # Closed required
branches:
- main
permissions:
contents: write # Required to push tags, create releases, and push changes to the wiki
pull-requests: write # Required to comment on pull request
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Terraform Module Releaser
uses: techpivot/terraform-module-releaser@v2 The defaults are deliberate: zero configuration produces a working release pipeline, and every behavior is overridable when a team's conventions require it, from the semver keywords and first-tag format to wiki layout, tag naming, and cleanup of legacy tags.
GitHub-native, built for the enterprise
The Action is 100% GitHub-native. There is no external service, no registry to operate, no storage bucket, and no credential that leaves your organization: it reads pull request data through the GitHub API and writes tags, releases, and wiki pages back through the same API. For regulated environments that is the difference between adopting a tool and onboarding a vendor; the entire release path stays inside the platform you already govern and audit.
It also runs where enterprise GitHub actually lives. The Action detects GitHub Enterprise Server automatically and adjusts its API endpoints, so the same workflow file works on GitHub.com and behind the firewall. It is MIT-licensed, distributed through the GitHub Marketplace, and has shipped steadily since 2024: 19 releases, v2.2.0 current as of August 7, 2026, with dozens of dependent repositories building on it in the open.
Secure by design
- one action
A single MIT-licensed Action with auditable source. One dependency to review, not a toolchain.
- your runners
Runs on the infrastructure you specify: GitHub-hosted, self-hosted, or private GitHub Actions runners.
- your boundary
No external services. No credentials leave the organization. Every call is the GitHub API you already govern.
This work grew out of an approach first sketched publicly in an early community post on GitHub-powered Terraform monorepos; the Action turns that idea into a maintained, production-grade tool.