Skip to content

Commit

Permalink
Allow to specify range specification instead of fixed version
Browse files Browse the repository at this point in the history
That allows to install for example the latest bug-fix version of
terraform 1.12.* even if 1.13 is already installed.
  • Loading branch information
sudomateo authored and potiuk committed Sep 8, 2020
1 parent e255dfd commit 861edd3
Show file tree
Hide file tree
Showing 5 changed files with 354 additions and 57 deletions.
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,29 @@ steps:
## Inputs
The following inputs are supported.
The action supports the following inputs:
- `cli_config_credentials_hostname` - (optional) The hostname of a Terraform Cloud/Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.
- `cli_config_credentials_hostname` - (optional) The hostname of a Terraform Cloud/Enterprise instance to
place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.

- `cli_config_credentials_token` - (optional) The API token for a Terraform Cloud/Enterprise instance to place within the credentials block of the Terraform CLI configuration file.
- `cli_config_credentials_token` - (optional) The API token for a Terraform Cloud/Enterprise instance to
place within the credentials block of the Terraform CLI configuration file.

- `terraform_version` - (optional) The version of Terraform CLI to install. A value of `latest` will install the latest version of Terraform CLI. Defaults to `latest`.
- `terraform_version` - (optional) The version of Terraform CLI to install. Instead of a full version string,
you can also specify a constraint string (see [Semver Ranges](https://www.npmjs.com/package/semver#ranges)
for available range specifications). Examples are: `<1.13.0`, `~1.12`, `1.12.x` (all three installing
the latest available 1.12 version). The special value of `latest` installs the latest version of
Terraform CLI. Defaults to `latest`.

- `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_wrapper` - (optional) 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`.

## Outputs

This action does not configure any outputs directly. However, when the `terraform_wrapper` input is set to `true`, the following outputs will be available for subsequent steps that call the `terraform` binary.
This action does not configure any outputs directly. However, when you set the `terraform_wrapper` input
to `true`, the following outputs is available for subsequent steps that call the `terraform` binary.

- `stdout` - The STDOUT stream of the call to the `terraform` binary.

Expand Down
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: 'HashiCorp - Setup Terraform'
description: 'Sets up Terraform CLI in your GitHub Actions workflow.'
author: 'HashiCorp, Inc.'
author: 'HashiCorp, Inc. (original)'
inputs:
cli_config_credentials_hostname:
description: 'The hostname of a Terraform Cloud/Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.'
Expand All @@ -10,7 +10,7 @@ inputs:
description: 'The API token for a Terraform Cloud/Enterprise instance to place within the credentials block of the Terraform CLI configuration file.'
required: false
terraform_version:
description: 'The version of Terraform CLI to install. A value of `latest` will install the latest version of Terraform CLI. Defaults to `latest`.'
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_wrapper:
Expand Down
56 changes: 36 additions & 20 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2068,14 +2068,23 @@ function findLatest (allVersions) {
// Find specific version given list of all available
function findSpecific (allVersions, version) {
core.debug(`Parsing version list for version ${version}`);
return allVersions.versions[version];
}

const versionObj = allVersions.versions[version];

if (!versionObj) {
throw new Error(`Could not find Terraform version ${version} in version list`);
// Find specific version given list of all available
function findLatestMatchingSpecification (allVersions, version) {
core.debug(`Parsing version list for latest matching specification ${version}`);
const versionList = [];
for (const _version in allVersions.versions) {
versionList.push(_version);
}
const bestMatchVersion = semver.maxSatisfying(versionList, version);
if (!bestMatchVersion) {
throw new Error(`Could not find Terraform version matching ${version} in version list`);
}
core.info(`Latest version satisfying ${version} is ${bestMatchVersion}`);

return versionObj;
return allVersions.versions[bestMatchVersion];
}

async function downloadMetadata () {
Expand Down Expand Up @@ -2215,30 +2224,37 @@ async function run () {
// Download metadata about all versions of Terraform CLI
const versionMetadata = await downloadMetadata();

const specificMatch = findSpecific(versionMetadata, version);
// Find latest or a specific version like 0.1.0
const versionObj = version.toLowerCase() === 'latest' ? findLatest(versionMetadata) : findSpecific(versionMetadata, version);
const versionObj = version.toLowerCase() === 'latest'
? findLatest(versionMetadata) : specificMatch || findLatestMatchingSpecification(versionMetadata, version);

// Get the build available for this runner's OS and a 64 bit architecture
const buildObj = getBuild(versionObj, osPlat, osArch);
if (versionObj) {
// Get the build available for this runner's OS and a 64 bit architecture
const buildObj = getBuild(versionObj, osPlat, osArch);

// Download requested version
const pathToCLI = await downloadCLI(buildObj.url);
// Download requested version
const pathToCLI = await downloadCLI(buildObj.url);

// Install our wrapper
if (wrapper) {
await installWrapper(pathToCLI);
}
// Install our wrapper
if (wrapper) {
await installWrapper(pathToCLI);
}

// Add to path
core.addPath(pathToCLI);
// Add to path
core.addPath(pathToCLI);

// Add credentials to file if they are provided
if (credentialsHostname && credentialsToken) {
await addCredentials(credentialsHostname, credentialsToken, osPlat);
// Add credentials to file if they are provided
if (credentialsHostname && credentialsToken) {
await addCredentials(credentialsHostname, credentialsToken, osPlat);
}
return versionObj;
} else {
core.setFailed(`Could not find Terraform version ${version} in version list`);
}
} catch (error) {
core.error(error);
throw new Error(error);
throw error;
}
}

Expand Down
66 changes: 41 additions & 25 deletions lib/setup-terraform.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,23 @@ function findLatest (allVersions) {
// Find specific version given list of all available
function findSpecific (allVersions, version) {
core.debug(`Parsing version list for version ${version}`);
return allVersions.versions[version];
}

const versionObj = allVersions.versions[version];

if (!versionObj) {
throw new Error(`Could not find Terraform version ${version} in version list`);
// Find specific version given list of all available
function findLatestMatchingSpecification (allVersions, version) {
core.debug(`Parsing version list for latest matching specification ${version}`);
const versionList = [];
for (const _version in allVersions.versions) {
versionList.push(_version);
}
const bestMatchVersion = semver.maxSatisfying(versionList, version);
if (!bestMatchVersion) {
throw new Error(`Could not find Terraform version matching ${version} in version list`);
}
core.info(`Latest version satisfying ${version} is ${bestMatchVersion}`);

return versionObj;
return allVersions.versions[bestMatchVersion];
}

async function downloadMetadata () {
Expand Down Expand Up @@ -180,30 +189,37 @@ async function run () {
// Download metadata about all versions of Terraform CLI
const versionMetadata = await downloadMetadata();

const specificMatch = findSpecific(versionMetadata, version);
// Find latest or a specific version like 0.1.0
const versionObj = version.toLowerCase() === 'latest' ? findLatest(versionMetadata) : findSpecific(versionMetadata, version);

// Get the build available for this runner's OS and a 64 bit architecture
const buildObj = getBuild(versionObj, osPlat, osArch);

// Download requested version
const pathToCLI = await downloadCLI(buildObj.url);

// Install our wrapper
if (wrapper) {
await installWrapper(pathToCLI);
}

// Add to path
core.addPath(pathToCLI);

// Add credentials to file if they are provided
if (credentialsHostname && credentialsToken) {
await addCredentials(credentialsHostname, credentialsToken, osPlat);
const versionObj = version.toLowerCase() === 'latest'
? findLatest(versionMetadata) : specificMatch || findLatestMatchingSpecification(versionMetadata, version);

if (versionObj) {
// Get the build available for this runner's OS and a 64 bit architecture
const buildObj = getBuild(versionObj, osPlat, osArch);

// Download requested version
const pathToCLI = await downloadCLI(buildObj.url);

// Install our wrapper
if (wrapper) {
await installWrapper(pathToCLI);
}

// Add to path
core.addPath(pathToCLI);

// Add credentials to file if they are provided
if (credentialsHostname && credentialsToken) {
await addCredentials(credentialsHostname, credentialsToken, osPlat);
}
return versionObj;
} else {
core.setFailed(`Could not find Terraform version ${version} in version list`);
}
} catch (error) {
core.error(error);
throw new Error(error);
throw error;
}
}

Expand Down
Loading

0 comments on commit 861edd3

Please sign in to comment.