diff --git a/dist/index.js b/dist/index.js index 283f8139..a29b527a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -143,9 +143,18 @@ async function run () { throw new Error(`Terraform version ${version} not available for ${platform} and ${arch}`); } - // Download requested version - const pathToCLI = await downloadCLI(build.url); + const pathToCLI = tc.find('terraform', version, arch); + // check if tool exists in cache, if not, download and cache it + if (!pathToCLI) { + // Download requested version + const pathToCLI = await downloadCLI(build.url); + + // add tool in cache + const cachedPath = await tc.cacheDir(pathToCLI, 'terraform', version, arch); + core.addPath(cachedPath); + } + // Install our wrapper if (wrapper) { await installWrapper(pathToCLI); diff --git a/dist/index1.js b/dist/index1.js index 976a9018..10037ae4 100755 --- a/dist/index1.js +++ b/dist/index1.js @@ -2,66 +2,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 633: -/***/ ((module) => { - -/** - * Acts as a listener for @actions/exec, by capturing STDOUT and STDERR - * streams, and exposing them via a contents attribute. - * - * @example - * // Instantiate a new listener - * const listener = new OutputListener(); - * // Register listener against STDOUT stream - * await exec.exec('ls', ['-ltr'], { - * listeners: { - * stdout: listener.listener - * } - * }); - * // Log out STDOUT contents - * console.log(listener.contents); - */ -class OutputListener { - constructor () { - this._buff = []; - } - - get listener () { - const listen = function listen (data) { - this._buff.push(data); - }; - return listen.bind(this); - } - - get contents () { - return this._buff - .map(chunk => chunk.toString()) - .join(''); - } -} - -module.exports = OutputListener; - - -/***/ }), - -/***/ 483: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const os = __nccwpck_require__(37); -const path = __nccwpck_require__(17); - -module.exports = (() => { - // If we're on Windows, then the executable ends with .exe - const exeSuffix = os.platform().startsWith('win') ? '.exe' : ''; - - return [process.env.TERRAFORM_CLI_PATH, `terraform-bin${exeSuffix}`].join(path.sep); -})(); - - -/***/ }), - -/***/ 241: +/***/ 190: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -88,7 +29,7 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; const os = __importStar(__nccwpck_require__(37)); -const utils_1 = __nccwpck_require__(278); +const utils_1 = __nccwpck_require__(861); /** * Commands * @@ -160,7 +101,7 @@ function escapeProperty(s) { /***/ }), -/***/ 186: +/***/ 316: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -195,12 +136,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(241); -const file_command_1 = __nccwpck_require__(717); -const utils_1 = __nccwpck_require__(278); +const command_1 = __nccwpck_require__(190); +const file_command_1 = __nccwpck_require__(685); +const utils_1 = __nccwpck_require__(861); const os = __importStar(__nccwpck_require__(37)); const path = __importStar(__nccwpck_require__(17)); -const oidc_utils_1 = __nccwpck_require__(41); +const oidc_utils_1 = __nccwpck_require__(419); /** * The code to exit an action */ @@ -475,11 +416,16 @@ function getIDToken(aud) { }); } exports.getIDToken = getIDToken; +/** + * Markdown summary exports + */ +var markdown_summary_1 = __nccwpck_require__(94); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return markdown_summary_1.markdownSummary; } })); //# sourceMappingURL=core.js.map /***/ }), -/***/ 717: +/***/ 685: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -510,7 +456,7 @@ exports.issueCommand = void 0; /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__nccwpck_require__(147)); const os = __importStar(__nccwpck_require__(37)); -const utils_1 = __nccwpck_require__(278); +const utils_1 = __nccwpck_require__(861); function issueCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { @@ -528,7 +474,293 @@ exports.issueCommand = issueCommand; /***/ }), -/***/ 41: +/***/ 94: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(37); +const fs_1 = __nccwpck_require__(147); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary'; +class MarkdownSummary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports markdown summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} markdown summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {MarkdownSummary} markdown summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {MarkdownSummary} markdown summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {MarkdownSummary} markdown summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {MarkdownSummary} markdown summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {MarkdownSummary} markdown summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {MarkdownSummary} markdown summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {MarkdownSummary} markdown summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {MarkdownSummary} markdown summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {MarkdownSummary} markdown summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {MarkdownSummary} markdown summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {MarkdownSummary} markdown summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {MarkdownSummary} markdown summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {MarkdownSummary} markdown summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {MarkdownSummary} markdown summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +// singleton export +exports.markdownSummary = new MarkdownSummary(); +//# sourceMappingURL=markdown-summary.js.map + +/***/ }), + +/***/ 419: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -544,9 +776,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(925); -const auth_1 = __nccwpck_require__(702); -const core_1 = __nccwpck_require__(186); +const http_client_1 = __nccwpck_require__(770); +const auth_1 = __nccwpck_require__(578); +const core_1 = __nccwpck_require__(316); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -612,7 +844,7 @@ exports.OidcClient = OidcClient; /***/ }), -/***/ 278: +/***/ 861: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -659,7 +891,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 514: +/***/ 110: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -695,7 +927,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getExecOutput = exports.exec = void 0; const string_decoder_1 = __nccwpck_require__(576); -const tr = __importStar(__nccwpck_require__(159)); +const tr = __importStar(__nccwpck_require__(515)); /** * Exec a command. * Output will be streamed to the live console. @@ -769,7 +1001,7 @@ exports.getExecOutput = getExecOutput; /***/ }), -/***/ 159: +/***/ 515: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -808,8 +1040,8 @@ const os = __importStar(__nccwpck_require__(37)); const events = __importStar(__nccwpck_require__(361)); const child = __importStar(__nccwpck_require__(81)); const path = __importStar(__nccwpck_require__(17)); -const io = __importStar(__nccwpck_require__(351)); -const ioUtil = __importStar(__nccwpck_require__(962)); +const io = __importStar(__nccwpck_require__(560)); +const ioUtil = __importStar(__nccwpck_require__(995)); const timers_1 = __nccwpck_require__(512); /* eslint-disable @typescript-eslint/unbound-method */ const IS_WINDOWS = process.platform === 'win32'; @@ -1394,7 +1626,7 @@ class ExecState extends events.EventEmitter { /***/ }), -/***/ 702: +/***/ 578: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -1460,15 +1692,15 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 925: +/***/ 770: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -const http = __nccwpck_require__(685); +const http = __nccwpck_require__(181); const https = __nccwpck_require__(687); -const pm = __nccwpck_require__(443); +const pm = __nccwpck_require__(450); let tunnel; var HttpCodes; (function (HttpCodes) { @@ -1887,7 +2119,7 @@ class HttpClient { if (useProxy) { // If using proxy, need tunnel if (!tunnel) { - tunnel = __nccwpck_require__(294); + tunnel = __nccwpck_require__(220); } const agentOptions = { maxSockets: maxSockets, @@ -2005,7 +2237,7 @@ exports.HttpClient = HttpClient; /***/ }), -/***/ 443: +/***/ 450: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -2070,7 +2302,7 @@ exports.checkBypass = checkBypass; /***/ }), -/***/ 962: +/***/ 995: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -2254,7 +2486,7 @@ exports.getCmdPath = getCmdPath; /***/ }), -/***/ 351: +/***/ 560: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -2293,7 +2525,7 @@ const assert_1 = __nccwpck_require__(491); const childProcess = __importStar(__nccwpck_require__(81)); const path = __importStar(__nccwpck_require__(17)); const util_1 = __nccwpck_require__(837); -const ioUtil = __importStar(__nccwpck_require__(962)); +const ioUtil = __importStar(__nccwpck_require__(995)); const exec = util_1.promisify(childProcess.exec); const execFile = util_1.promisify(childProcess.execFile); /** @@ -2602,15 +2834,15 @@ function copyFile(srcFile, destFile, force) { /***/ }), -/***/ 294: +/***/ 220: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(219); +module.exports = __nccwpck_require__(418); /***/ }), -/***/ 219: +/***/ 418: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2618,7 +2850,7 @@ module.exports = __nccwpck_require__(219); var net = __nccwpck_require__(808); var tls = __nccwpck_require__(404); -var http = __nccwpck_require__(685); +var http = __nccwpck_require__(181); var https = __nccwpck_require__(687); var events = __nccwpck_require__(361); var assert = __nccwpck_require__(491); @@ -2880,6 +3112,65 @@ if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { exports.debug = debug; // for test +/***/ }), + +/***/ 127: +/***/ ((module) => { + +/** + * Acts as a listener for @actions/exec, by capturing STDOUT and STDERR + * streams, and exposing them via a contents attribute. + * + * @example + * // Instantiate a new listener + * const listener = new OutputListener(); + * // Register listener against STDOUT stream + * await exec.exec('ls', ['-ltr'], { + * listeners: { + * stdout: listener.listener + * } + * }); + * // Log out STDOUT contents + * console.log(listener.contents); + */ +class OutputListener { + constructor () { + this._buff = []; + } + + get listener () { + const listen = function listen (data) { + this._buff.push(data); + }; + return listen.bind(this); + } + + get contents () { + return this._buff + .map(chunk => chunk.toString()) + .join(''); + } +} + +module.exports = OutputListener; + + +/***/ }), + +/***/ 851: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const os = __nccwpck_require__(37); +const path = __nccwpck_require__(17); + +module.exports = (() => { + // If we're on Windows, then the executable ends with .exe + const exeSuffix = os.platform().startsWith('win') ? '.exe' : ''; + + return [process.env.TERRAFORM_CLI_PATH, `terraform-bin${exeSuffix}`].join(path.sep); +})(); + + /***/ }), /***/ 491: @@ -2914,7 +3205,7 @@ module.exports = require("fs"); /***/ }), -/***/ 685: +/***/ 181: /***/ ((module) => { "use strict"; @@ -3027,12 +3318,12 @@ module.exports = require("util"); var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { -const io = __nccwpck_require__(351); -const core = __nccwpck_require__(186); -const { exec } = __nccwpck_require__(514); +const io = __nccwpck_require__(560); +const core = __nccwpck_require__(316); +const { exec } = __nccwpck_require__(110); -const OutputListener = __nccwpck_require__(633); -const pathToCLI = __nccwpck_require__(483); +const OutputListener = __nccwpck_require__(127); +const pathToCLI = __nccwpck_require__(851); async function checkTerraform () { // Setting check to `true` will cause `which` to throw if terraform isn't found diff --git a/lib/setup-terraform.js b/lib/setup-terraform.js index 1e61d2c5..0922c07d 100644 --- a/lib/setup-terraform.js +++ b/lib/setup-terraform.js @@ -137,9 +137,18 @@ async function run () { throw new Error(`Terraform version ${version} not available for ${platform} and ${arch}`); } - // Download requested version - const pathToCLI = await downloadCLI(build.url); + const pathToCLI = tc.find('terraform', version, arch); + // check if tool exists in cache, if not, download and cache it + if (!pathToCLI) { + // Download requested version + const pathToCLI = await downloadCLI(build.url); + + // add tool in cache + const cachedPath = await tc.cacheDir(pathToCLI, 'terraform', version, arch); + core.addPath(cachedPath); + } + // Install our wrapper if (wrapper) { await installWrapper(pathToCLI);