Merge pull request #165 from cloudflare/cina/fix-release-workflow-pt2

Build action before pushing dist-tags
This commit is contained in:
Cina Saffary 2023-08-31 10:55:48 -05:00
commit 53ee19c30e
6 changed files with 4512 additions and 111 deletions

View file

@ -39,10 +39,14 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Tag & Release Action - name: Build action
if: steps.changesets.outputs.published == 'true' if: steps.changesets.outputs.published == 'true'
run: npm run build
- name: Push dist-tags
if: steps.changesets.outputs.published == 'true'
uses: JasonEtco/build-and-tag-action@v2
with: with:
tag_name: v${{ fromJSON(steps.changesets.outputs.publishedPackages)[0].version }} tag_name: v${{ fromJSON(steps.changesets.outputs.publishedPackages)[0].version }}
uses: JasonEtco/build-and-tag-action@v2
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}

4354
dist/index.mjs vendored Normal file

File diff suppressed because it is too large Load diff

20
package-lock.json generated
View file

@ -1,15 +1,16 @@
{ {
"name": "wrangler-action", "name": "wrangler-action",
"version": "3.0.2", "version": "3.1.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "wrangler-action", "name": "wrangler-action",
"version": "3.0.2", "version": "3.1.1",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"dependencies": { "dependencies": {
"@actions/core": "^1.10.0" "@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1"
}, },
"devDependencies": { "devDependencies": {
"@changesets/changelog-github": "^0.4.8", "@changesets/changelog-github": "^0.4.8",
@ -31,6 +32,14 @@
"uuid": "^8.3.2" "uuid": "^8.3.2"
} }
}, },
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
@ -39,6 +48,11 @@
"tunnel": "^0.0.6" "tunnel": "^0.0.6"
} }
}, },
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.22.5", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",

View file

