{"id":17489338,"url":"https://github.com/igorbrites/terraform-modules","last_synced_at":"2025-06-27T00:08:54.755Z","repository":{"id":77720576,"uuid":"477753438","full_name":"igorbrites/terraform-modules","owner":"igorbrites","description":"Example of a monorepo with terraform Modules deployed by Lerna","archived":false,"fork":false,"pushed_at":"2022-05-25T13:38:23.000Z","size":224,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T16:17:17.394Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igorbrites.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-04T15:07:35.000Z","updated_at":"2024-05-04T20:31:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"ded303d5-ee04-4f74-8ca4-d5c8111f4813","html_url":"https://github.com/igorbrites/terraform-modules","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/igorbrites/terraform-modules","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorbrites%2Fterraform-modules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorbrites%2Fterraform-modules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorbrites%2Fterraform-modules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorbrites%2Fterraform-modules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igorbrites","download_url":"https://codeload.github.com/igorbrites/terraform-modules/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorbrites%2Fterraform-modules/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262164571,"owners_count":23268782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-19T05:24:35.486Z","updated_at":"2025-06-27T00:08:54.711Z","avatar_url":"https://github.com/igorbrites.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terraform Modules\n\nThis module complements the ideas of the article:\n[How to use Lerna in a monorepo to deploy Terraform modules](soon).\n\nMonorepo with all our Terraform modules, with specific versioning to everyone of\nthem. The modules stay in our [Terraform Cloud private repository](https://app.terraform.io/app/igorbrites/registry/private/modules).\n\n## Modules\n\nAll modules stays in [`modules`](modules) folder, separated by its main\nprovider. E.g.:\n\n```bash\n└── modules\n    ├── aws\n    │   └── rds\n    │       ├── CHANGELOG.md\n    │       ├── LICENSE\n    │       ├── README.md\n    │       ├── main.tf\n    │       ├── outputs.tf\n    │       ├── package.json\n    │       └── variables.tf\n    └── common\n        └── labels\n            ├── CHANGELOG.md\n            ├── LICENSE\n            ├── README.md\n            ├── main.tf\n            ├── outputs.tf\n            ├── package.json\n            └── variables.tf\n```\n\nAs you can see, all modules follows this format:\n\n- `main.tf`: Main file with the principal codes. If the module does a lot of\n  things, is a good idea to split in different files, but you can put main calls\n  here;\n- `outputs.tf` and `variables.tf`: The files to store input and output variables.\n  You must leave these files in the folder, even if they are empty (more on this\n  later);\n- `README.md`: Here you document everything that the module does, with the\n  objective of it, examples on how to use the module, etc. Some info will be added\n  by [`terraform-docs`](https://terraform-docs.io/) during pipeline (variables,\n  outputs, providers...);\n- `LICENSE`: The module's license. It will be `Proprietary` in most cases, but\n  the file is required by Terraform Cloud;\n- `package.json`: Here is how we will controll each version of each module.\n\nThese files are required by Terraform Cloud to recognize the module and show its\nversions.\n\n## Contributing\n\n### Commits\n\nTo make versioning of the modules, we will use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).\nIf you are not familiarized, the commits must look like this:\n\n```bash\ngit commit -m \"chore(my-module): explanation of my commit\"\n```\n\nIn this way, depending of commits, we now what will be the next version:\n\n- `fix:` commits creates a new `PATCH` version;\n- `feat:` commits creates a new `MINOR` version;\n  - There is other commit types, like `build:`, `chore:`, `ci:`, `docs:`, `style:`,\n    `refactor:`, `perf:`, `test:`, but they will behave as `feat:`;\n- If your modifications breaks the behaviour of the module, you must do a commit\n  with a `!` mark after the type (or after the scope), and add a description of\n  the breaking change two lines bellow in commit, like this:\n\n  ```bash\n  git commit -m \"refactor(my-module)!: refactoring the entire module\n\n  BREAKING CHANGE: this module does not support Terraform prior to 1.x anymore.\"\n  ```\n\n  In this way, it creates a new `MAJOR` version.\n\nSo, the first step after cloning this repo is running `npm install`.\n\n_\"But wait\"_ I hear you say, _\"this is a Terraform repo, why should I run `npm install`?\"_\n\nTo ensure all commits will follow the rules above, we use [Husky Hooks](https://typicode.github.io/husky/#/)\nand [commitlint](https://github.com/conventional-changelog/commitlint) during\ncommit. You can see these scripts in [.husky](.husky) folder. And `npm install`\ninstalls the hooks in your local environment.\n\n### Creating a new module\n\nYou can run `.scripts/new-module.sh`:\n\n![Creating Module, created using asciinema](.docs/create-module.svg)\n\n### Tools\n\nThis repo requires Terraform 1.x or later. If you don't want to download it or\nany other tool used here, you can use [ASDF](https://asdf-vm.com/). It manages\nversions of different tools (like nodejs, golang, kubectl...), and you only need\nto run `.scripts/asdf.sh`, it will install ASDF and the tools listed in the\n[`.tool-versions`](.tool-versions) file.\n\n## CI/CD\n\nHere we use [Jenkins](https://www.jenkins.io/) as our CI/CD tool, and you can\ncheck all pipeline at [`Jenkinsfile`](./Jenkinsfile) file. But the flow is this:\n\n| ![Terraform modules pipeline flow](.docs/terraform-flow.svg) |\n|:--:|\n| _All green boxes are commands executed for each module_ |\n\n- You open a PR with your modifications;\n- Jenkins executes `Validation` and `Terraform Docs`;\n  - The first runs a series of validations:\n    - We use [GitHub's super-linter](https://github.com/github/super-linter),\n      which lints everything in the repo: Terraform, Shell scripts, JSON, YAML, etc;\n    - Then we run `terraform validate` on each modified module.\n  - The other runs [`terraform-docs`](https://github.com/terraform-docs/gh-actions)\n    on each modified module, injecting its output on `README.md` and commit this\n    modification.\n    - To `terraform-docs` work propperly, you need to add some annotations to\n      `README.md`: `\u003c!-- BEGIN_TF_DOCS --\u003e` and `\u003c!-- END_TF_DOCS --\u003e`. So in\n      Jenkins, `terraform-docs` will generate module's docs and insert between\n      these annotations. You can add any information before and after them, but\n      anything mannualy wrote between them will be overwritten.\n\nAfter merging the PR, Jenkins creates the versions of each modified module.\nTo achive this, we use [Lerna](https://lerna.js.org/), a tool for managing\nmonorepos with multiple packages. It is used mainly to deal with NodeJS packages,\nbut the only restriction to Lerna identify a package (module) is to have a `package.json`\ninside the package. So, it can see all modifications on that module, and create\nversions based on these modifications. Then it creates a tag called like\n`module@0.1.2`, puts this version inside `package.json`, creates a `CHANGELOG.md`\nof the module, and pushes everything back to GitHub.\n\nThen, after each module has its version, we use\n[Terraform Cloud's API](https://www.terraform.io/docs/cloud/api/modules.html) to\npush the new module there. In TF Cloud, the module's URL is something like this:\n\n```bash\nhttps://app.terraform.io/app/igorbrites/registry/modules/private/igorbrites/module-name/provider/version\n\n# E.g.: https://app.terraform.io/app/igorbrites/registry/modules/private/igorbrites/labels/commons/2.1.0\n```\n\n## Modules usage\n\nE.g.:\n\n```hcl\nmodule \"labels\" {\n  source  = \"app.terraform.io/igorbrites/labels/common\"\n  version = \"2.2.0\"\n  # insert required variables here\n}\n```\n\nAnd this is how it looks on Terraform Registry:\n\n![](https://user-images.githubusercontent.com/1479917/161577057-20b473a9-6915-43a4-9359-8d5066ea2b11.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorbrites%2Fterraform-modules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figorbrites%2Fterraform-modules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorbrites%2Fterraform-modules/lists"}