From 25100680598dbfccce9cc8a06b6121769ba6fa26 Mon Sep 17 00:00:00 2001 From: craigdbarber Date: Thu, 7 Nov 2019 12:47:11 -0800 Subject: [PATCH] Added dist files, skipped tar steps for windows os in tests, increased timeout for installer test --- setup-gcloud/.gitignore | 1 + setup-gcloud/__tests__/client-util.test.ts | 8 +- setup-gcloud/__tests__/download-util.test.ts | 11 + setup-gcloud/__tests__/install-util.test.ts | 2 +- setup-gcloud/dist/client-util.js | 99 ++++++++ setup-gcloud/dist/download-util.js | 63 +++++ setup-gcloud/dist/gcloud-sdk-test.js | 69 ++++++ setup-gcloud/dist/install-util.js | 64 +++++ setup-gcloud/dist/installer.js | 243 +++++++++++++++++++ setup-gcloud/dist/setup-gcloud.js | 104 ++++++++ setup-gcloud/dist/src/client-util.js | 99 ++++++++ setup-gcloud/dist/src/download-util.js | 63 +++++ setup-gcloud/dist/src/install-util.js | 64 +++++ setup-gcloud/dist/src/setup-gcloud.js | 104 ++++++++ setup-gcloud/dist/test-util.js | 46 ++++ setup-gcloud/dist/test.js | 52 ++++ 16 files changed, 1088 insertions(+), 4 deletions(-) create mode 100644 setup-gcloud/dist/client-util.js create mode 100644 setup-gcloud/dist/download-util.js create mode 100644 setup-gcloud/dist/gcloud-sdk-test.js create mode 100644 setup-gcloud/dist/install-util.js create mode 100644 setup-gcloud/dist/installer.js create mode 100644 setup-gcloud/dist/setup-gcloud.js create mode 100644 setup-gcloud/dist/src/client-util.js create mode 100644 setup-gcloud/dist/src/download-util.js create mode 100644 setup-gcloud/dist/src/install-util.js create mode 100644 setup-gcloud/dist/src/setup-gcloud.js create mode 100644 setup-gcloud/dist/test-util.js create mode 100644 setup-gcloud/dist/test.js diff --git a/setup-gcloud/.gitignore b/setup-gcloud/.gitignore index 08a94406..90e11084 100644 --- a/setup-gcloud/.gitignore +++ b/setup-gcloud/.gitignore @@ -1,5 +1,6 @@ node_modules/ __tests__/runner/* +runner/ # Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore # Logs diff --git a/setup-gcloud/__tests__/client-util.test.ts b/setup-gcloud/__tests__/client-util.test.ts index 20c0cef2..0cd04714 100644 --- a/setup-gcloud/__tests__/client-util.test.ts +++ b/setup-gcloud/__tests__/client-util.test.ts @@ -20,6 +20,8 @@ import * as testUtil from '../src/test-util'; import * as util from '../src/client-util'; +const TEST_TIMEOUT_MILLIS = 10000; + describe('queryGcloudSDKRelease tests', () => { it('Finds matching version linux', async () => { const release: util.IGcloudSDKRelease | null = await util.queryGcloudSDKRelease( @@ -35,7 +37,7 @@ describe('queryGcloudSDKRelease tests', () => { `https://www.googleapis.com/download/storage/v1/b/cloud-sdk-release/o/google-cloud-sdk-${testUtil.TEST_SDK_VERSION}-linux-x86_64.tar.gz`, ), ); - }); + }, TEST_TIMEOUT_MILLIS); it('Finds matching version windows', async () => { const release: util.IGcloudSDKRelease | null = await util.queryGcloudSDKRelease( @@ -51,7 +53,7 @@ describe('queryGcloudSDKRelease tests', () => { `https://www.googleapis.com/download/storage/v1/b/cloud-sdk-release/o/google-cloud-sdk-${testUtil.TEST_SDK_VERSION}-windows-x86_64.zip`, ), ); - }); + }, TEST_TIMEOUT_MILLIS); it('Finds matching version darwin', async () => { const release: util.IGcloudSDKRelease | null = await util.queryGcloudSDKRelease( @@ -67,7 +69,7 @@ describe('queryGcloudSDKRelease tests', () => { `https://www.googleapis.com/download/storage/v1/b/cloud-sdk-release/o/google-cloud-sdk-${testUtil.TEST_SDK_VERSION}-darwin-x86_64.tar.gz`, ), ); - }); + }, TEST_TIMEOUT_MILLIS); it('Errors on unsupported OS', async () => { await expect(util.queryGcloudSDKRelease('temple', 'x86_64', testUtil.TEST_SDK_VERSION)).rejects.toThrow( diff --git a/setup-gcloud/__tests__/download-util.test.ts b/setup-gcloud/__tests__/download-util.test.ts index 62c31cb0..8c671195 100644 --- a/setup-gcloud/__tests__/download-util.test.ts +++ b/setup-gcloud/__tests__/download-util.test.ts @@ -20,6 +20,7 @@ import fs from 'fs'; import * as io from '@actions/io'; import * as testUtil from '../src/test-util'; +import * as os from 'os'; const toolDir = testUtil.setupTempDir('tools', 'RUNNER_TOOL_CACHE'); const tempDir = testUtil.setupTempDir('temp', 'RUNNER_TEMP'); @@ -44,6 +45,11 @@ describe('downloadAndExtractTool tests', () => { it( 'Downloads and extracts linux version', async () => { + // skip on windows until this issue is resolved: https://github.com/actions/toolkit/issues/194 + if (os.platform() == 'win32') { + return; + } + const release: clientUtil.IGcloudSDKRelease | null = await clientUtil.queryGcloudSDKRelease( 'linux', 'x86_64', @@ -75,6 +81,11 @@ describe('downloadAndExtractTool tests', () => { it( 'Downloads and extracts darwin version', async () => { + // skip on windows until this issue is resolved: https://github.com/actions/toolkit/issues/194 + if (os.platform() == 'win32') { + return; + } + const release: clientUtil.IGcloudSDKRelease | null = await clientUtil.queryGcloudSDKRelease( 'darwin', 'x86_64', diff --git a/setup-gcloud/__tests__/install-util.test.ts b/setup-gcloud/__tests__/install-util.test.ts index cf4f8b95..2d847a22 100644 --- a/setup-gcloud/__tests__/install-util.test.ts +++ b/setup-gcloud/__tests__/install-util.test.ts @@ -32,7 +32,7 @@ import * as downloadUtil from '../src/download-util'; import * as clientUtil from '../src/client-util'; // Installation can require a bit longer of a timeout. -const TEST_TIMEOUT_MILLIS = 20000; +const TEST_TIMEOUT_MILLIS = 60000; describe('installGcloudSDK tests', () => { beforeAll(async () => { diff --git a/setup-gcloud/dist/client-util.js b/setup-gcloud/dist/client-util.js new file mode 100644 index 00000000..ea18dc42 --- /dev/null +++ b/setup-gcloud/dist/client-util.js @@ -0,0 +1,99 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Contains REST client utility functions. + */ +const rest = __importStar(require("typed-rest-client/RestClient")); +/** + * Queries for a gcloud SDK release. + * + * @param os The OS of the release. + * @param arch The architecutre of the release + * @param version The version of the release. + * @returns The matching release data or else null if not found. + */ +function queryGcloudSDKRelease(os, arch, version) { + return __awaiter(this, void 0, void 0, function* () { + // massage the arch to match gcloud sdk conventions + if (arch == 'x64') { + arch = 'x86_64'; + } + const client = getClient(); + const storageObjects = (yield client.get(formatReleaseURL(os, arch, version))).result; + // If no response was returned this indicates an error. + if (!storageObjects) { + throw new Error('Unable to retreieve cloud sdk version list'); + } + // If an empty response was returned, this indicates no matches found. + if (!storageObjects.items) { + return null; + } + // Get the latest generation that matches the version spec. + const release = storageObjects.items.sort((a, b) => { + if (a.generation > b.generation) { + return 1; + } + return -1; + })[0]; + if (release) { + return { + name: release.name, + url: release.mediaLink, + version: version + }; + } + return null; + }); +} +exports.queryGcloudSDKRelease = queryGcloudSDKRelease; +function formatReleaseURL(os, arch, version) { + let objectName; + switch (os) { + case 'linux': + objectName = `google-cloud-sdk-${version}-linux-${arch}.tar.gz`; + break; + case 'darwin': + objectName = `google-cloud-sdk-${version}-darwin-${arch}.tar.gz`; + break; + case 'win32': + objectName = `google-cloud-sdk-${version}-windows-${arch}.zip`; + break; + default: + throw new Error(`Unexpected OS '${os}'`); + } + return encodeURI(`https://www.googleapis.com/storage/v1/b/cloud-sdk-release/o?prefix=${objectName}`); +} +function getClient() { + return new rest.RestClient('github-actions-setup-gcloud'); +} diff --git a/setup-gcloud/dist/download-util.js b/setup-gcloud/dist/download-util.js new file mode 100644 index 00000000..5274b263 --- /dev/null +++ b/setup-gcloud/dist/download-util.js @@ -0,0 +1,63 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Contains download utility functions. + */ +const toolCache = __importStar(require("@actions/tool-cache")); +/** + * Downloads and extracts the tool at the specified URL. + * + * @url The URL of the tool to be downloaded. + * @returns The path to the locally extracted tool. + */ +function downloadAndExtractTool(url) { + return __awaiter(this, void 0, void 0, function* () { + const downloadPath = yield toolCache.downloadTool(url); + let extractedPath; + if (url.indexOf('.zip') != -1) { + extractedPath = yield toolCache.extractZip(downloadPath); + } + else if (url.indexOf('.tar.gz') != -1) { + extractedPath = yield toolCache.extractTar(downloadPath); + } + else if (url.indexOf('.7z') != -1) { + extractedPath = yield toolCache.extract7z(downloadPath); + } + else { + throw new Error(`Unexpected download archive type, downloadPath: ${downloadPath}`); + } + return extractedPath; + }); +} +exports.downloadAndExtractTool = downloadAndExtractTool; diff --git a/setup-gcloud/dist/gcloud-sdk-test.js b/setup-gcloud/dist/gcloud-sdk-test.js new file mode 100644 index 00000000..8fd2aecb --- /dev/null +++ b/setup-gcloud/dist/gcloud-sdk-test.js @@ -0,0 +1,69 @@ +"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 }); +//import * as rest from 'typed-rest-client/RestClient'; +//import request from 'request-promise-native'; +const request = require('request-promise-native'); +const http = require('http'); +function queryGcloudSDKRelease(osPlat, osArch, versionSpec) { + return __awaiter(this, void 0, void 0, function* () { + let objectName; + switch (osPlat) { + case 'linux': + objectName = `google-cloud-sdk-${versionSpec}-linux-${osArch}.tar.gz`; + break; + case 'darwin': + objectName = `google-cloud-sdk-${versionSpec}-darwin-${osArch}.tar.gz`; + break; + case 'win32': + objectName = `google-cloud-sdk-${versionSpec}-windows-${osArch}.zip`; + break; + default: + throw new Error(`Unexpected OS '${osPlat}'`); + } + let dataUrl = encodeURI(`https://www.googleapis.com/storage/v1/b/cloud-sdk-release/o?prefix='${objectName}'`); + console.log(`\n!!dataUrl: ${dataUrl}\n`); + //let response : rest.IRestResponse = await client.get(dataUrl); + let response = yield request({ + method: 'GET', + uri: dataUrl, + headers: { "Content-Type": " application/json" } + }); + console.log(`\n!!response: ${response}\n`); + // console.log(`\n!!response.statusCode: ${response.statusCode}\n`); + // console.log(`\n!!response.result: ${response.result}\n`); + // console.log("\n!!response.result.keys:\n"); + // Object.keys(response.result!).forEach(key => console.log(`${key}\n`)); + //console.log(`\n!!response.result.kind: ${response.result!.kind}\n`); + //console.log("\n!!response.result.keys: " + Object.keys(response.result) + "\n"); + return null; + // let listReleasesResponse: IStorageObjectListReponse | null = + // (await rest.get(dataUrl)).result || null; + // // get the latest generation that matches the version spec + // if (!listReleasesResponse) { + // throw new Error('Unable to retreieve cloud sdk version list'); + // } + // console.log("\n!!listReleasesResponse: " + typeof listReleasesResponse + "\n"); + // console.log("\n!!listReleasesResponse.keys: " + Object.keys(listReleasesResponse) + "\n"); + // console.log(`\n!!listReleasesResponse.kind: ${listReleasesResponse.kind}\n`); + // let release: IStorageObject | null = listReleasesResponse.items.sort((a,b) => { + // if (a.generation > b.generation) { + // return 1; + // } + // return -1; + // })[0]; + // if (release) { + // return { name: release.name, url: release.mediaLink, version: versionSpec }; + // } + // return null; + }); +} +exports.queryGcloudSDKRelease = queryGcloudSDKRelease; diff --git a/setup-gcloud/dist/install-util.js b/setup-gcloud/dist/install-util.js new file mode 100644 index 00000000..3835f114 --- /dev/null +++ b/setup-gcloud/dist/install-util.js @@ -0,0 +1,64 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Contains installation utility functions. + */ +const toolCache = __importStar(require("@actions/tool-cache")); +const core = __importStar(require("@actions/core")); +const path_1 = __importDefault(require("path")); +const shell = __importStar(require("shelljs")); +/** + * Installs the gcloud SDK into the actions environment. + * + * @param version The version being installed. + * @param gcloudExtPath The extraction path for the gcloud SDK. + * @returns The path of the installed tool. + */ +function installGcloudSDK(version, gcloudExtPath) { + return __awaiter(this, void 0, void 0, function* () { + const toolRoot = path_1.default.join(gcloudExtPath, 'google-cloud-sdk'); + let toolPath = yield toolCache.cacheDir(toolRoot, 'gcloud', version); + toolPath = path_1.default.join(toolPath, 'bin'); + const shellResult = shell.chmod('+x', path_1.default.join(toolPath, 'gcloud')); + if (shellResult.code != 0) { + throw new Error(`Failed to set execute permissions on gcloud binary, error: ${shellResult.stderr}`); + } + core.addPath(toolPath); + return toolPath; + }); +} +exports.installGcloudSDK = installGcloudSDK; diff --git a/setup-gcloud/dist/installer.js b/setup-gcloud/dist/installer.js new file mode 100644 index 00000000..a3678266 --- /dev/null +++ b/setup-gcloud/dist/installer.js @@ -0,0 +1,243 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +// Load tempDirectory before it gets wiped by tool-cache +let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || ''; +const core = __importStar(require("@actions/core")); +const io = __importStar(require("@actions/io")); +const tc = __importStar(require("@actions/tool-cache")); +const restm = __importStar(require("typed-rest-client/RestClient")); +const os = __importStar(require("os")); +const path = __importStar(require("path")); +const semver = __importStar(require("semver")); +let osPlat = os.platform(); +let osArch = os.arch(); +if (!tempDirectory) { + let baseLocation; + if (process.platform === 'win32') { + // On windows use the USERPROFILE env variable + baseLocation = process.env['USERPROFILE'] || 'C:\\'; + } + else { + if (process.platform === 'darwin') { + baseLocation = '/Users'; + } + else { + baseLocation = '/home'; + } + } + tempDirectory = path.join(baseLocation, 'actions', 'temp'); +} +function getNode(versionSpec) { + return __awaiter(this, void 0, void 0, function* () { + // check cache + let toolPath; + toolPath = tc.find('node', versionSpec); + // If not found in cache, download + if (!toolPath) { + let version; + const c = semver.clean(versionSpec) || ''; + // If explicit version + if (semver.valid(c) != null) { + // version to download + version = versionSpec; + } + else { + // query nodejs.org for a matching version + version = yield queryLatestMatch(versionSpec); + if (!version) { + throw new Error(`Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`); + } + // check cache + toolPath = tc.find('node', version); + } + if (!toolPath) { + // download, extract, cache + toolPath = yield acquireNode(version); + } + } + // + // a tool installer initimately knows details about the layout of that tool + // for example, node binary is in the bin folder after the extract on Mac/Linux. + // layouts could change by version, by platform etc... but that's the tool installers job + // + if (osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } + // + // prepend the tools path. instructs the agent to prepend for future tasks + core.addPath(toolPath); + }); +} +exports.getNode = getNode; +function queryLatestMatch(versionSpec) { + return __awaiter(this, void 0, void 0, function* () { + // node offers a json list of versions + let dataFileName; + switch (osPlat) { + case 'linux': + dataFileName = 'linux-' + osArch; + break; + case 'darwin': + dataFileName = 'osx-' + osArch + '-tar'; + break; + case 'win32': + dataFileName = 'win-' + osArch + '-exe'; + break; + default: + throw new Error(`Unexpected OS '${osPlat}'`); + } + let versions = []; + let dataUrl = 'https://nodejs.org/dist/index.json'; + let rest = new restm.RestClient('github-actions-setup-gcloud'); + let nodeVersions = (yield rest.get(dataUrl)).result || []; + nodeVersions.forEach((nodeVersion) => { + // ensure this version supports your os and platform + if (nodeVersion.files.indexOf(dataFileName) >= 0) { + versions.push(nodeVersion.version); + } + }); + // get the latest version that matches the version spec + let version = evaluateVersions(versions, versionSpec); + return version; + }); +} +// TODO - should we just export this from @actions/tool-cache? Lifted directly from there +function evaluateVersions(versions, versionSpec) { + let version = ''; + core.debug(`evaluating ${versions.length} versions`); + versions = versions.sort((a, b) => { + if (semver.gt(a, b)) { + return 1; + } + return -1; + }); + for (let i = versions.length - 1; i >= 0; i--) { + const potential = versions[i]; + const satisfied = semver.satisfies(potential, versionSpec); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; +} +function acquireNode(version) { + return __awaiter(this, void 0, void 0, function* () { + // + // Download - a tool installer intimately knows how to get the tool (and construct urls) + // + version = semver.clean(version) || ''; + let fileName = osPlat == 'win32' + ? 'node-v' + version + '-win-' + os.arch() + : 'node-v' + version + '-' + osPlat + '-' + os.arch(); + let urlFileName = osPlat == 'win32' ? fileName + '.7z' : fileName + '.tar.gz'; + let downloadUrl = 'https://nodejs.org/dist/v' + version + '/' + urlFileName; + let downloadPath; + try { + downloadPath = yield tc.downloadTool(downloadUrl); + } + catch (err) { + if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { + return yield acquireNodeFromFallbackLocation(version); + } + throw err; + } + // + // Extract + // + let extPath; + if (osPlat == 'win32') { + let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe'); + extPath = yield tc.extract7z(downloadPath, undefined, _7zPath); + } + else { + extPath = yield tc.extractTar(downloadPath); + } + // + // Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded + // + let toolRoot = path.join(extPath, fileName); + return yield tc.cacheDir(toolRoot, 'node', version); + }); +} +// For non LTS versions of Node, the files we need (for Windows) are sometimes located +// in a different folder than they normally are for other versions. +// Normally the format is similar to: https://nodejs.org/dist/v5.10.1/node-v5.10.1-win-x64.7z +// In this case, there will be two files located at: +// /dist/v5.10.1/win-x64/node.exe +// /dist/v5.10.1/win-x64/node.lib +// If this is not the structure, there may also be two files located at: +// /dist/v0.12.18/node.exe +// /dist/v0.12.18/node.lib +// This method attempts to download and cache the resources from these alternative locations. +// Note also that the files are normally zipped but in this case they are just an exe +// and lib file in a folder, not zipped. +function acquireNodeFromFallbackLocation(version) { + return __awaiter(this, void 0, void 0, function* () { + // Create temporary folder to download in to + let tempDownloadFolder = 'temp_' + Math.floor(Math.random() * 2000000000); + let tempDir = path.join(tempDirectory, tempDownloadFolder); + yield io.mkdirP(tempDir); + let exeUrl; + let libUrl; + try { + exeUrl = `https://nodejs.org/dist/v${version}/win-${os.arch()}/node.exe`; + libUrl = `https://nodejs.org/dist/v${version}/win-${os.arch()}/node.lib`; + const exePath = yield tc.downloadTool(exeUrl); + yield io.cp(exePath, path.join(tempDir, 'node.exe')); + const libPath = yield tc.downloadTool(libUrl); + yield io.cp(libPath, path.join(tempDir, 'node.lib')); + } + catch (err) { + if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { + exeUrl = `https://nodejs.org/dist/v${version}/node.exe`; + libUrl = `https://nodejs.org/dist/v${version}/node.lib`; + const exePath = yield tc.downloadTool(exeUrl); + yield io.cp(exePath, path.join(tempDir, 'node.exe')); + const libPath = yield tc.downloadTool(libUrl); + yield io.cp(libPath, path.join(tempDir, 'node.lib')); + } + else { + throw err; + } + } + return yield tc.cacheDir(tempDir, 'node', version); + }); +} diff --git a/setup-gcloud/dist/setup-gcloud.js b/setup-gcloud/dist/setup-gcloud.js new file mode 100644 index 00000000..adfd3d84 --- /dev/null +++ b/setup-gcloud/dist/setup-gcloud.js @@ -0,0 +1,104 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const core = __importStar(require("@actions/core")); +const exec_1 = __importDefault(require("@actions/exec")); +const toolCache = __importStar(require("@actions/tool-cache")); +const js_base64_1 = require("js-base64"); +const fs_1 = require("fs"); +const tmp = __importStar(require("tmp")); +const os = __importStar(require("os")); +const clientUtil = __importStar(require("./client-util")); +const downloadUtil = __importStar(require("./download-util")); +const installUtil = __importStar(require("./install-util")); +function run() { + return __awaiter(this, void 0, void 0, function* () { + try { + tmp.setGracefulCleanup(); + const version = core.getInput('version'); + if (!version) { + throw new Error('Missing required parameter: `version`'); + } + const serviceAccountEmail = core.getInput('service_account_email'); + if (!serviceAccountEmail) { + throw new Error('Missing required input: `service_account_email`'); + } + const serviceAccountKey = core.getInput('service_account_key'); + if (!serviceAccountKey) { + throw new Error('Missing required input: `service_account_key`'); + } + // install the gcloud is not already present + let toolPath = toolCache.find('gcloud', version); + if (!toolPath) { + installGcloudSDK(version); + } + // write the service account key to a temporary file + const tmpKeyFilePath = yield new Promise((resolve, reject) => { + tmp.file((err, path, fd, cleanupCallback) => { + if (err) { + reject(err); + } + resolve(path); + }); + }); + yield fs_1.promises.writeFile(tmpKeyFilePath, js_base64_1.Base64.decode(serviceAccountKey)); + // authenticate as the specified service account + yield exec_1.default.exec(`gcloud auth activate-service-account ${serviceAccountEmail} --key-file=${tmpKeyFilePath}`); + } + catch (error) { + core.setFailed(error.message); + } + }); +} +function installGcloudSDK(version) { + return __awaiter(this, void 0, void 0, function* () { + // retreive the release corresponding to the specified version and the current env + const osPlat = os.platform(); + const osArch = os.arch(); + const release = yield clientUtil.queryGcloudSDKRelease(osPlat, osArch, version); + if (!release) { + throw new Error(`Failed to find release, os: ${osPlat} arch: ${osArch} version: ${version}`); + } + // download and extract the release + const extPath = yield downloadUtil.downloadAndExtractTool(release.url); + if (!extPath) { + throw new Error(`Failed to download release, url: ${release.url}`); + } + // install the downloaded release into the github action env + yield installUtil.installGcloudSDK(version, extPath); + }); +} +run(); diff --git a/setup-gcloud/dist/src/client-util.js b/setup-gcloud/dist/src/client-util.js new file mode 100644 index 00000000..ea18dc42 --- /dev/null +++ b/setup-gcloud/dist/src/client-util.js @@ -0,0 +1,99 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Contains REST client utility functions. + */ +const rest = __importStar(require("typed-rest-client/RestClient")); +/** + * Queries for a gcloud SDK release. + * + * @param os The OS of the release. + * @param arch The architecutre of the release + * @param version The version of the release. + * @returns The matching release data or else null if not found. + */ +function queryGcloudSDKRelease(os, arch, version) { + return __awaiter(this, void 0, void 0, function* () { + // massage the arch to match gcloud sdk conventions + if (arch == 'x64') { + arch = 'x86_64'; + } + const client = getClient(); + const storageObjects = (yield client.get(formatReleaseURL(os, arch, version))).result; + // If no response was returned this indicates an error. + if (!storageObjects) { + throw new Error('Unable to retreieve cloud sdk version list'); + } + // If an empty response was returned, this indicates no matches found. + if (!storageObjects.items) { + return null; + } + // Get the latest generation that matches the version spec. + const release = storageObjects.items.sort((a, b) => { + if (a.generation > b.generation) { + return 1; + } + return -1; + })[0]; + if (release) { + return { + name: release.name, + url: release.mediaLink, + version: version + }; + } + return null; + }); +} +exports.queryGcloudSDKRelease = queryGcloudSDKRelease; +function formatReleaseURL(os, arch, version) { + let objectName; + switch (os) { + case 'linux': + objectName = `google-cloud-sdk-${version}-linux-${arch}.tar.gz`; + break; + case 'darwin': + objectName = `google-cloud-sdk-${version}-darwin-${arch}.tar.gz`; + break; + case 'win32': + objectName = `google-cloud-sdk-${version}-windows-${arch}.zip`; + break; + default: + throw new Error(`Unexpected OS '${os}'`); + } + return encodeURI(`https://www.googleapis.com/storage/v1/b/cloud-sdk-release/o?prefix=${objectName}`); +} +function getClient() { + return new rest.RestClient('github-actions-setup-gcloud'); +} diff --git a/setup-gcloud/dist/src/download-util.js b/setup-gcloud/dist/src/download-util.js new file mode 100644 index 00000000..5274b263 --- /dev/null +++ b/setup-gcloud/dist/src/download-util.js @@ -0,0 +1,63 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Contains download utility functions. + */ +const toolCache = __importStar(require("@actions/tool-cache")); +/** + * Downloads and extracts the tool at the specified URL. + * + * @url The URL of the tool to be downloaded. + * @returns The path to the locally extracted tool. + */ +function downloadAndExtractTool(url) { + return __awaiter(this, void 0, void 0, function* () { + const downloadPath = yield toolCache.downloadTool(url); + let extractedPath; + if (url.indexOf('.zip') != -1) { + extractedPath = yield toolCache.extractZip(downloadPath); + } + else if (url.indexOf('.tar.gz') != -1) { + extractedPath = yield toolCache.extractTar(downloadPath); + } + else if (url.indexOf('.7z') != -1) { + extractedPath = yield toolCache.extract7z(downloadPath); + } + else { + throw new Error(`Unexpected download archive type, downloadPath: ${downloadPath}`); + } + return extractedPath; + }); +} +exports.downloadAndExtractTool = downloadAndExtractTool; diff --git a/setup-gcloud/dist/src/install-util.js b/setup-gcloud/dist/src/install-util.js new file mode 100644 index 00000000..3835f114 --- /dev/null +++ b/setup-gcloud/dist/src/install-util.js @@ -0,0 +1,64 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Contains installation utility functions. + */ +const toolCache = __importStar(require("@actions/tool-cache")); +const core = __importStar(require("@actions/core")); +const path_1 = __importDefault(require("path")); +const shell = __importStar(require("shelljs")); +/** + * Installs the gcloud SDK into the actions environment. + * + * @param version The version being installed. + * @param gcloudExtPath The extraction path for the gcloud SDK. + * @returns The path of the installed tool. + */ +function installGcloudSDK(version, gcloudExtPath) { + return __awaiter(this, void 0, void 0, function* () { + const toolRoot = path_1.default.join(gcloudExtPath, 'google-cloud-sdk'); + let toolPath = yield toolCache.cacheDir(toolRoot, 'gcloud', version); + toolPath = path_1.default.join(toolPath, 'bin'); + const shellResult = shell.chmod('+x', path_1.default.join(toolPath, 'gcloud')); + if (shellResult.code != 0) { + throw new Error(`Failed to set execute permissions on gcloud binary, error: ${shellResult.stderr}`); + } + core.addPath(toolPath); + return toolPath; + }); +} +exports.installGcloudSDK = installGcloudSDK; diff --git a/setup-gcloud/dist/src/setup-gcloud.js b/setup-gcloud/dist/src/setup-gcloud.js new file mode 100644 index 00000000..c62e1685 --- /dev/null +++ b/setup-gcloud/dist/src/setup-gcloud.js @@ -0,0 +1,104 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const core = __importStar(require("@actions/core")); +const exec_1 = __importDefault(require("@actions/exec")); +const toolCache = __importStar(require("@actions/tool-cache")); +const base64 = __importStar(require("js-base64")); +const fs_1 = require("fs"); +const tmp = __importStar(require("tmp")); +const os = __importStar(require("os")); +const clientUtil = __importStar(require("./client-util")); +const downloadUtil = __importStar(require("./download-util")); +const installUtil = __importStar(require("./install-util")); +function run() { + return __awaiter(this, void 0, void 0, function* () { + try { + tmp.setGracefulCleanup(); + const version = core.getInput('version'); + if (!version) { + throw new Error('Missing required parameter: `version`'); + } + const serviceAccountEmail = core.getInput('service_account_email'); + if (!serviceAccountEmail) { + throw new Error('Missing required input: `service_account_email`'); + } + const serviceAccountKey = core.getInput('service_account_key'); + if (!serviceAccountKey) { + throw new Error('Missing required input: `service_account_key`'); + } + // install the gcloud is not already present + let toolPath = toolCache.find('gcloud', version); + if (!toolPath) { + installGcloudSDK(version); + } + // write the service account key to a temporary file + const tmpKeyFilePath = yield new Promise((resolve, reject) => { + tmp.file((err, path, fd, cleanupCallback) => { + if (err) { + reject(err); + } + resolve(path); + }); + }); + yield fs_1.promises.writeFile(tmpKeyFilePath, base64.decode(serviceAccountKey)); + // authenticate as the specified service account + yield exec_1.default(`gcloud auth activate-service-account ${serviceAccountEmail} --key-file=${tmpKeyFilePath}`); + } + catch (error) { + core.setFailed(error.message); + } + }); +} +function installGcloudSDK(version) { + return __awaiter(this, void 0, void 0, function* () { + // retreive the release corresponding to the specified version and the current env + const osPlat = os.platform(); + const osArch = os.arch(); + const release = yield clientUtil.queryGcloudSDKRelease(osPlat, osArch, version); + if (!release) { + throw new Error(`Failed to find release, os: ${osPlat} arch: ${osArch} version: ${version}`); + } + // download and extract the release + const extPath = yield downloadUtil.downloadAndExtractTool(release.url); + if (!extPath) { + throw new Error(`Failed to download release, url: ${release.url}`); + } + // install the downloaded release into the github action env + yield installUtil.installGcloudSDK(version, extPath); + }); +} +run(); diff --git a/setup-gcloud/dist/test-util.js b/setup-gcloud/dist/test-util.js new file mode 100644 index 00000000..60327a45 --- /dev/null +++ b/setup-gcloud/dist/test-util.js @@ -0,0 +1,46 @@ +"use strict"; +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * A collection of utility functions for testing. + */ +const path_1 = __importDefault(require("path")); +/** + * Sets up a temporary directory for testing within the `__tests_/runner` + * directory. + * + * @param leafName The leaf directory name. + * @param envName If specified, the name of the environment variable the + * temporary directory path will be saved to. + */ +function setupTempDir(leafName, envName) { + const tempDirPath = path_1.default.join(__dirname, 'runner', Math.random() + .toString(36) + .substring(8), leafName); + if (envName) { + process.env[envName] = tempDirPath; + } + return tempDirPath; +} +exports.setupTempDir = setupTempDir; +/** + * The version of the gcloud SDK being tested against. + */ +exports.TEST_SDK_VERSION = '270.0.0'; diff --git a/setup-gcloud/dist/test.js b/setup-gcloud/dist/test.js new file mode 100644 index 00000000..80dd39e0 --- /dev/null +++ b/setup-gcloud/dist/test.js @@ -0,0 +1,52 @@ +"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()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const restm = __importStar(require("typed-rest-client/RestClient")); +function queryGcloudSDKRelease(osPlat, osArch, versionSpec) { + return __awaiter(this, void 0, void 0, function* () { + let objectName; + switch (osPlat) { + case 'linux': + objectName = `google-cloud-sdk-${versionSpec}-linux-${osArch}.tar.gz`; + break; + case 'darwin': + objectName = `google-cloud-sdk-${versionSpec}-darwin-${osArch}.tar.gz`; + break; + case 'win32': + objectName = `google-cloud-sdk-${versionSpec}-windows-${osArch}.zip`; + break; + default: + throw new Error(`Unexpected OS '${osPlat}'`); + } + let dataUrl = `https://storage.googleapis.com/cloud-sdk-release/o?prefix='${objectName}`; + let rest = new restm.RestClient('github-actions-setup-gcloud'); + let listReleasesResponse = (yield rest.get(dataUrl)).result || null; + // get the latest generation that matches the version spec + let release = listReleasesResponse.items.sort((a, b) => { + if (a.generation > b.generation) { + return 1; + } + return -1; + })[0]; + if (release) { + return { name: release.name, url: release.mediaLink, version: versionSpec }; + } + return null; + }); +} +exports.queryGcloudSDKRelease = queryGcloudSDKRelease;