Skip to content

Commit 8b52d43

Browse files
authored
Use getExecOutput for gcloud commands (#279)
Crafting our own buffers is more efficient, but we have to actually flush those buffers before reading, to ensure we have 100% of the output. This is error prone and incredibly verbose. Using `getExecOutput` instead sacrifices a negligible performance overhead for a much less callback-y design.
1 parent 07a7b6c commit 8b52d43

File tree

3 files changed

+38
-56
lines changed

3 files changed

+38
-56
lines changed

.github/workflows/unit.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
name: 'unit'
1818
runs-on: '${{ matrix.os }}'
1919
strategy:
20+
fail-fast: false
2021
matrix:
2122
os:
2223
- 'ubuntu-latest'

src/deploy-cloudrun.ts

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import * as core from '@actions/core';
18-
import { exec } from '@actions/exec';
18+
import { getExecOutput } from '@actions/exec';
1919
import * as toolCache from '@actions/tool-cache';
2020
import * as setupGcloud from '@google-github-actions/setup-cloud-sdk';
2121
import path from 'path';
@@ -186,37 +186,20 @@ export async function run(): Promise<void> {
186186
}
187187

188188
const toolCommand = setupGcloud.getToolCommand();
189+
const options = { silent: true };
190+
const commandString = `${toolCommand} ${cmd.join(' ')}`;
191+
core.info(`Running: ${commandString}`);
189192

190-
// Get output of gcloud cmd.
191-
let output = '';
192-
const stdout = (data: Buffer): void => {
193-
output += data.toString();
194-
};
195-
let errOutput = '';
196-
const stderr = (data: Buffer): void => {
197-
errOutput += data.toString();
198-
};
199-
200-
const options = {
201-
listeners: {
202-
stderr,
203-
stdout,
204-
},
205-
silent: true,
206-
};
207-
core.info(`running: ${toolCommand} ${cmd.join(' ')}`);
208193
// Run gcloud cmd.
209-
try {
210-
await exec(toolCommand, cmd, options);
211-
// Set url as output.
212-
setUrlOutput(output + errOutput);
213-
} catch (error) {
214-
if (errOutput) {
215-
throw new Error(errOutput);
216-
} else {
217-
throw new Error(convertUnknown(error));
218-
}
194+
const output = await getExecOutput(toolCommand, cmd, options);
195+
if (output.exitCode !== 0) {
196+
const errMsg = output.stderr || `command exited ${output.exitCode}, but stderr had no output`;
197+
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
219198
}
199+
200+
// gcloud outputs status information to stderr.
201+
// TODO: update this to use JSON or YAML machine-readable output instead.
202+
setUrlOutput(output.stdout + output.stderr);
220203
} catch (error) {
221204
core.setFailed(convertUnknown(error));
222205
}

tests/e2e.test.ts

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import { expect } from 'chai';
1818
import { GoogleAuth } from 'google-auth-library';
19-
import { exec } from '@actions/exec';
19+
import { getExecOutput } from '@actions/exec';
2020
import * as _ from 'lodash';
2121
import 'mocha';
2222
import { run_v1 } from 'googleapis';
@@ -52,18 +52,7 @@ describe('E2E tests', function () {
5252
}
5353
toolCommand = 'gcloud';
5454
if (SERVICE) {
55-
sleep(10000);
5655
// get Service yaml
57-
let output = '';
58-
const stdout = (data: Buffer): void => {
59-
output += data.toString();
60-
};
61-
const options = {
62-
listeners: {
63-
stdout,
64-
},
65-
silent: true,
66-
};
6756
let cmd = [
6857
'run',
6958
'services',
@@ -76,8 +65,17 @@ describe('E2E tests', function () {
7665
'--region',
7766
'us-central1',
7867
];
79-
await exec(toolCommand, cmd, options);
80-
service = yaml.load(output) as run_v1.Schema$Service;
68+
69+
const options = { silent: true };
70+
const commandString = `${toolCommand} ${cmd.join(' ')}`;
71+
const output = await getExecOutput(toolCommand, cmd, options);
72+
if (output.exitCode !== 0) {
73+
const errMsg =
74+
output.stderr || `command exited ${output.exitCode}, but stderr had no output`;
75+
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
76+
}
77+
78+
service = yaml.load(output.stdout) as run_v1.Schema$Service;
8179
if (!service) console.log('no service found');
8280
}
8381
});
@@ -207,17 +205,8 @@ describe('E2E tests', function () {
207205
let attempt = 0;
208206
let revisions = [];
209207
while (attempt < max && revisions.length < parseInt(COUNT)) {
210-
await sleep(1000);
211-
let output = '';
212-
const stdout = (data: Buffer): void => {
213-
output += data.toString();
214-
};
215-
const options = {
216-
listeners: {
217-
stdout,
218-
},
219-
silent: true,
220-
};
208+
await sleep(1000 * attempt);
209+
221210
let cmd = [
222211
'run',
223212
'revisions',
@@ -231,8 +220,17 @@ describe('E2E tests', function () {
231220
'--region',
232221
'us-central1',
233222
];
234-
await exec(toolCommand, cmd, options);
235-
revisions = JSON.parse(output);
223+
224+
const options = { silent: true };
225+
const commandString = `${toolCommand} ${cmd.join(' ')}`;
226+
227+
const output = await getExecOutput(toolCommand, cmd, options);
228+
if (output.exitCode !== 0) {
229+
const errMsg =
230+
output.stderr || `command exited ${output.exitCode}, but stderr had no output`;
231+
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
232+
}
233+
revisions = JSON.parse(output.stdout);
236234
}
237235

238236
expect(revisions.length).to.equal(parseInt(COUNT));

0 commit comments

Comments
 (0)