diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index e203563..4d259de 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,16 +1,41 @@ name: Tests -on: push +on: + push: + branches: ['**'] jobs: test: strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest, macos-latest, windows-latest] version: [latest, 245.0.0] + project: [auto, matrix-education] + exclude: + - os: ubuntu-latest + version: 245.0.0 + project: matrix-education + - os: macos-latest + version: latest + project: matrix-education + - os: macos-latest + version: 245.0.0 + project: auto + - os: macos-latest + version: 245.0.0 + project: matrix-education + - os: windows-latest + version: latest + project: matrix-education + - os: windows-latest + version: 245.0.0 + project: auto + - os: windows-latest + version: 245.0.0 + project: matrix-education fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Setup Node.js 12 uses: actions/setup-node@v1.2.0 with: @@ -19,7 +44,7 @@ jobs: run: node dist/index.js env: INPUT_VERSION: ${{ matrix.version }} - INPUT_PROJECT: ${{ secrets.GCLOUD_PROJECT }} + INPUT_PROJECT: ${{ matrix.project }} INPUT_COMPONENTS: beta INPUT_SERVICE-ACCOUNT-KEY: ${{ secrets.GCLOUD_AUTH }} - name: Test Google Cloud SDK CLI diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a72103 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +## Version 1.0.0 - Stable release +- **feat**: added support for Windows +- **fixed**: inputs are now compared to strings +- **fixed**: project guess using the `service-account-key` input +- **changed**: new install directories + - `/usr/lib/google-cloud-sdk` on Ubuntu runners (overrides the already installed one) + - `$HOME/opt/google-cloud-sdk` on MacOS runners + - `C:\Program Files\google-cloud-sdk` on Windows runners + +## Version 0.1.x - Pre-releases +The versions are now deprecated and should not be used. diff --git a/README.md b/README.md index 6c2fa9a..c00da21 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ -# @mathrix-education/setup-gcloud +# mathrix-education/setup-gcloud + +![Workflow status][workflow] +![Latest release][latest-release] + +[workflow]: https://img.shields.io/github/workflow/status/mathrix-education/setup-gcloud/Tests?style=flat-square +[latest-release]: https://img.shields.io/github/v/release/mathrix-education/setup-gcloud?label=latest%20release&style=flat-square + Install the Google Cloud SDK in your GitHub Actions workflow. **This action is not supported by Google Cloud.** @@ -18,27 +25,29 @@ If the official [@actions/gcloud][2.1] action works perfectly, the fact that it So we chose to create a JavaScript action to fix this problem, also adding additional features, such as Docker authentication with Google Cloud Container Registry. +Update [2019/01/27]: The [GoogleCloudPlatform official GitHub organization][2.4] has released an official +[setup-gcloud][2.5] action. Compared to Mathrix's one, we provide some additional automation tasks, such as project +guessing and automatic Docker Configuration. + [2.1]: https://github.com/actions/gcloud [2.2]: https://github.com/actions/gcloud/tree/master/auth [2.3]: https://github.com/actions/gcloud/tree/master/cli +[2.4]: https://github.com/GoogleCloudPlatform +[2.5]: https://github.com/GoogleCloudPlatform/github-actions/tree/master/setup-gcloud ## Usage ### Supported operating systems -This action currently supports only Mac-OS and Ubuntu based systems. -Indeed, despite our efforts, we have not been able to launch the -installation of the Google Cloud SDK on Windows. - -The supported operating systems matrix is the following: +This action currently supports Ubuntu, Mac-OS and Windows based systems. The supported operating systems matrix is +the following: | Operating system | Status | |------------------|-------| | `ubuntu-latest` | ![3.1] | | `macos-latest` | ![3.1] | -| `windows-latest` | ![3.2] | +| `windows-latest` | ![3.1] | [3.1]: https://img.shields.io/badge/status-supported-brightgreen -[3.2]: https://img.shields.io/badge/status-unsupported-red ### Inputs | Name | Type | Default value | diff --git a/action.yml b/action.yml index 1a2d811..c445a65 100644 --- a/action.yml +++ b/action.yml @@ -11,18 +11,18 @@ inputs: version: description: Google Cloud SDK to use. If left null, will use the latest one. required: false - default: latest + default: 'latest' service-account-key: description: The service account key to use, base64-encoded. required: false project: description: The default Google Cloud project. You can change it later. required: false - default: auto + default: 'auto' components: - description: Install additional components (e.g. beta, gsutils, etc.) + description: Install additional components (e.g. beta, gsutil, etc.) required: false configure-docker: description: Configure Docker to interact with Google Cloud Container Registry. required: false - default: false + default: 'false' diff --git a/dist/index.js b/dist/index.js index cd95547..6f13771 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3903,25 +3903,40 @@ var external_path_ = __webpack_require__(622); var exec = __webpack_require__(986); // CONCATENATED MODULE: ./src/constants.ts +var _a; + const INSTALL_DIRECTORY = 'google-cloud-sdk'; -const WINDOWS_INSTALL_PATH = `C:\\${INSTALL_DIRECTORY}`; -const UBUNTU_INSTALL_PATH = `/home/runner/${INSTALL_DIRECTORY}`; +const UBUNTU_INSTALL_PATH = `/usr/lib/${INSTALL_DIRECTORY}`; +const MACOS_INSTALL_PATH = Object(external_path_.resolve)((_a = process.env.HOME, (_a !== null && _a !== void 0 ? _a : process.cwd())), INSTALL_DIRECTORY); +const WINDOWS_INSTALL_PATH = `C:\\Program Files\\${INSTALL_DIRECTORY}`; // CONCATENATED MODULE: ./src/utils.ts +/** + * Check if the runner is Windows-based. + */ function isWindows() { return process.platform === 'win32'; } +/** + * Check if the runner is MacOS-based. + */ function isMacOS() { return process.platform === 'darwin'; } +/** + * Check if the runner is Ubuntu-based. + */ function isUbuntu() { return process.platform === 'linux'; } -function getCloudSDKFolder() { +/** + * Get the Google Cloud SDK installation directory. + */ +function getCloudSDKDirectory() { if (isWindows()) { return WINDOWS_INSTALL_PATH; } @@ -3929,10 +3944,12 @@ function getCloudSDKFolder() { return UBUNTU_INSTALL_PATH; } else { - const home = process.env.HOME ? process.env.HOME : process.cwd(); - return Object(external_path_.resolve)(home, INSTALL_DIRECTORY); + return MACOS_INSTALL_PATH; } } +/** + * Get the Google Cloud SDK download link + */ function getDownloadLink() { const baseUrl = 'https://dl.google.com/dl/cloudsdk/channels/rapid'; const version = Object(core.getInput)('version'); @@ -3954,9 +3971,18 @@ function getDownloadLink() { return `${baseUrl}/downloads/google-cloud-sdk-${version}-linux-x86_64.tar.gz`; } } +/** + * Execute a gcloud command + * @param args The gcloud args + * @param options The command options + */ async function gcloud(args, options = undefined) { - const gcloudPath = Object(external_path_.resolve)(getCloudSDKFolder(), 'bin', 'gcloud' + (isWindows() ? '.cmd' : '')); - args.unshift('--quiet'); + let gcloudPath = Object(external_path_.resolve)(getCloudSDKDirectory(), 'bin', 'gcloud' + (isWindows() ? '.cmd' : '')); + if (isWindows()) { + // Windows installation directory is C:\Program Files and thus need to be escaped + gcloudPath = gcloudPath.replace(getCloudSDKDirectory(), `"${getCloudSDKDirectory()}"`); + } + args.unshift('--quiet'); // Add quiet to all commands await Object(exec.exec)(gcloudPath, args, options); } @@ -3971,13 +3997,12 @@ async function gcloud(args, options = undefined) { async function authenticate() { // If service account key is not provided, skip the authentication if (!Object(core.getInput)('service-account-key')) { - Object(core.warning)('No service-account-key input was passed.' + - 'If it is intentional, you can safely ignore this warning.'); + Object(core.warning)('No service-account-key input was passed. If it is intentional, you can safely ignore this warning.'); return; } // Write the service account key const serviceAccountKeyBase64 = Object(core.getInput)('service-account-key'); - const serviceAccountKeyJson = Buffer.from(serviceAccountKeyBase64, 'base64'); + const serviceAccountKeyJson = Buffer.from(serviceAccountKeyBase64, 'base64').toString(); const serviceAccountKeyPath = Object(external_path_.resolve)(process.cwd(), 'gcloud.json'); Object(external_fs_.writeFileSync)(serviceAccountKeyPath, serviceAccountKeyJson); // Activate the service account @@ -3986,38 +4011,67 @@ async function authenticate() { 'activate-service-account', `--key-file=${serviceAccountKeyPath}`, ]); + // Remove the service account key + Object(external_fs_.unlinkSync)(serviceAccountKeyPath); + // Configure the default project + if (Object(core.getInput)('project') === 'auto' && + Object(core.getInput)('service-account-key') !== '') { + // Project will be read from the service account key + const serviceAccountKey = JSON.parse(serviceAccountKeyJson.toString()); + if (serviceAccountKey.hasOwnProperty('project_id')) { + // If key has a project_id field, use it to set the default project + await gcloud(['config', 'set', 'project', serviceAccountKey.project_id]); + } + else { + Object(core.warning)('You gave a service account key, but it does not have the "project_id" key. Thus, the default project ' + + 'cannot be configured. Your service account key might malformed.'); + } + } + else if (!['', 'none', 'auto'].includes(Object(core.getInput)('project'))) { + // Project was passed as input + await gcloud(['config', 'set', 'project', Object(core.getInput)('project')]); + } // Configure Docker if necessary - if (Object(core.getInput)('configure-docker')) { + if (Object(core.getInput)('configure-docker') === 'true') { await gcloud(['--quiet', 'auth', 'configure-docker']); } - // Remove the service account key - Object(external_fs_.unlinkSync)(serviceAccountKeyPath); } // EXTERNAL MODULE: ./node_modules/@actions/tool-cache/lib/tool-cache.js var tool_cache = __webpack_require__(533); -// EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js -var io = __webpack_require__(1); - // CONCATENATED MODULE: ./src/download.ts + + /** * Download the Google Cloud SDK archive. */ async function download() { const downloadLink = getDownloadLink(); const downloadPath = await Object(tool_cache.downloadTool)(downloadLink); - const extractionPath = Object(external_path_.resolve)(getCloudSDKFolder(), '..'); - await Object(io.mkdirP)(getCloudSDKFolder()); + const extractionPath = Object(external_path_.resolve)(getCloudSDKDirectory(), '..'); if (downloadLink.endsWith('.zip')) { + // Windows: simply extract zip file await Object(tool_cache.extractZip)(downloadPath, extractionPath); } else if (downloadLink.endsWith('.tar.gz')) { - await Object(tool_cache.extractTar)(downloadPath, extractionPath); + if (isUbuntu()) { + // Ubuntu: Remove the existing installation of Google Cloud SDK + await Object(exec.exec)(`sudo rm -rf ${UBUNTU_INSTALL_PATH}`); + await Object(exec.exec)(`sudo tar -xf ${downloadPath} -C ${extractionPath}`); + } + else { + // MacOS: simply extract tar.gz file + await Object(tool_cache.extractTar)(downloadPath, extractionPath); + } + } + else { + // Should never be reached + Object(core.setFailed)(`Unexpected extension (expected zip or tar.gz), but got ${downloadLink}`); } } @@ -4031,11 +4085,11 @@ var external_child_process_ = __webpack_require__(129); /** - * Setup the Google Cloud SDK. + * Setup the Google Cloud SDK by running the install script. */ async function setup() { const installScriptExtension = isWindows() ? 'bat' : 'sh'; - const installScript = Object(external_path_.resolve)(getCloudSDKFolder(), `install.${installScriptExtension}`); + const installScript = Object(external_path_.resolve)(getCloudSDKDirectory(), `install.${installScriptExtension}`); const args = [ '--usage-reporting=false', '--command-completion=false', @@ -4043,30 +4097,32 @@ async function setup() { '--usage-reporting=false', '--quiet', ]; - if (Object(core.getInput)('components')) { + if (Object(core.getInput)('components') !== '') { args.push('--additional-components=' + Object(core.getInput)('components')); } - if (isWindows()) { - // @actions/exec does not exit on windows - Object(external_child_process_.execSync)(`"${installScript}" ${args.join(' ')}`, { stdio: 'inherit' }); + if (isUbuntu()) { + /* + * On Ubuntu, since we extracted the SDK to a protected directory, we have also to run the installer as root, which + * has side-effects on the user $HOME folder. + */ + await Object(exec.exec)(`sudo ${installScript}`, args); + const user = process.env.USER || ''; + const home = process.env.HOME || ''; + await Object(exec.exec)(`sudo chown -R ${user} ${home}`); } - else { + else if (isMacOS()) { + // On MacOS, we simply have to run the install script await Object(exec.exec)(installScript, args); } - if (Object(core.getInput)('project') === 'auto' && - Object(core.getInput)('service-account-key')) { - // Project will be read from the service account key - const buffer = new Buffer(Object(core.getInput)('service-account-key'), 'base64'); - const serviceAccountKey = JSON.parse(buffer.toString()); - if (serviceAccountKey.hasOwnProperty('project_id')) { - await gcloud(['config', 'set', 'project', serviceAccountKey.project_id]); - } + else if (isWindows()) { + // @actions/exec does not exit on windows + Object(external_child_process_.execSync)(`"${installScript}" ${args.join(' ')}`, { stdio: 'inherit' }); } - else if (Object(core.getInput)('project') !== 'none') { - // Project was passed as input - await gcloud(['config', 'set', 'project', Object(core.getInput)('project')]); + else { + // Should never be reached + Object(core.setFailed)(`Unexpected os platform, got: ${process.platform}`); } - const binPath = Object(external_path_.resolve)(getCloudSDKFolder(), 'bin'); + const binPath = Object(external_path_.resolve)(getCloudSDKDirectory(), 'bin'); Object(core.addPath)(binPath); } @@ -4076,16 +4132,11 @@ async function setup() { - /** * Install the Google Cloud SDK. */ async function install() { try { - // Currently, Windows is disabled because the installer does not work properly - if (isWindows()) { - Object(core.error)('This action does not support Windows for now. PR are welcome!'); - } await download(); await setup(); await authenticate(); diff --git a/package-lock.json b/package-lock.json index cdfc3ed..f1aecb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@mathrix-education/setup-gcloud", - "version": "0.1.2", + "version": "0.1.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/authenticate.ts b/src/authenticate.ts index 3ec3ed0..8b3fc91 100644 --- a/src/authenticate.ts +++ b/src/authenticate.ts @@ -10,15 +10,17 @@ export async function authenticate(): Promise { // If service account key is not provided, skip the authentication if (!core.getInput('service-account-key')) { core.warning( - 'No service-account-key input was passed.' + - 'If it is intentional, you can safely ignore this warning.', + 'No service-account-key input was passed. If it is intentional, you can safely ignore this warning.', ); return; } // Write the service account key const serviceAccountKeyBase64 = core.getInput('service-account-key'); - const serviceAccountKeyJson = Buffer.from(serviceAccountKeyBase64, 'base64'); + const serviceAccountKeyJson = Buffer.from( + serviceAccountKeyBase64, + 'base64', + ).toString(); const serviceAccountKeyPath = resolve(process.cwd(), 'gcloud.json'); writeFileSync(serviceAccountKeyPath, serviceAccountKeyJson); @@ -29,11 +31,35 @@ export async function authenticate(): Promise { `--key-file=${serviceAccountKeyPath}`, ]); + // Remove the service account key + unlinkSync(serviceAccountKeyPath); + + // Configure the default project + if ( + core.getInput('project') === 'auto' && + core.getInput('service-account-key') !== '' + ) { + // Project will be read from the service account key + const serviceAccountKey: { project_id: string } = JSON.parse( + serviceAccountKeyJson.toString(), + ); + + if (serviceAccountKey.hasOwnProperty('project_id')) { + // If key has a project_id field, use it to set the default project + await gcloud(['config', 'set', 'project', serviceAccountKey.project_id]); + } else { + core.warning( + 'You gave a service account key, but it does not have the "project_id" key. Thus, the default project ' + + 'cannot be configured. Your service account key might malformed.', + ); + } + } else if (!['', 'none', 'auto'].includes(core.getInput('project'))) { + // Project was passed as input + await gcloud(['config', 'set', 'project', core.getInput('project')]); + } + // Configure Docker if necessary - if (core.getInput('configure-docker')) { + if (core.getInput('configure-docker') === 'true') { await gcloud(['--quiet', 'auth', 'configure-docker']); } - - // Remove the service account key - unlinkSync(serviceAccountKeyPath); } diff --git a/src/constants.ts b/src/constants.ts index 36cfe64..a306de2 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,3 +1,9 @@ +import { resolve } from 'path'; + export const INSTALL_DIRECTORY = 'google-cloud-sdk'; -export const WINDOWS_INSTALL_PATH = `C:\\${INSTALL_DIRECTORY}`; -export const UBUNTU_INSTALL_PATH = `/home/runner/${INSTALL_DIRECTORY}`; +export const UBUNTU_INSTALL_PATH = `/usr/lib/${INSTALL_DIRECTORY}`; +export const MACOS_INSTALL_PATH = resolve( + process.env.HOME ?? process.cwd(), + INSTALL_DIRECTORY, +); +export const WINDOWS_INSTALL_PATH = `C:\\Program Files\\${INSTALL_DIRECTORY}`; diff --git a/src/download.ts b/src/download.ts index 0983331..dcea399 100644 --- a/src/download.ts +++ b/src/download.ts @@ -1,7 +1,10 @@ +import * as core from '@actions/core'; +import * as exec from '@actions/exec'; +import * as io from '@actions/io'; import * as tc from '@actions/tool-cache'; -import { getCloudSDKFolder, getDownloadLink } from './utils'; import { resolve } from 'path'; -import * as io from '@actions/io'; +import { MACOS_INSTALL_PATH, UBUNTU_INSTALL_PATH } from './constants'; +import { getCloudSDKDirectory, getDownloadLink, isUbuntu } from './utils'; /** * Download the Google Cloud SDK archive. @@ -9,13 +12,24 @@ import * as io from '@actions/io'; export async function download(): Promise { const downloadLink = getDownloadLink(); const downloadPath = await tc.downloadTool(downloadLink); - const extractionPath = resolve(getCloudSDKFolder(), '..'); - - await io.mkdirP(getCloudSDKFolder()); + const extractionPath = resolve(getCloudSDKDirectory(), '..'); if (downloadLink.endsWith('.zip')) { + // Windows: simply extract zip file await tc.extractZip(downloadPath, extractionPath); } else if (downloadLink.endsWith('.tar.gz')) { - await tc.extractTar(downloadPath, extractionPath); + if (isUbuntu()) { + // Ubuntu: Remove the existing installation of Google Cloud SDK + await exec.exec(`sudo rm -rf ${UBUNTU_INSTALL_PATH}`); + await exec.exec(`sudo tar -xf ${downloadPath} -C ${extractionPath}`); + } else { + // MacOS: simply extract tar.gz file + await tc.extractTar(downloadPath, extractionPath); + } + } else { + // Should never be reached + core.setFailed( + `Unexpected extension (expected zip or tar.gz), but got ${downloadLink}`, + ); } } diff --git a/src/install.ts b/src/install.ts index 69bfbd3..f8490d8 100644 --- a/src/install.ts +++ b/src/install.ts @@ -2,20 +2,12 @@ import * as core from '@actions/core'; import { authenticate } from './authenticate'; import { download } from './download'; import { setup } from './setup'; -import { isWindows } from './utils'; /** * Install the Google Cloud SDK. */ export async function install(): Promise { try { - // Currently, Windows is disabled because the installer does not work properly - if (isWindows()) { - core.error( - 'This action does not support Windows for now. PR are welcome!', - ); - } - await download(); await setup(); await authenticate(); diff --git a/src/setup.ts b/src/setup.ts index 58249b9..4fc4fb9 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -2,15 +2,15 @@ import * as core from '@actions/core'; import * as exec from '@actions/exec'; import { execSync } from 'child_process'; import { resolve } from 'path'; -import { gcloud, getCloudSDKFolder, isWindows } from './utils'; +import { getCloudSDKDirectory, isMacOS, isUbuntu, isWindows } from './utils'; /** - * Setup the Google Cloud SDK. + * Setup the Google Cloud SDK by running the install script. */ export async function setup(): Promise { const installScriptExtension = isWindows() ? 'bat' : 'sh'; const installScript = resolve( - getCloudSDKFolder(), + getCloudSDKDirectory(), `install.${installScriptExtension}`, ); @@ -22,35 +22,31 @@ export async function setup(): Promise { '--quiet', ]; - if (core.getInput('components')) { + if (core.getInput('components') !== '') { args.push('--additional-components=' + core.getInput('components')); } - if (isWindows()) { + if (isUbuntu()) { + /* + * On Ubuntu, since we extracted the SDK to a protected directory, we have also to run the installer as root, which + * has side-effects on the user $HOME folder. + */ + await exec.exec(`sudo ${installScript}`, args); + + const user = process.env.USER || ''; + const home = process.env.HOME || ''; + await exec.exec(`sudo chown -R ${user} ${home}`); + } else if (isMacOS()) { + // On MacOS, we simply have to run the install script + await exec.exec(installScript, args); + } else if (isWindows()) { // @actions/exec does not exit on windows execSync(`"${installScript}" ${args.join(' ')}`, { stdio: 'inherit' }); } else { - await exec.exec(installScript, args); - } - - if ( - core.getInput('project') === 'auto' && - core.getInput('service-account-key') - ) { - // Project will be read from the service account key - const buffer = new Buffer(core.getInput('service-account-key'), 'base64'); - const serviceAccountKey: { project_id: string } = JSON.parse( - buffer.toString(), - ); - - if (serviceAccountKey.hasOwnProperty('project_id')) { - await gcloud(['config', 'set', 'project', serviceAccountKey.project_id]); - } - } else if (core.getInput('project') !== 'none') { - // Project was passed as input - await gcloud(['config', 'set', 'project', core.getInput('project')]); + // Should never be reached + core.setFailed(`Unexpected os platform, got: ${process.platform}`); } - const binPath = resolve(getCloudSDKFolder(), 'bin'); + const binPath = resolve(getCloudSDKDirectory(), 'bin'); core.addPath(binPath); } diff --git a/src/utils.ts b/src/utils.ts index 40073a6..34438d1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,35 +1,51 @@ import * as core from '@actions/core'; import * as exec from '@actions/exec'; +import { ExecOptions } from '@actions/exec/lib/interfaces'; import { resolve } from 'path'; import { INSTALL_DIRECTORY, + MACOS_INSTALL_PATH, UBUNTU_INSTALL_PATH, WINDOWS_INSTALL_PATH, } from './constants'; +/** + * Check if the runner is Windows-based. + */ export function isWindows(): boolean { return process.platform === 'win32'; } +/** + * Check if the runner is MacOS-based. + */ export function isMacOS(): boolean { return process.platform === 'darwin'; } +/** + * Check if the runner is Ubuntu-based. + */ export function isUbuntu(): boolean { return process.platform === 'linux'; } -export function getCloudSDKFolder(): string { +/** + * Get the Google Cloud SDK installation directory. + */ +export function getCloudSDKDirectory(): string { if (isWindows()) { return WINDOWS_INSTALL_PATH; } else if (isUbuntu()) { return UBUNTU_INSTALL_PATH; } else { - const home = process.env.HOME ? process.env.HOME : process.cwd(); - return resolve(home, INSTALL_DIRECTORY); + return MACOS_INSTALL_PATH; } } +/** + * Get the Google Cloud SDK download link + */ export function getDownloadLink(): string { const baseUrl = 'https://dl.google.com/dl/cloudsdk/channels/rapid'; const version = core.getInput('version'); @@ -51,17 +67,30 @@ export function getDownloadLink(): string { } } +/** + * Execute a gcloud command + * @param args The gcloud args + * @param options The command options + */ export async function gcloud( args: string[], - options: any = undefined, + options: ExecOptions | undefined = undefined, ): Promise { - const gcloudPath = resolve( - getCloudSDKFolder(), + let gcloudPath = resolve( + getCloudSDKDirectory(), 'bin', 'gcloud' + (isWindows() ? '.cmd' : ''), ); - args.unshift('--quiet'); + if (isWindows()) { + // Windows installation directory is C:\Program Files and thus need to be escaped + gcloudPath = gcloudPath.replace( + getCloudSDKDirectory(), + `"${getCloudSDKDirectory()}"`, + ); + } + + args.unshift('--quiet'); // Add quiet to all commands await exec.exec(gcloudPath, args, options); }