From 5db7851ff2abe8d6e091dad159ceeb22e0fbdd3b Mon Sep 17 00:00:00 2001 From: Jared Cuffe Date: Wed, 3 Mar 2021 20:58:18 -0800 Subject: [PATCH 1/2] Uses tool cache - skips wrapper create on hit. --- dist/index.js | 43 ++++++++++++++++++++++++++++++++++-------- lib/setup-terraform.js | 43 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/dist/index.js b/dist/index.js index 9c5f3c03..8f590084 100644 --- a/dist/index.js +++ b/dist/index.js @@ -34,6 +34,9 @@ const tc = __webpack_require__(7784); const io = __webpack_require__(7436); const releases = __webpack_require__(9947); +// Constants +const CACHE_KEY = 'terraform'; + // arch in [arm, x32, x64...] (https://nodejs.org/api/os.html#os_os_arch) // return value in [amd64, 386, arm] function mapArch (arch) { @@ -53,7 +56,7 @@ function mapOS (os) { return mappings[os] || os; } -async function downloadCLI (url) { +async function downloadCLI (url, version) { core.debug(`Downloading Terraform CLI from ${url}`); const pathToCLIZip = await tc.downloadTool(url); @@ -65,7 +68,24 @@ async function downloadCLI (url) { throw new Error(`Unable to download Terraform from ${url}`); } - return pathToCLI; + // Cache for later + const cachedPath = await tc.cacheDir(pathToCLI, CACHE_KEY, version); + return cachedPath; +} + +async function checkWrapper (pathToCLI) { + const exeSuffix = os.platform().startsWith('win') ? '.exe' : ''; + const target = [pathToCLI, `terraform-bin${exeSuffix}`].join(path.sep); + + core.debug('Checking for existing wrapper'); + + const hasWrapper = io.which(target); + + if (hasWrapper) { + core.debug('Wrapper found, skipping creation.'); + } + + return hasWrapper; } async function installWrapper (pathToCLI) { @@ -95,9 +115,6 @@ async function installWrapper (pathToCLI) { core.error(`Unable to copy ${source} to ${target}.`); throw e; } - - // Export a new environment variable, so our wrapper can locate the binary - core.exportVariable('TERRAFORM_CLI_PATH', pathToCLI); } // Add credentials to CLI Configuration File @@ -151,14 +168,24 @@ async function run () { throw new Error(`Terraform version ${version} not available for ${platform} and ${arch}`); } - // Download requested version - const pathToCLI = await downloadCLI(build.url); + // Check cache for requested version, then download if not present + let pathToCLI = tc.find(CACHE_KEY, release.version, os.arch()); + + // Check to see if wrapper has been installed in a previous run + const hasWrapper = pathToCLI && checkWrapper(pathToCLI); + + if (!pathToCLI) { + pathToCLI = await downloadCLI(build.url, release.version); + } // Install our wrapper - if (wrapper) { + if (wrapper && !hasWrapper) { await installWrapper(pathToCLI); } + // Export a new environment variable, so our wrapper can locate the binary + core.exportVariable('TERRAFORM_CLI_PATH', pathToCLI); + // Add to path core.addPath(pathToCLI); diff --git a/lib/setup-terraform.js b/lib/setup-terraform.js index 2f0b8bf6..f5c5bb59 100644 --- a/lib/setup-terraform.js +++ b/lib/setup-terraform.js @@ -9,6 +9,9 @@ const tc = require('@actions/tool-cache'); const io = require('@actions/io'); const releases = require('@hashicorp/js-releases'); +// Constants +const CACHE_KEY = 'terraform'; + // arch in [arm, x32, x64...] (https://nodejs.org/api/os.html#os_os_arch) // return value in [amd64, 386, arm] function mapArch (arch) { @@ -28,7 +31,7 @@ function mapOS (os) { return mappings[os] || os; } -async function downloadCLI (url) { +async function downloadCLI (url, version) { core.debug(`Downloading Terraform CLI from ${url}`); const pathToCLIZip = await tc.downloadTool(url); @@ -40,7 +43,24 @@ async function downloadCLI (url) { throw new Error(`Unable to download Terraform from ${url}`); } - return pathToCLI; + // Cache for later + const cachedPath = await tc.cacheDir(pathToCLI, CACHE_KEY, version); + return cachedPath; +} + +async function checkWrapper (pathToCLI) { + const exeSuffix = os.platform().startsWith('win') ? '.exe' : ''; + const target = [pathToCLI, `terraform-bin${exeSuffix}`].join(path.sep); + + core.debug('Checking for existing wrapper'); + + const hasWrapper = io.which(target); + + if (hasWrapper) { + core.debug('Wrapper found, skipping creation.'); + } + + return hasWrapper; } async function installWrapper (pathToCLI) { @@ -70,9 +90,6 @@ async function installWrapper (pathToCLI) { core.error(`Unable to copy ${source} to ${target}.`); throw e; } - - // Export a new environment variable, so our wrapper can locate the binary - core.exportVariable('TERRAFORM_CLI_PATH', pathToCLI); } // Add credentials to CLI Configuration File @@ -126,14 +143,24 @@ async function run () { throw new Error(`Terraform version ${version} not available for ${platform} and ${arch}`); } - // Download requested version - const pathToCLI = await downloadCLI(build.url); + // Check cache for requested version, then download if not present + let pathToCLI = tc.find(CACHE_KEY, release.version, os.arch()); + + // Check to see if wrapper has been installed in a previous run + const hasWrapper = pathToCLI && checkWrapper(pathToCLI); + + if (!pathToCLI) { + pathToCLI = await downloadCLI(build.url, release.version); + } // Install our wrapper - if (wrapper) { + if (wrapper && !hasWrapper) { await installWrapper(pathToCLI); } + // Export a new environment variable, so our wrapper can locate the binary + core.exportVariable('TERRAFORM_CLI_PATH', pathToCLI); + // Add to path core.addPath(pathToCLI); From 0e91055bdfa4d3baef5c73c252c1d1c86dd12214 Mon Sep 17 00:00:00 2001 From: Jared Cuffe Date: Fri, 5 Mar 2021 20:10:13 -0800 Subject: [PATCH 2/2] Mocks new tool-cache methods. --- test/setup-terraform.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/setup-terraform.test.js b/test/setup-terraform.test.js index fa2fd337..24e0190c 100644 --- a/test/setup-terraform.test.js +++ b/test/setup-terraform.test.js @@ -564,6 +564,13 @@ describe('Setup Terraform', () => { .fn() .mockReturnValueOnce('file'); + tc.cacheDir = jest.fn() + .mockReturnValueOnce('file'); + + tc.find = jest + .fn() + .mockReturnValueOnce(null); + os.platform = jest .fn() .mockReturnValue('linux'); @@ -608,6 +615,13 @@ describe('Setup Terraform', () => { .fn() .mockReturnValueOnce('file'); + tc.cacheDir = jest.fn() + .mockReturnValueOnce('file'); + + tc.find = jest + .fn() + .mockReturnValueOnce(null); + os.platform = jest .fn() .mockReturnValue('win32');