From 5de63cedb589ab051d017a264ce2666dd18f6468 Mon Sep 17 00:00:00 2001 From: plukevdh Date: Tue, 23 May 2023 15:50:27 -0400 Subject: [PATCH] utilize .tool-versions file to resolve terraform version --- dist/index.js | 34 ++++++++++++++++++++-- lib/setup-terraform.js | 34 ++++++++++++++++++++-- test/index.json | 40 ++++++++++++++++++++++++++ test/setup-terraform.test.js | 55 +++++++++++++++++++++++++++++++++++- 4 files changed, 158 insertions(+), 5 deletions(-) diff --git a/dist/index.js b/dist/index.js index 85f35b30..7ed7cb18 100644 --- a/dist/index.js +++ b/dist/index.js @@ -34,6 +34,36 @@ function mapOS (os) { return mappings[os] || os; } +async function resolveVersion () { + let version = core.getInput('terraform_version'); + + if (!version) { + version = await getToolVersions(); + } + + return version; +} + +async function getToolVersions () { + let version = ''; + core.debug('Attempting to infer Terraform version from .tool-versions'); + + if (await fs.existsSync('.tool-versions')) { + const contents = await fs.readFileSync('.tool-versions').toString(); + const match = contents.match(/^terraform (\d+(\.\d+)*)/m); + + if (!match) { + core.debug('Could not find a valid terraform version from .tool-versions'); + } else { + version = match[1]; + } + } else { + core.debug('.tool-versions does not exist'); + } + + return version; +} + async function downloadCLI (url) { core.debug(`Downloading Terraform CLI from ${url}`); const pathToCLIZip = await tc.downloadTool(url); @@ -44,7 +74,7 @@ async function downloadCLI (url) { if (os.platform().startsWith('win')) { core.debug(`Terraform CLI Download Path is ${pathToCLIZip}`); const fixedPathToCLIZip = `${pathToCLIZip}.zip`; - io.mv(pathToCLIZip, fixedPathToCLIZip); + await io.mv(pathToCLIZip, fixedPathToCLIZip); core.debug(`Moved download to ${fixedPathToCLIZip}`); pathToCLI = await tc.extractZip(fixedPathToCLIZip); } else { @@ -124,7 +154,7 @@ credentials "${credentialsHostname}" { async function run () { try { // Gather GitHub Actions inputs - const version = core.getInput('terraform_version'); + const version = await resolveVersion(); const credentialsHostname = core.getInput('cli_config_credentials_hostname'); const credentialsToken = core.getInput('cli_config_credentials_token'); const wrapper = core.getInput('terraform_wrapper') === 'true'; diff --git a/lib/setup-terraform.js b/lib/setup-terraform.js index 1e61d2c5..d4012e52 100644 --- a/lib/setup-terraform.js +++ b/lib/setup-terraform.js @@ -28,6 +28,36 @@ function mapOS (os) { return mappings[os] || os; } +async function resolveVersion () { + let version = core.getInput('terraform_version'); + + if (!version) { + version = await getToolVersions(); + } + + return version; +} + +async function getToolVersions () { + let version = ''; + core.debug('Attempting to infer Terraform version from .tool-versions'); + + if (await fs.existsSync('.tool-versions')) { + const contents = await fs.readFileSync('.tool-versions').toString(); + const match = contents.match(/^terraform (\d+(\.\d+)*)/m); + + if (!match) { + core.debug('Could not find a valid terraform version from .tool-versions'); + } else { + version = match[1]; + } + } else { + core.debug('.tool-versions does not exist'); + } + + return version; +} + async function downloadCLI (url) { core.debug(`Downloading Terraform CLI from ${url}`); const pathToCLIZip = await tc.downloadTool(url); @@ -38,7 +68,7 @@ async function downloadCLI (url) { if (os.platform().startsWith('win')) { core.debug(`Terraform CLI Download Path is ${pathToCLIZip}`); const fixedPathToCLIZip = `${pathToCLIZip}.zip`; - io.mv(pathToCLIZip, fixedPathToCLIZip); + await io.mv(pathToCLIZip, fixedPathToCLIZip); core.debug(`Moved download to ${fixedPathToCLIZip}`); pathToCLI = await tc.extractZip(fixedPathToCLIZip); } else { @@ -118,7 +148,7 @@ credentials "${credentialsHostname}" { async function run () { try { // Gather GitHub Actions inputs - const version = core.getInput('terraform_version'); + const version = await resolveVersion(); const credentialsHostname = core.getInput('cli_config_credentials_hostname'); const credentialsToken = core.getInput('cli_config_credentials_token'); const wrapper = core.getInput('terraform_wrapper') === 'true'; diff --git a/test/index.json b/test/index.json index dd2531d3..e1e2a7c6 100644 --- a/test/index.json +++ b/test/index.json @@ -176,6 +176,46 @@ "url": "https://releases.hashicorp.com/terraform/0.10.0/terraform_0.10.0_windows_386.zip" } ] + }, + "1.3.7": { + "name": "terraform", + "version": "1.3.7", + "shasums": "terraform_1.3.7_SHA256SUMS", + "shasums_signature": "terraform_1.3.7_SHA256SUMS.sig", + "builds": [ + { + "name": "terraform", + "version": "1.3.7", + "os": "darwin", + "arch": "amd64", + "filename": "terraform_1.3.7_darwin_amd64.zip", + "url": "https://releases.hashicorp.com/terraform/1.3.7/terraform_1.3.7_darwin_amd64.zip" + }, + { + "name": "terraform", + "version": "1.3.7", + "os": "linux", + "arch": "386", + "filename": "terraform_1.3.7_linux_386.zip", + "url": "https://releases.hashicorp.com/terraform/1.3.7/terraform_1.3.7_linux_386.zip" + }, + { + "name": "terraform", + "version": "1.3.7", + "os": "linux", + "arch": "amd64", + "filename": "terraform_1.3.7_linux_amd64.zip", + "url": "https://releases.hashicorp.com/terraform/1.3.7/terraform_1.3.7_linux_amd64.zip" + }, + { + "name": "terraform", + "version": "1.3.7", + "os": "windows", + "arch": "386", + "filename": "terraform_1.3.7_windows_386.zip", + "url": "https://releases.hashicorp.com/terraform/1.3.7/terraform_1.3.7_windows_386.zip" + } + ] } } } \ No newline at end of file diff --git a/test/setup-terraform.test.js b/test/setup-terraform.test.js index 367de90b..41130e27 100644 --- a/test/setup-terraform.test.js +++ b/test/setup-terraform.test.js @@ -156,7 +156,7 @@ describe('Setup Terraform', () => { .reply(200, json); const versionObj = await setup(); - expect(versionObj.version).toEqual('0.10.0'); + expect(versionObj.version).toEqual('1.3.7'); // downloaded CLI has been added to path expect(core.addPath).toHaveBeenCalled(); @@ -420,6 +420,59 @@ describe('Setup Terraform', () => { expect(creds.indexOf(credentialsToken)).toBeGreaterThan(-1); }); + test('gets version from .tool-versions when version not provided', async () => { + const credentialsHostname = 'app.terraform.io'; + const credentialsToken = 'asdfjkl'; + + fs.existsSync = jest + .fn() + .mockReturnValueOnce(true); + + fs.readFileSync = jest + .fn() + .mockReturnValueOnce(`terraform 1.3.7 +golang 1.16.3 +python 3.10.11 +ruby 3.2.1 +`); + + core.getInput = jest + .fn() + .mockReturnValueOnce(null) + .mockReturnValueOnce(credentialsHostname) + .mockReturnValueOnce(credentialsToken); + + tc.downloadTool = jest + .fn() + .mockReturnValueOnce('file.zip'); + + tc.extractZip = jest + .fn() + .mockReturnValueOnce('file'); + + os.platform = jest + .fn() + .mockReturnValue('linux'); + + os.arch = jest + .fn() + .mockReturnValue('amd64'); + + nock('https://releases.hashicorp.com') + .get('/terraform/index.json') + .reply(200, json); + + const versionObj = await setup(); + expect(versionObj.version).toEqual('1.3.7'); + + // downloaded CLI has been added to path + expect(core.addPath).toHaveBeenCalled(); + // expect credentials are in ${HOME}.terraformrc + const creds = await fs.readFile(`${process.env.HOME}/.terraformrc`, { encoding: 'utf8' }); + expect(creds.indexOf(credentialsHostname)).toBeGreaterThan(-1); + expect(creds.indexOf(credentialsToken)).toBeGreaterThan(-1); + }); + test('fails when metadata cannot be downloaded', async () => { const version = 'latest'; const credentialsHostname = 'app.terraform.io';