Skip to content

Commit e37d731

Browse files
authored
Always update traffic if tag_traffic or revision_traffic is given (#535)
Closes #533 This could potentially be a breaking change for anyone using a step that had an `image` or `source` with a `tag_traffic` or `revision_traffic`. Previously this would not re-deploy, but now it does.
1 parent 7a7a472 commit e37d731

File tree

5 files changed

+136
-96
lines changed

5 files changed

+136
-96
lines changed

.github/workflows/integration.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ jobs:
113113
env_vars_update_strategy: 'overwrite'
114114
secrets: /api/secrets/my-secret=${{ vars.SECRET_NAME }}:latest
115115
secrets_update_strategy: 'overwrite'
116+
to_revision: 'LATEST=100'
116117

117118
- name: 'Run re-deploy tests'
118119
run: 'npm run e2e-tests'
@@ -201,6 +202,7 @@ jobs:
201202
with:
202203
image: 'gcr.io/cloudrun/hello'
203204
service: '${{ env.SERVICE_NAME }}'
205+
to_revision: 'LATEST=100'
204206

205207
- name: 'Run re-deploy tests'
206208
run: 'npm run e2e-tests' # Check that config isn't overwritten

README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ jobs:
8181
code](https://cloud.google.com/run/docs/deploying-source-code).
8282

8383
- <a name="suffix"></a><a href="#user-content-suffix"><code>suffix</code></a>: _(Optional)_ String suffix to append to the revision name. Revision names always start
84-
with the service name automatically. For example, specifying 'v1' for a
85-
service named 'helloworld', would lead to a revision named
86-
'helloworld-v1'.
84+
with the service name automatically. For example, specifying `v1` for a
85+
service named `helloworld`, would lead to a revision named
86+
`helloworld-v1`. This option is only applies to services.
8787

8888
- <a name="env_vars"></a><a href="#user-content-env_vars"><code>env_vars</code></a>: _(Optional)_ List of environment variables that should be set in the environment.
8989
These are comma-separated or newline-separated `KEY=VALUE`. Keys or values
@@ -179,7 +179,8 @@ jobs:
179179

180180
Setting this to `true` will skip adding these special labels.
181181

182-
- <a name="tag"></a><a href="#user-content-tag"><code>tag</code></a>: _(Optional)_ Traffic tag to assign to the newly-created revision.
182+
- <a name="tag"></a><a href="#user-content-tag"><code>tag</code></a>: _(Optional)_ Traffic tag to assign to the newly-created revision. This option is only
183+
applies to services.
183184

184185
- <a name="timeout"></a><a href="#user-content-timeout"><code>timeout</code></a>: _(Optional)_ Maximum request execution time, specified as a duration like "10m5s" for
185186
ten minutes and 5 seconds.
@@ -202,11 +203,12 @@ jobs:
202203

203204
Please note, this GitHub Action does not parse or validate the flags. You
204205
are responsible for making sure the flags are available on the gcloud
205-
version and subcommand. When using `tag_traffic` or `revision_traffic`,
206-
the subcommand is `gcloud run services update-traffic`. For all other
207-
values, the subcommand is `gcloud run deploy`.
206+
version and subcommand. The provided flags will be appended to the
207+
`deploy` command. When `revision_traffic` or `tag_traffic` are set, the
208+
flags will also be appended to the subsequent `update-traffic` command.
208209

209-
- <a name="no_traffic"></a><a href="#user-content-no_traffic"><code>no_traffic</code></a>: _(Optional, default: `false`)_ If true, the newly deployed revision will not receive traffic.
210+
- <a name="no_traffic"></a><a href="#user-content-no_traffic"><code>no_traffic</code></a>: _(Optional, default: `false`)_ If true, the newly deployed revision will not receive traffic. This option
211+
is only applies to services.
210212

211213
- <a name="revision_traffic"></a><a href="#user-content-revision_traffic"><code>revision_traffic</code></a>: _(Optional)_ Comma-separated list of revision traffic assignments.
212214

@@ -218,14 +220,16 @@ jobs:
218220
with:
219221
revision_traffic: 'LATEST=100'
220222

221-
This is mutually-exclusive with `tag_traffic`.
223+
This is mutually-exclusive with `tag_traffic`. This option is only applies
224+
to services.
222225

223226
- <a name="tag_traffic"></a><a href="#user-content-tag_traffic"><code>tag_traffic</code></a>: _(Optional)_ Comma-separated list of tag traffic assignments.
224227

225228
with:
226229
tag_traffic: 'my-tag=10' # percentage
227230

228-
This is mutually-exclusive with `revision_traffic`.
231+
This is mutually-exclusive with `revision_traffic`. This option is only
232+
applies to services.
229233

230234
- <a name="project_id"></a><a href="#user-content-project_id"><code>project_id</code></a>: _(Optional)_ ID of the Google Cloud project in which to deploy the service.
231235

action.yml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ inputs:
6161
suffix:
6262
description: |-
6363
String suffix to append to the revision name. Revision names always start
64-
with the service name automatically. For example, specifying 'v1' for a
65-
service named 'helloworld', would lead to a revision named
66-
'helloworld-v1'.
64+
with the service name automatically. For example, specifying `v1` for a
65+
service named `helloworld`, would lead to a revision named
66+
`helloworld-v1`. This option is only applies to services.
6767
required: false
6868

6969
env_vars:
@@ -186,7 +186,8 @@ inputs:
186186

187187
tag:
188188
description: |-
189-
Traffic tag to assign to the newly-created revision.
189+
Traffic tag to assign to the newly-created revision. This option is only
190+
applies to services.
190191
required: false
191192

192193
timeout:
@@ -215,14 +216,15 @@ inputs:
215216
216217
Please note, this GitHub Action does not parse or validate the flags. You
217218
are responsible for making sure the flags are available on the gcloud
218-
version and subcommand. When using `tag_traffic` or `revision_traffic`,
219-
the subcommand is `gcloud run services update-traffic`. For all other
220-
values, the subcommand is `gcloud run deploy`.
219+
version and subcommand. The provided flags will be appended to the
220+
`deploy` command. When `revision_traffic` or `tag_traffic` are set, the
221+
flags will also be appended to the subsequent `update-traffic` command.
221222
required: false
222223

223224
no_traffic:
224225
description: |-
225-
If true, the newly deployed revision will not receive traffic.
226+
If true, the newly deployed revision will not receive traffic. This option
227+
is only applies to services.
226228
default: 'false'
227229
required: false
228230

@@ -238,7 +240,8 @@ inputs:
238240
with:
239241
revision_traffic: 'LATEST=100'
240242
241-
This is mutually-exclusive with `tag_traffic`.
243+
This is mutually-exclusive with `tag_traffic`. This option is only applies
244+
to services.
242245
required: false
243246

244247
tag_traffic:
@@ -248,7 +251,8 @@ inputs:
248251
with:
249252
tag_traffic: 'my-tag=10' # percentage
250253
251-
This is mutually-exclusive with `revision_traffic`.
254+
This is mutually-exclusive with `revision_traffic`. This option is only
255+
applies to services.
252256
required: false
253257

254258
project_id:

src/main.ts

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ export async function run(): Promise<void> {
119119
const skipDefaultLabels = parseBoolean(getInput('skip_default_labels'));
120120
const flags = getInput('flags');
121121

122-
let responseType = ResponseTypes.DEPLOY; // Default response type for output parsing
123-
let cmd;
122+
let deployCmd: string[] = [];
124123

125124
// Throw errors if inputs aren't valid
126125
if (revTraffic && tagTraffic) {
@@ -153,23 +152,15 @@ export async function run(): Promise<void> {
153152
}
154153

155154
// Find base command
156-
if (revTraffic || tagTraffic) {
157-
// Set response type for output parsing
158-
responseType = ResponseTypes.UPDATE_TRAFFIC;
159-
160-
// Update traffic
161-
cmd = ['run', 'services', 'update-traffic', service];
162-
if (revTraffic) cmd.push('--to-revisions', revTraffic);
163-
if (tagTraffic) cmd.push('--to-tags', tagTraffic);
164-
} else if (metadata) {
155+
if (metadata) {
165156
const contents = await readFile(metadata, 'utf8');
166157
const parsed = parseYAML(contents);
167158

168159
const kind = parsed?.kind;
169160
if (kind === 'Service') {
170-
cmd = ['run', 'services', 'replace', metadata];
161+
deployCmd = ['run', 'services', 'replace', metadata];
171162
} else if (kind === 'Job') {
172-
cmd = ['run', 'jobs', 'replace', metadata];
163+
deployCmd = ['run', 'jobs', 'replace', metadata];
173164
} else {
174165
throw new Error(`Unkown metadata type "${kind}", expected "Job" or "Service"`);
175166
}
@@ -179,80 +170,92 @@ export async function run(): Promise<void> {
179170
`not covered by the semver backwards compatibility guarantee.`,
180171
);
181172

182-
cmd = ['run', 'jobs', 'deploy', job];
173+
deployCmd = ['run', 'jobs', 'deploy', job];
183174

184175
if (image) {
185-
cmd.push('--image', image);
176+
deployCmd.push('--image', image);
186177
} else if (source) {
187-
cmd.push('--source', source);
178+
deployCmd.push('--source', source);
188179
}
189180

190181
// Set optional flags from inputs
191-
setEnvVarsFlags(cmd, envVars, envVarsFile, envVarsUpdateStrategy);
192-
setSecretsFlags(cmd, secrets, secretsUpdateStrategy);
182+
setEnvVarsFlags(deployCmd, envVars, envVarsFile, envVarsUpdateStrategy);
183+
setSecretsFlags(deployCmd, secrets, secretsUpdateStrategy);
193184

194185
// There is no --update-secrets flag on jobs, but there will be in the
195186
// future. At that point, we can remove this.
196-
const idx = cmd.indexOf('--update-secrets');
187+
const idx = deployCmd.indexOf('--update-secrets');
197188
if (idx >= 0) {
198189
logWarning(
199190
`Cloud Run does not allow updating secrets on jobs, ignoring ` +
200191
`"secrets_update_strategy" value of "merge"`,
201192
);
202-
cmd[idx] = '--set-secrets';
193+
deployCmd[idx] = '--set-secrets';
203194
}
204195

205196
// Compile the labels
206197
const defLabels = skipDefaultLabels ? {} : defaultLabels();
207198
const compiledLabels = Object.assign({}, defLabels, labels);
208199
if (compiledLabels && Object.keys(compiledLabels).length > 0) {
209-
cmd.push('--labels', joinKVStringForGCloud(compiledLabels));
200+
deployCmd.push('--labels', joinKVStringForGCloud(compiledLabels));
210201
}
211202
} else {
212-
cmd = ['run', 'deploy', service];
203+
deployCmd = ['run', 'deploy', service];
213204

214205
if (image) {
215-
cmd.push('--image', image);
206+
deployCmd.push('--image', image);
216207
} else if (source) {
217-
cmd.push('--source', source);
208+
deployCmd.push('--source', source);
218209
}
219210

220211
// Set optional flags from inputs
221-
setEnvVarsFlags(cmd, envVars, envVarsFile, envVarsUpdateStrategy);
222-
setSecretsFlags(cmd, secrets, secretsUpdateStrategy);
212+
setEnvVarsFlags(deployCmd, envVars, envVarsFile, envVarsUpdateStrategy);
213+
setSecretsFlags(deployCmd, secrets, secretsUpdateStrategy);
223214

224215
if (tag) {
225-
cmd.push('--tag', tag);
216+
deployCmd.push('--tag', tag);
226217
}
227-
if (suffix) cmd.push('--revision-suffix', suffix);
228-
if (noTraffic) cmd.push('--no-traffic');
229-
if (timeout) cmd.push('--timeout', timeout);
218+
if (suffix) deployCmd.push('--revision-suffix', suffix);
219+
if (noTraffic) deployCmd.push('--no-traffic');
220+
if (timeout) deployCmd.push('--timeout', timeout);
230221

231222
// Compile the labels
232223
const defLabels = skipDefaultLabels ? {} : defaultLabels();
233224
const compiledLabels = Object.assign({}, defLabels, labels);
234225
if (compiledLabels && Object.keys(compiledLabels).length > 0) {
235-
cmd.push('--update-labels', joinKVStringForGCloud(compiledLabels));
226+
deployCmd.push('--update-labels', joinKVStringForGCloud(compiledLabels));
236227
}
237228
}
238229

230+
// Traffic flags
231+
let updateTrafficCmd = ['run', 'services', 'update-traffic', service];
232+
if (revTraffic) updateTrafficCmd.push('--to-revisions', revTraffic);
233+
if (tagTraffic) updateTrafficCmd.push('--to-tags', tagTraffic);
234+
239235
// Push common flags
240-
cmd.push('--format', 'json');
236+
deployCmd.push('--format', 'json');
237+
updateTrafficCmd.push('--format', 'json');
238+
241239
if (region?.length > 0) {
242-
cmd.push(
243-
'--region',
244-
region
245-
.flat()
246-
.filter((e) => e !== undefined && e !== null && e !== '')
247-
.join(','),
248-
);
240+
const regions = region
241+
.flat()
242+
.filter((e) => e !== undefined && e !== null && e !== '')
243+
.join(',');
244+
deployCmd.push('--region', regions);
245+
updateTrafficCmd.push('--region', regions);
246+
}
247+
if (projectId) {
248+
deployCmd.push('--project', projectId);
249+
updateTrafficCmd.push('--project', projectId);
249250
}
250-
if (projectId) cmd.push('--project', projectId);
251251

252252
// Add optional flags
253253
if (flags) {
254254
const flagList = parseFlags(flags);
255-
if (flagList) cmd = cmd.concat(flagList);
255+
if (flagList) {
256+
deployCmd = deployCmd.concat(flagList);
257+
updateTrafficCmd = updateTrafficCmd.concat(flagList);
258+
}
256259
}
257260

258261
// Install gcloud if not already installed.
@@ -266,7 +269,8 @@ export async function run(): Promise<void> {
266269
// Install gcloud component if needed and prepend the command
267270
if (gcloudComponent) {
268271
await installGcloudComponent(gcloudComponent);
269-
cmd.unshift(gcloudComponent);
272+
deployCmd.unshift(gcloudComponent);
273+
updateTrafficCmd.unshift(gcloudComponent);
270274
}
271275

272276
// Authenticate - this comes from google-github-actions/auth.
@@ -280,25 +284,33 @@ export async function run(): Promise<void> {
280284

281285
const toolCommand = getToolCommand();
282286
const options = { silent: !isDebug, ignoreReturnCode: true };
283-
const commandString = `${toolCommand} ${cmd.join(' ')}`;
287+
const commandString = `${toolCommand} ${deployCmd.join(' ')}`;
284288
logInfo(`Running: ${commandString}`);
285-
logDebug(JSON.stringify({ toolCommand: toolCommand, args: cmd, options: options }, null, ' '));
286-
287-
// Run gcloud cmd.
288-
const output = await getExecOutput(toolCommand, cmd, options);
289-
if (output.exitCode !== 0) {
290-
const errMsg = output.stderr || `command exited ${output.exitCode}, but stderr had no output`;
289+
logDebug(
290+
JSON.stringify({ toolCommand: toolCommand, args: deployCmd, options: options }, null, ' '),
291+
);
292+
293+
// Run deploy command
294+
const deployCmdExec = await getExecOutput(toolCommand, deployCmd, options);
295+
if (deployCmdExec.exitCode !== 0) {
296+
const errMsg =
297+
deployCmdExec.stderr ||
298+
`command exited ${deployCmdExec.exitCode}, but stderr had no output`;
291299
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
292300
}
301+
setActionOutputs(parseDeployResponse(deployCmdExec.stdout, { tag: tag }));
293302

294-
// Map outputs by response type
295-
const outputs: DeployCloudRunOutputs =
296-
responseType === ResponseTypes.UPDATE_TRAFFIC
297-
? parseUpdateTrafficResponse(output.stdout)
298-
: parseDeployResponse(output.stdout, { tag: tag });
299-
300-
// Map outputs to GitHub actions output
301-
setActionOutputs(outputs);
303+
// Run revision/tag command
304+
if (revTraffic || tagTraffic) {
305+
const updateTrafficExec = await getExecOutput(toolCommand, updateTrafficCmd, options);
306+
if (updateTrafficExec.exitCode !== 0) {
307+
const errMsg =
308+
updateTrafficExec.stderr ||
309+
`command exited ${updateTrafficExec.exitCode}, but stderr had no output`;
310+
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
311+
}
312+
setActionOutputs(parseUpdateTrafficResponse(updateTrafficExec.stdout));
313+
}
302314
} catch (err) {
303315
const msg = errorMessage(err);
304316
setFailed(`google-github-actions/deploy-cloudrun failed with: ${msg}`);

0 commit comments

Comments
 (0)