@ -29,7 +29,8 @@
"check": "prettier --check ." "check": "prettier --check ."
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.10.0" "@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1"
}, },
"devDependencies": { "devDependencies": {
"@changesets/changelog-github": "^0.4.8", "@changesets/changelog-github": "^0.4.8",

54
src/exec.ts Normal file
View file

@ -0,0 +1,54 @@
import {
exec as _childProcessExec,
type ExecException,
} from "node:child_process";
import { EOL } from "node:os";
import { promisify } from "node:util";
export { exec } from "@actions/exec";
const childProcessExec = promisify(_childProcessExec);
type ExecAsyncException = ExecException & {
stderr: string;
stdout: string;
};
function isExecAsyncException(err: unknown): err is ExecAsyncException {
return err instanceof Error && "code" in err && "stderr" in err;
}
export async function execShell(
command: string,
{
silent = false,
...options
}: Parameters<typeof childProcessExec>[1] & { silent?: boolean } = {},
) {
if (!silent) {
process.stdout.write("[command]" + command + EOL);
}
try {
const promise = childProcessExec(command, {
...options,
});
const { child } = promise;
if (!silent) {
child.stdout?.on("data", (data: Buffer) => process.stdout.write(data));
child.stderr?.on("data", (data: Buffer) => process.stderr.write(data));
}
await promise;
return child.exitCode;
} catch (err: any) {
if (isExecAsyncException(err)) {
process.stderr.write(err.stderr);
throw new Error(`Process failed with exit code ${err.code}`);
}
throw err;
}
}

View file

@ -8,10 +8,8 @@ import {
startGroup as originalStartGroup, startGroup as originalStartGroup,
getBooleanInput, getBooleanInput,
} from "@actions/core"; } from "@actions/core";
import { execSync, exec } from "node:child_process"; import { exec, execShell } from "./exec";
import { checkWorkingDirectory, getNpxCmd, semverCompare } from "./utils"; import { checkWorkingDirectory, getNpxCmd, semverCompare } from "./utils";
import * as util from "node:util";
const execAsync = util.promisify(exec);
const DEFAULT_WRANGLER_VERSION = "3.5.1"; const DEFAULT_WRANGLER_VERSION = "3.5.1";
@ -56,8 +54,8 @@ function endGroup(): void {
async function main() { async function main() {
try { try {
installWrangler();
authenticationSetup(); authenticationSetup();
await installWrangler();
await execCommands(getMultilineInput("preCommands"), "pre"); await execCommands(getMultilineInput("preCommands"), "pre");
await uploadSecrets(); await uploadSecrets();
await wranglerCommands(); await wranglerCommands();
@ -69,36 +67,24 @@ async function main() {
} }
} }
async function runProcess( async function installWrangler() {
command: Parameters<typeof execAsync>[0],
options: Parameters<typeof execAsync>[1],
) {
try {
const result = await execAsync(command, options);
result.stdout && info(result.stdout.toString());
result.stderr && error(result.stderr.toString(), true);
return result;
} catch (err: any) {
err.stdout && info(err.stdout.toString());
err.stderr && error(err.stderr.toString(), true);
throw new Error(`\`${command}\` returned non-zero exit code.`);
}
}
function installWrangler() {
if (config["WRANGLER_VERSION"].startsWith("1")) { if (config["WRANGLER_VERSION"].startsWith("1")) {
throw new Error( throw new Error(
`Wrangler v1 is no longer supported by this action. Please use major version 2 or greater`, `Wrangler v1 is no longer supported by this action. Please use major version 2 or greater`,
); );
} }
startGroup("📥 Installing Wrangler"); startGroup("📥 Installing Wrangler");
const command = `npm install wrangler@${config["WRANGLER_VERSION"]}`; try {
info(`Running command: ${command}`); await exec("npm", ["install", `wrangler@${config["WRANGLER_VERSION"]}`], {
execSync(command, { cwd: config["workingDirectory"], env: process.env }); cwd: config["workingDirectory"],
info(`✅ Wrangler installed`, true); silent: config["QUIET_MODE"],
endGroup(); });
info(`✅ Wrangler installed`, true);
} finally {
endGroup();
}
} }
function authenticationSetup() { function authenticationSetup() {
@ -113,28 +99,21 @@ async function execCommands(commands: string[], cmdType: string) {
startGroup(`🚀 Running ${cmdType}Commands`); startGroup(`🚀 Running ${cmdType}Commands`);
try { try {
const arrPromises = commands.map(async (command) => { for (const command of commands) {
const cmd = command.startsWith("wrangler") const cmd = command.startsWith("wrangler")
? `${getNpxCmd()} ${command}` ? `${getNpxCmd()} ${command}`
: command; : command;
info(`🚀 Executing command: ${cmd}`); await execShell(cmd, {
return await runProcess(cmd, {
cwd: config["workingDirectory"], cwd: config["workingDirectory"],
env: process.env, silent: config["QUIET_MODE"],
}); });
}); }
await Promise.all(arrPromises);
} finally { } finally {
endGroup(); endGroup();
} }
} }
/**
* A helper function to get the secret from the environment variables.
*/
function getSecret(secret: string) { function getSecret(secret: string) {
if (!secret) { if (!secret) {
throw new Error("Secret name cannot be blank."); throw new Error("Secret name cannot be blank.");
@ -142,33 +121,43 @@ function getSecret(secret: string) {
const value = process.env[secret]; const value = process.env[secret];
if (!value) { if (!value) {
throw new Error(`Value for secret ${secret} not found.`); throw new Error(`Value for secret ${secret} not found in environment.`);
} }
return value; return value;
} }
async function legacyUploadSecrets( function getEnvVar(envVar: string) {
if (!envVar) {
throw new Error("Var name cannot be blank.");
}
const value = process.env[envVar];
if (!value) {
throw new Error(`Value for var ${envVar} not found in environment.`);
}
return value;
}
function legacyUploadSecrets(
secrets: string[], secrets: string[],
environment?: string, environment?: string,
workingDirectory?: string, workingDirectory?: string,
) { ) {
const arrPromises = secrets return Promise.all(
.map((secret) => { secrets.map((secret) => {
const command = `echo ${getSecret( const args = ["wranger", "secret", "put", secret];
secret, if (environment) {
)} | ${getNpxCmd()} wrangler secret put ${secret}`; args.push("--env", environment);
return environment ? command.concat(` --env ${environment}`) : command; }
}) return exec(getNpxCmd(), ["wrangler", "secret", "put", secret], {
.map( cwd: workingDirectory,
async (command) => silent: config["QUIET_MODE"],
await execAsync(command, { input: Buffer.from(getSecret(secret)),
cwd: workingDirectory, });
env: process.env, }),
}), );
);
await Promise.all(arrPromises);
} }
async function uploadSecrets() { async function uploadSecrets() {
@ -183,51 +172,34 @@ async function uploadSecrets() {
startGroup("🔑 Uploading secrets..."); startGroup("🔑 Uploading secrets...");
try { try {
if (semverCompare(config["WRANGLER_VERSION"], "3.4.0")) if (semverCompare(config["WRANGLER_VERSION"], "3.4.0")) {
return legacyUploadSecrets(secrets, environment, workingDirectory); return legacyUploadSecrets(secrets, environment, workingDirectory);
}
const secretObj = secrets.reduce((acc: any, secret: string) => { const args = ["wrangler", "secret:bulk"];
acc[secret] = getSecret(secret);
return acc;
}, {});
const environmentSuffix = !environment.length if (environment) {
? "" args.push("--env", environment);
: ` --env ${environment}`; }
const secretCmd = `echo "${JSON.stringify(secretObj).replaceAll( await exec(getNpxCmd(), args, {
'"',
'\\"',
)}" | ${getNpxCmd()} wrangler secret:bulk ${environmentSuffix}`;
execSync(secretCmd, {
cwd: workingDirectory, cwd: workingDirectory,
env: process.env, silent: config["QUIET_MODE"],
stdio: "ignore", input: Buffer.from(
JSON.stringify(
Object.fromEntries(
secrets.map((secret) => [secret, getSecret(secret)]),
),
),
),
}); });
info(`✅ Uploaded secrets`);
} catch (err) { } catch (err) {
error(`❌ Upload failed`);
throw new Error(`Failed to upload secrets.`); throw new Error(`Failed to upload secrets.`);
} finally { } finally {
endGroup(); endGroup();
} }
} }
function getVarArgs() {
const vars = config["VARS"];
const envVarArray = vars.map((envVar: string) => {
if (process.env[envVar] && process.env[envVar]?.length !== 0) {
return `${envVar}:${process.env[envVar]!}`;
} else {
throw new Error(`Value for var ${envVar} not found in environment.`);
}
});
return envVarArray.length > 0 ? `--var ${envVarArray.join(" ").trim()}` : "";
}
async function wranglerCommands() { async function wranglerCommands() {
startGroup("🚀 Running Wrangler Commands"); startGroup("🚀 Running Wrangler Commands");
try { try {
@ -242,27 +214,29 @@ async function wranglerCommands() {
commands.push(deployCommand); commands.push(deployCommand);
} }
const arrPromises = commands.map(async (command) => { for (let command of commands) {
if (environment.length > 0 && !command.includes(`--env`)) { const args = ["wrangler", ...command.split(/\s+/)];
command = command.concat(` --env ${environment}`);
if (environment && !args.includes(`--env`)) {
args.push("--env", environment);
} }
const cmd = `${getNpxCmd()} wrangler ${command} ${ if (
(command.startsWith("deploy") || command.startsWith("publish")) && config["VARS"].length &&
!command.includes(`--var`) (args.includes("deploy") || args.includes("publish")) &&
? getVarArgs() !args.includes("--var")
: "" ) {
}`.trim(); args.push("--var");
for (const v of config["VARS"]) {
args.push(`${v}:${getEnvVar(v)}`);
}
}
info(`🚀 Executing command: ${cmd}`); await exec(getNpxCmd(), args, {
return await runProcess(cmd, {
cwd: config["workingDirectory"], cwd: config["workingDirectory"],
env: process.env, silent: config["QUIET_MODE"],
}); });
}); }
await Promise.all(arrPromises);
} finally { } finally {
endGroup(); endGroup();
} }