8000 Always update traffic if tag_traffic or revision_traffic is given by sethvargo · Pull Request #535 · google-github-actions/deploy-cloudrun · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Always update traffic if tag_traffic or revision_traffic is given #535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ jobs:
env_vars_update_strategy: 'overwrite'
secrets: /api/secrets/my-secret=${{ vars.SECRET_NAME }}:latest
secrets_update_strategy: 'overwrite'
to_revision: 'LATEST=100'

- name: 'Run re-deploy tests'
run: 'npm run e2e-tests'
Expand Down Expand Up @@ -201,6 +202,7 @@ jobs:
with:
image: 'gcr.io/cloudrun/hello'
service: '${{ env.SERVICE_NAME }}'
to_revision: 'LATEST=100'

- name: 'Run re-deploy tests'
run: 'npm run e2e-tests' # Check that config isn't overwritten
Expand Down
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ jobs:
code](https://cloud.google.com/run/docs/deploying-source-code).

- <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
with the service name automatically. For example, specifying 'v1' for a
service named 'helloworld', would lead to a revision named
'helloworld-v1'.
with the service name automatically. For example, specifying `v1` for a
service named `helloworld`, would lead to a revision named
`helloworld-v1`. This option is only applies to services.

- <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.
These are comma-separated or newline-separated `KEY=VALUE`. Keys or values
Expand Down Expand Up @@ -179,7 +179,8 @@ jobs:

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

- <a name="tag"></a><a href="#user-content-tag"><code>tag</code></a>: _(Optional)_ Traffic tag to assign to the newly-created revision.
- <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
applies to services.

- <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
ten minutes and 5 seconds.
Expand All @@ -202,11 +203,12 @@ jobs:

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

- <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.
- <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
is only applies to services.

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

Expand All @@ -218,14 +220,16 @@ jobs:
with:
revision_traffic: 'LATEST=100'

This is mutually-exclusive with `tag_traffic`.
This is mutually-exclusive with `tag_traffic`. This option is only applies
to services.

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

with:
tag_traffic: 'my-tag=10' # percentage

This is mutually-exclusive with `revision_traffic`.
This is mutually-exclusive with `revision_traffic`. This option is only
applies to services.

- <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.

Expand Down
24 changes: 14 additions & 10 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ inputs:
suffix:
description: |-
String suffix to append to the revision name. Revision names always start
with the service name automatically. For example, specifying 'v1' for a
service named 'helloworld', would lead to a revision named
'helloworld-v1'.
with the service name automatically. For example, specifying `v1` for a
service named `helloworld`, would lead to a revision named
`helloworld-v1`. This option is only applies to services.
required: false

env_vars:
Expand Down Expand Up @@ -186,7 +186,8 @@ inputs:

tag:
description: |-
Traffic tag to assign to the newly-created revision.
Traffic tag to assign to the newly-created revision. This option is only
applies to services.
required: false

timeout:
Expand Down Expand Up @@ -215,14 +216,15 @@ inputs:

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

no_traffic:
description: |-
If true, the newly deployed revision will not receive traffic.
If true, the newly deployed revision will not receive traffic. This option
is only applies to services.
default: 'false'
required: false

Expand All @@ -238,7 +240,8 @@ inputs:
with:
revision_traffic: 'LATEST=100'

This is mutually-exclusive with `tag_traffic`.
This is mutually-exclusive with `tag_traffic`. This option is only applies
to services.
required: false

tag_traffic:
Expand All @@ -248,7 +251,8 @@ inputs:
with:
tag_traffic: 'my-tag=10' # percentage

This is mutually-exclusive with `revision_traffic`.
This is mutually-exclusive with `revision_traffic`. This option is only
applies to services.
required: false

project_id:
Expand Down
126 changes: 69 additions & 57 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ export async function run(): Promise<void> {
const skipDefaultLabels = parseBoolean(getInput('skip_default_labels'));
const flags = getInput('flags');

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

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

// Find base command
if (revTraffic || tagTraffic) {
// Set response type for output parsing
responseType = ResponseTypes.UPDATE_TRAFFIC;

// Update traffic
cmd = ['run', 'services', 'update-traffic', service];
if (revTraffic) cmd.push('--to-revisions', revTraffic);
if (tagTraffic) cmd.push('--to-tags', tagTraffic);
} else if (metadata) {
if (metadata) {
const contents = await readFile(metadata, 'utf8');
const parsed = parseYAML(contents);

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

cmd = ['run', 'jobs', 'deploy', job];
deployCmd = ['run', 'jobs', 'deploy', job];

if (image) {
cmd.push('--image', image);
deployCmd.push('--image', image);
} else if (source) {
cmd.push('--source', source);
deployCmd.push('--source', source);
}

// Set optional flags from inputs
setEnvVarsFlags(cmd, envVars, envVarsFile, envVarsUpdateStrategy);
setSecretsFlags(cmd, secrets, secretsUpdateStrategy);
setEnvVarsFlags(deployCmd, envVars, envVarsFile, envVarsUpdateStrategy);
setSecretsFlags(deployCmd, secrets, secretsUpdateStrategy);

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

// Compile the labels
const defLabels = skipDefaultLabels ? {} : defaultLabels();
const compiledLabels = Object.assign({}, defLabels, labels);
if (compiledLabels && Object.keys(compiledLabels).length > 0) {
cmd.push('--labels', joinKVStringForGCloud(compiledLabels));
deployCmd.push('--labels', joinKVStringForGCloud(compiledLabels));
}
} else {
cmd = ['run', 'deploy', service];
deployCmd = ['run', 'deploy', service];

if (image) {
cmd.push('--image', image);
deployCmd.push('--image', image);
} else if (source) {
cmd.push('--source', source);
deployCmd.push('--source', source);
}

// Set optional flags from inputs
setEnvVarsFlags(cmd, envVars, envVarsFile, envVarsUpdateStrategy);
setSecretsFlags(cmd, secrets, secretsUpdateStrategy);
setEnvVarsFlags(deployCmd, envVars, envVarsFile, envVarsUpdateStrategy);
setSecretsFlags(deployCmd, secrets, secretsUpdateStrategy);

if (tag) {
cmd.push('--tag', tag);
deployCmd.push('--tag', tag);
}
if (suffix) cmd.push('--revision-suffix', suffix);
if (noTraffic) cmd.push('--no-traffic');
if (timeout) cmd.push('--timeout', timeout);
if (suffix) deployCmd.push('--revision-suffix', suffix);
if (noTraffic) deployCmd.push('--no-traffic');
if (timeout) deployCmd.push('--timeout', timeout);

// Compile the labels
const defLabels = skipDefaultLabels ? {} : defaultLabels();
const compiledLabels = Object.assign({}, defLabels, labels);
if (compiledLabels && Object.keys(compiledLabels).length > 0) {
cmd.push('--update-labels', joinKVStringForGCloud(compiledLabels));
deployCmd.push('--update-labels', joinKVStringForGCloud(compiledLabels));
}
}

// Traffic flags
let updateTrafficCmd = ['run', 'services', 'update-traffic', service];
if (revTraffic) updateTrafficCmd.push('--to-revisions', revTraffic);
if (tagTraffic) updateTrafficCmd.push('--to-tags', tagTraffic);

// Push common flags
cmd.push('--format', 'json');
deployCmd.push('--format', 'json');
updateTrafficCmd.push('--format', 'json');

if (region?.length > 0) {
cmd.push(
'--region',
region
.flat()
.filter((e) => e !== undefined && e !== null && e !== '')
.join(','),
);
const regions = region
.flat()
.filter((e) => e !== undefined && e !== null && e !== '')
.join(',');
deployCmd.push('--region', regions);
updateTrafficCmd.push('--region', regions);
}
if (projectId) {
deployCmd.push('--project', projectId);
updateTrafficCmd.push('--project', projectId);
}
if (projectId) cmd.push('--project', projectId);

// Add optional flags
if (flags) {
const flagList = parseFlags(flags);
if (flagList) cmd = cmd.concat(flagList);
if (flagList) {
deployCmd = deployCmd.concat(flagList);
updateTrafficCmd = updateTrafficCmd.concat(flagList);
}
}

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

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

const toolCommand = getToolCommand();
const options = { silent: !isDebug, ignoreReturnCode: true };
const commandString = `${toolCommand} ${cmd.join(' ')}`;
const commandString = `${toolCommand} ${deployCmd.join(' ')}`;
logInfo(`Running: ${commandString}`);
logDebug(JSON.stringify({ toolCommand: toolCommand, args: cmd, options: options }, null, ' '));

// Run gcloud cmd.
const output = await getExecOutput(toolCommand, cmd, options);
if (output.exitCode !== 0) {
const errMsg = output.stderr || `command exited ${output.exitCode}, but stderr had no output`;
logDebug(
JSON.stringify({ toolCommand: toolCommand, args: deployCmd, options: options }, null, ' '),
);

// Run deploy command
const deployCmdExec = await getExecOutput(toolCommand, deployCmd, options);
if (deployCmdExec.exitCode !== 0) {
const errMsg =
deployCmdExec.stderr ||
`command exited ${deployCmdExec.exitCode}, but stderr had no output`;
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
}
setActionOutputs(parseDeployResponse(deployCmdExec.stdout, { tag: tag }));

// Map outputs by response type
const outputs: DeployCloudRunOutputs =
responseType === ResponseTypes.UPDATE_TRAFFIC
? parseUpdateTrafficResponse(output.stdout)
: parseDeployResponse(output.stdout, { tag: tag });

// Map outputs to GitHub actions output
setActionOutputs(outputs);
// Run revision/tag command
if (revTraffic || tagTraffic) {
const updateTrafficExec = await getExecOutput(toolCommand, updateTrafficCmd, options);
if (updateTrafficExec.exitCode !== 0) {
const errMsg =
updateTrafficExec.stderr ||
`command exited ${updateTrafficExec.exitCode}, but stderr had no output`;
throw new Error(`failed to execute gcloud command \`${commandString}\`: ${errMsg}`);
}
setActionOutputs(parseUpdateTrafficResponse(updateTrafficExec.stdout));
}
} catch (err) {
const msg = errorMessage(err);
setFailed(`google-github-actions/deploy-cloudrun failed with: ${msg}`);
Expand Down
Loading
Loading
0