While terraform-exec is already widely used, please note that this module is not yet at v1.0.0, and that therefore breaking changes may occur in minor releases.
We strictly follow semantic versioning.
Three packages comprise the public API of the terraform-exec Go module:
Package github.com/hashicorp/terraform-exec/tfexec
exposes functionality for constructing and running Terraform CLI commands. Structured return values use the data types defined in the hashicorp/terraform-json package.
Each Terraform CLI first- or second-level subcommand (e.g. terraform refresh
, or terraform workspace new
) is implemented in a separate Go file. This file defines a public function on the Terraform
struct, which consumers use to call the CLI command, and a private *Cmd
version of this function which returns an *exec.Cmd
, in order to facilitate unit testing (see Testing below).
For example:
func (tf *Terraform) Refresh(ctx context.Context, opts ...RefreshCmdOption) error {
cmd, err := tf.refreshCmd(ctx, opts...)
if err != nil {
return err
}
return tf.runTerraformCmd(cmd)
}
func (tf *Terraform) refreshCmd(ctx context.Context, opts ...RefreshCmdOption) (*exec.Cmd, error) {
...
return tf.buildTerraformCmd(ctx, mergeEnv, args...), nil
}
Command options are implemented using the functional variadic options pattern. For further reading on this pattern, please see Functional options for friendly APIs by Dave Cheney.
We aim for full test coverage of all Terraform CLI commands implemented in tfexec
, with as many combinations of command-line options as possible. New command implementations will not be merged without both unit and end-to-end tests.
The following environment variables can be set during testing:
TFEXEC_E2ETEST_VERSIONS
: When set to a comma-separated list of version strings, this overrides the default list of Terraform versions for end-to-end tests, and runs those tests against only the versions supplied.TFEXEC_E2ETEST_TERRAFORM_PATH
: When set to the path of a valid local Terraform executable, only tests appropriate to that executable's version are run. No other versions are downloaded or run. Note that this means that tests usingrunTestWithVersions()
will only run if the test version matches the local executable exactly.
If both of these environment variables are set, TFEXEC_E2ETEST_TERRAFORM_PATH
takes precedence, and any other versions specified in TFEXEC_E2ETEST_VERSIONS
are ignored.
Unit tests live alongside command implementations in tfexec/
. A unit test asserts that the string version of the exec.Cmd
returned by the *Cmd
function (e.g. refreshCmd
) is as expected. Minimally, commands must be tested with no options passed ("defaults"), and with all options set to non-default values. The assertCmd()
helper can be used for this purpose. Please see tfexec/init_test.go
for a reasonable starting point.
End-to-end tests test both tfinstall
and tfexec
, using the former to install Terraform binaries according to various version constraints, and exercising the latter in as many combinations as possible, after real-world use cases.
By default, each test is run against the latest patch versions of all Terraform minor version releases, starting at 0.11. Copy an existing test and use the runTest()
helper for this purpose.
Subject to compatibility guarantees, each new version of Terraform CLI may:
- Add a command or flag not previously present
- Remove a command or flag
- Change stdout or stderr output
- Change the format of output files, e.g. the state file
- Change a command's exit code
These and any other differences between versions should be specified in test assertions.
If the command implemented differs in any way between Terraform versions (e.g. a flag is added or removed, or the subcommand does not exist in earlier versions), use t.Skip()
directives and version checks to adapt test behaviour as appropriate. For example:
https://github.com/hashicorp/terraform-exec/blob/d0cb3efafda90dd47bbfabdccde3cf7e45e0376d/tfexec/internal/e2etest/validate_test.go#L15-L23
The runTestWithVersions()
helper can be used to run tests against specific Terraform versions. This should be used only alongside a test using runTest()
to cover the remaining past and future versions.
The github.com/hashicorp/terraform-exec
Go module in its entirety is versioned according to Go module versioning with Git tags. The latest version is automatically written to internal/version/version.go
during the release process.
Releases are made on a reasonably regular basis by the Terraform team, using our custom CI workflows. There is currently no set release schedule and no requirement for contributors to write CHANGELOG entries.
The following notes are only relevant to maintainers.
- Make sure CHANGELOG.md has all changes and the first line has the version you're intending to release (with
(Unreleased)
suffix). - Trigger the
release
workflow from GitHub UI. This will run the release script. As part of that script:
Unreleased
,[GH-XXX]
will be replaced.- The version will be bumped to match the one parsed from
CHANGELOG.md
. - Tag will be pushed
- Create new release via GitHub UI to point to the new tag and copy the appropriate part of the CHANGELOG.md there.
Please disclose security vulnerabilities by following the procedure described at https://www.hashicorp.com/security#vulnerability-reporting.
In general we do not accept PRs containing only the following changes:
- Correcting spelling or typos
- Code formatting, including whitespace
- Other cosmetic changes that do not affect functionality
While we appreciate the effort that goes into preparing PRs, there is always a tradeoff between benefit and cost. The costs involved in accepting such contributions include the time taken for thorough review, the noise created in the git history, and the increased number of GitHub notifications that maintainers must attend to.
We believe that one should "leave the campsite cleaner than you found it", so you are welcome to clean up cosmetic issues in the neighbourhood when submitting a patch that makes functional changes or fixes.