Skip to content

feat: support terraform_version_file #454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ steps:
terraform_version: "1.1.7"
```

A specific version of Terraform CLI can be installed using a version file:

```yaml
steps:
- uses: hashicorp/setup-terraform@v3
with:
terraform_version_file: ".tool-versions"
```

Credentials for HCP Terraform ([app.terraform.io](https://app.terraform.io/)) can be configured:

```yaml
Expand Down Expand Up @@ -251,10 +260,24 @@ The action supports the following inputs:
for available range specifications). Examples are: `"<1.2.0"`, `"~1.1.0"`, `"1.1.7"` (all three installing
the latest available `1.1` version). Prerelease versions can be specified and a range will stay within the
given tag such as `beta` or `rc`. If no version is given, it will default to `latest`.
- `terraform_version_file` - (optional) The path to a file containing terraform version. Supported file types are `.tool-versions` or `.terraform-version`. See more details in [about version-file](#Terraform-version-file).
- `terraform_wrapper` - (optional) Whether to install a wrapper to wrap subsequent calls of
the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs
named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.

### Terraform version file

If the `terraform_version_file` input is specified, the action will extract the version from the file and install it.

Supported files names are `.tool-versions` or `.terraform-version`.
In `.tool-versions` file, terraform version should be preceded by the terraform keyword (e.g., `terraform 1.13.0`).
The `.tool-versions` file supports version specifications in accordance with Semantic Versioning ([semver](https://semver.org/)) and [Semver Ranges](https://www.npmjs.com/package/semver#ranges).
The `.terraform-version` file supports version specifications as explained in the `terraform_version` input.

If both `terraform_version` and `terraform_version_file` inputs are provided, the `terraform_version` input will be used.

If the file contains multiple versions, only the first one will be recognized.

## Outputs

This action does not configure any outputs directly. However, when you set the `terraform_wrapper` input
Expand Down
4 changes: 3 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ inputs:
required: false
terraform_version:
description: 'The version of Terraform CLI to install. Instead of full version string you can also specify constraint string starting with "<" (for example `<1.13.0`) to install the latest version satisfying the constraint. A value of `latest` will install the latest version of Terraform CLI. Defaults to `latest`.'
default: 'latest'
required: false
terraform_version_file:
description: 'The path to the `.terraform-version` file. See examples of supported syntax in README file'
required: false
terraform_wrapper:
description: 'Whether or not to install a wrapper to wrap subsequent calls of the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.'
Expand Down
58 changes: 57 additions & 1 deletion lib/setup-terraform.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,70 @@ credentials "${credentialsHostname}" {
await fs.writeFile(credsFile, creds);
}

async function getVersionFromFileContent (versionFile) {
if (!versionFile) {
return;
}

let versionRegExp;
const versionFileName = path.basename(versionFile);
if (versionFileName === '.tool-versions') {
versionRegExp = /^(terraform\s+)(?<version>[^\s]+)$/m;
} else if (versionFileName === '.terraform-version') {
versionRegExp = /(?<version>[^\s]+)/;
} else {
return;
}

try {
const content = fs.readFileSync(versionFile).toString().trim();
let fileContent = '';
if (content.match(versionRegExp)?.groups?.version) {
fileContent = content.match(versionRegExp)?.groups?.version;
}
if (!fileContent) {
return;
}
core.debug(`Version from file '${fileContent}'`);
return fileContent;
} catch (error) {
if (error.code === 'ENOENT') {
return;
}
throw error;
}
}

// get the Terraform version from the action inputs
async function getTerraformVersion (versionInput, versionFile) {
const DEFAULT_VERSION = 'latest';

let version = versionInput;
if (!versionInput && !versionFile) {
core.info(`Set default value for version to ${DEFAULT_VERSION}`);
version = DEFAULT_VERSION;
}

if (!version && versionFile) {
version = await getVersionFromFileContent(versionFile);
if (!version) {
throw new Error(`No supported version was found in file ${versionFile}`);
}
}
return version;
}

async function run () {
try {
// Gather GitHub Actions inputs
const version = core.getInput('terraform_version');
const versionInput = core.getInput('terraform_version', { required: false });
const versionFile = core.getInput('terraform_version_file', { required: false });
const credentialsHostname = core.getInput('cli_config_credentials_hostname');
const credentialsToken = core.getInput('cli_config_credentials_token');
const wrapper = core.getInput('terraform_wrapper') === 'true';

const version = await getTerraformVersion(versionInput, versionFile);

// Gather OS details
const osPlatform = os.platform();
const osArch = os.arch();
Expand Down
Loading