{"id":13505873,"url":"https://github.com/tfmake/tfmake","last_synced_at":"2026-01-12T00:56:01.375Z","repository":{"id":142998574,"uuid":"607351590","full_name":"tfmake/tfmake","owner":"tfmake","description":"Automating Terraform with the power of make.","archived":false,"fork":false,"pushed_at":"2025-02-22T21:59:02.000Z","size":100,"stargazers_count":23,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-22T22:26:21.483Z","etag":null,"topics":["github-actions","make","terraform"],"latest_commit_sha":null,"homepage":"","language":"Shell","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/tfmake.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":"2023-02-27T20:13:56.000Z","updated_at":"2025-02-22T21:58:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"c3ccb084-7509-462c-8b78-2e738a860de4","html_url":"https://github.com/tfmake/tfmake","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfmake%2Ftfmake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfmake%2Ftfmake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfmake%2Ftfmake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfmake%2Ftfmake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tfmake","download_url":"https://codeload.github.com/tfmake/tfmake/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246262490,"owners_count":20749170,"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":["github-actions","make","terraform"],"created_at":"2024-08-01T00:01:15.953Z","updated_at":"2026-01-12T00:56:01.367Z","avatar_url":"https://github.com/tfmake.png","language":"Shell","readme":"# tfmake\n\n**tfmake** is a tool for automating Terraform with the power of make. It is designed for projects with multiple modules; particularly when dependencies among them are present and an ordered execution is required.\n\n## Requirements\n\n- bash 4+\n- yq\n- make\n\n## Limitations\n\n- To ensure an ordered execution, all dependencies between modules MUST be explicitly declared.\n- A module path SHOULD NOT contain spaces; e.g. use `sample_module` instead of `sample module`.\n\n## Installation\n\n### Git\n\n```bash\ngit clone https://github.com/tfmake/tfmake.git\nsudo cp -r tfmake/usr/local/* /usr/local/\nsudo chmod +x /usr/local/bin/tfmake\n```\n\n## Usage\n\n```\nUsage:\n  tfmake \u003ccommand\u003e [options]\n\nCore Commands:\n  context           Define the execution context: validate, plan, apply, or destroy.\n  init              Initialize the data directory for Terraform execution.\n  generate          Create a Makefile to orchestrate the Terraform execution.\n  run               Run the generated Makefile for Terraform execution.\n\nOther Commands:\n  cleanup           Cleanup the data directory.\n  config            Configure tfmake settings.\n  graph             Visualize Terraform modules and their dependencies.\n  output            Display output values from a Terraform module.\n  summary           Generate a Markdown summary from Terraform execution logs.\n  touch             Mark modified files to trigger necessary updates.\n\nShortcut Commands:\n  validate          Execute core commands using the \"validate\" context.\n  plan              Execute core commands using the \"plan\" context.\n  apply             Execute core commands using the \"apply\" context.\n  destroy           Execute core commands using the \"destroy\" context.\n\nGitHub Commands:\n  gh-pr-comment     Post a comment on a GitHub pull request.\n  gh-step-summary   Append content to GitHub Step Summary.\n\nGlobal Options:\n  -h, --help, help  Display this help message and exit.\n  -v, --version     Alias for the \"version\" command.\n```\n\n## How tfmake works\n\n### The .tfmake file\n\n**tfmake** is based on the _explicit declaration_ of dependencies between modules. In a Terraform project, this could be inferred from the usage of `terraform_remote_state` data resource; although implicit dependencies cases could exist.\n\nThe syntax for the `.tfmake` file is as follow:\n\n```YAML\ndependencies: [\u003cmodule\u003e, \u003cmodule\u003e, ..., \u003cmodule\u003e]\n```\n\ne.g. if module C depends on A and B, the following declaration is needed:\n\n```YAML\ndependencies:\n  - A\n  - B\n```\n\n\u003e All dependencies MUST be declared. Omitting some of them based on transitivity is discouraged.\n\n### Core commands\n\nSimilar to Terraform, **tfmake** is composed of multiple commands, each one playing an important role in a predefined sequence.\n\nThe core sequence is made up of four commands, as illustrated in the next diagram.\n\n```mermaid\nflowchart LR\n\nclassDef primary fill:#a3cfbb,stroke:#a3cfbb,color:#136c44;\nclassDef secondary fill:#fee69b,stroke:#fee69b,color:#987405;\n\ncontext(\"tfmake context\")\ninit(\"tfmake init\")\ngenerate(\"tfmake generate\")\nrun(\"tfmake run\")\n\ncontext --\u003e init --\u003e generate --\u003e run\n\ncontext:::primary\ninit:::primary\ngenerate:::primary\nrun:::primary\n```\n\n#### tfmake context\n\nAllows to define the Terraform command to execute: `validate`, `plan`, `apply`, or `destroy`.\n\n```\ntfmake context plan\n```\n\n#### tfmake init\n\nAs the name suggests, this command deals with the initialization process, used to discover the Terraform modules, and their dependencies. That information is persisted for further usage.\n\n```\ntfmake init\n```\n\nSometimes, a requirement arises to exclude some modules inside a project. The option `--exclude` supports it, by passing  a space separated list of modules.\n\n```\ntfmake init -i \"X Y Z\"\n```\n\n#### tfmake generate\n\nThis command acts like a code generator, using the information gathered by **init** to create a `Makefile`. Each module is added as a _target_, with their files and dependencies as _prerequisites_. The **tfmake** context determines the Terraform command to use as part of the _target's recipes_.\n\n```\ntfmake generate\n```\n\nWhat follows is an adapted example for a three-module project plan `Makefile`.\n\n```Makefile\nall: A B C\n\nA: $(wildcard A/*.tf A/*.tfvars)\n\tterraform -chdir=\"A\" init\n\tterraform -chdir=\"A\" plan\n\nB: $(wildcard B/*.tf B/*.tfvars) A\n\tterraform -chdir=\"B\" init\n\tterraform -chdir=\"B\" plan\n\nC: $(wildcard C/*.tf C/*.tfvars) A B\n\tterraform -chdir=\"C\" init\n\tterraform -chdir=\"C\" plan\n```\n\nWhen the `Makefile` is there, it's possible to use it for running the [make](https://man7.org/linux/man-pages/man1/make.1.html) utility.\n\nOne of the goals of **tfmake** is to avoid unnecessary executions. If a module (_target_) files or their dependencies don't change, there is no need to run a `validate`, `plan`, `apply`, or `destroy` on it. This behavior, derived from the `make` way of working, reduces the execution time and favors cost optimization.\n\n\u003e The make program uses the makefile description and the last-modification times of the files to decide which of the files need to be updated.\n\n#### tfmake run\n\nAs mentioned before, a `Makefile` is the entrypoint for `make` execution. The **run** command brings some advantages over it, including multiple modes of execution and a proper handling of failures for CI/CD pipelines.\n\nBy default (`tfmake run`), the command calls `make` and runs it with the semantics described above, avoiding unnecessary executions. However, two other modes exist with the options `--all` and `--dry-run`.\n\nThe first one executes Terraform `validate`, `plan`, `apply`, or `destroy` for all modules, whereas the second is similar to the default mode, producing a list of modules but without running their recipes.\n\n### Configuring the Infrastructure as Code Tool\n\nBy default, `tfmake` uses `terraform` as its infrastructure as code tool. However, it can also be set to use OpenTofu if preferred.\n\n```bash\ntfmake config --set iactool tofu\n```\n\n### A special command\n\n#### tfmake touch\n\nThe **touch** command is a wrapper over the corresponding Linux utility, and is used to change the modification time of modules files. This is mandatory in a GitHub Actions workflow after a [checkout](https://github.com/actions/checkout) or could be used in a local environment to force the `make` semantics.\n\nFor instance, using the modules A, B and C; a change in a `.tf` file inside B will cause the execution of it and C in that order.\n\nThe command could be executed with the option `-f|--files` and a list of space separated files.\n\n```\ntfmake touch -f \"A/main.tf B/main.tf\"\n```\n\nis equivalent to\n\n```\ntfmake touch -f \"A/main.tf\" -f \"B/main.tf\"\n```\n\n\u003e In a GitHub Actions workflow use `tj-actions/changed-files` to get the list of changed files.\n\n### Outputs and feedback\n\nWhen the **run** command is finished, the outputs from Terraform executions for each module are stored for further processing. The **summary** command produces a report in Markdown format, after joining them all.\n\nWhen running `tfmake` as part of a GitHub Actions workflow, it is possible to use the report to provide feedback in two different ways.\n\nThe first is by means of a Pull Request comment, with the help of the following command.\n\n```\ntfmake gh-pr-comment --number \"${{ github.event.pull_request.number }}\"\n```\n\nThe second alternative is based on the GitHub Actions Step Summary feature, with the help of the **gh-step-summary** command.\n\n## License\n\n[MIT License](https://github.com/tfmake/tfmake/blob/main/LICENSE)\n","funding_links":[],"categories":["Tools"],"sub_categories":["Community providers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfmake%2Ftfmake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftfmake%2Ftfmake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfmake%2Ftfmake/lists"}