Skip to content

Commit

Permalink
(feat): Use existing wrangler installation when appropriate (#235)
Browse files Browse the repository at this point in the history
* (feat): Check for existing wrangler installation

* Add test for pre-installed wrangler

* Add changeset

* Address CR comments - check for an exact wrangler version match

* Tweak the fixture test for the pre-installed-wrangler test

* Simplify if/else logic for checking wrangler versions as per review notes

* fix(test): Fix execution for fake wrangler installation

* fixup! fix(test): Fix execution for fake wrangler installation

* Setup new CI test convention for wrangler-action

* Remove unncessary ts-expect-error comments

---------

Co-authored-by: Peter Bacon Darwin <pbacondarwin@cloudflare.com>
  • Loading branch information
AdiRishi and petebacondarwin committed May 15, 2024
1 parent ea5754c commit 0545ad2
Show file tree
Hide file tree
Showing 36 changed files with 333 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-planes-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler-action": minor
---

wrangler-action will now re-use existing wrangler installations when available
43 changes: 23 additions & 20 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Only build app
uses: ./
with:
workingDirectory: "./test/base"
workingDirectory: "./test/only-build"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run
Expand All @@ -38,12 +38,11 @@ jobs:
uses: ./
with:
quiet: true
workingDirectory: "./test/base"
workingDirectory: "./test/build-quiet"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run

# START Setup and teardown of Worker Environment Tests
- name: Environment support
uses: ./
with:
Expand All @@ -52,28 +51,20 @@ jobs:
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
environment: dev
preCommands: npx wrangler deploy --env dev # https://github.com/cloudflare/wrangler-action/issues/162
postCommands: npx wrangler delete --name wrangler-action-dev-environment-test --force
secrets: |
SECRET1
SECRET2
env:
SECRET1: ${{ secrets.SECRET1 }}
SECRET2: ${{ secrets.SECRET2 }}

- name: Clean up Deployed Environment Worker
uses: ./
with:
workingDirectory: "./test/base"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: delete --name wrangler-action-dev-environment-test --force

# END Setup and teardown of Worker Environment Tests
# START Setup and teardown of Workers w/ Secrets Tests
- name: Deploy app secrets w/ hardcoded Wrangler v2
uses: ./
with:
wranglerVersion: "2.20.0"
workingDirectory: "./test/base"
workingDirectory: "./test/secrets-v2"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
secrets: |
Expand All @@ -84,13 +75,13 @@ jobs:
SECRET2: ${{ secrets.SECRET2 }}

- name: Health Check Deployed Worker
run: node .github/workflows/workerHealthCheck.cjs
run: node .github/workflows/workerHealthCheck.cjs wrangler-action-test-secrets-v2
shell: bash

- name: Deploy app secrets w/ default version
uses: ./
with:
workingDirectory: "./test/base"
workingDirectory: "./test/secrets-default"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
secrets: |
Expand All @@ -101,22 +92,23 @@ jobs:
SECRET2: ${{ secrets.SECRET2 }}

- name: Health Check Deployed Worker
run: node .github/workflows/workerHealthCheck.cjs
run: node .github/workflows/workerHealthCheck.cjs wrangler-action-test-secrets-default
shell: bash

- name: Clean Up Deployed Workers
uses: ./
with:
workingDirectory: "./test/base"
workingDirectory: "./test/secrets-default"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: delete --name wrangler-action-test --force
command: delete --name wrangler-action-test-secrets-v2 --force
postCommands: npx wrangler delete --name wrangler-action-test-secrets-default --force
# END Setup and teardown of Workers w/ Secrets Tests

- name: Support packageManager variable
uses: ./
with:
workingDirectory: "./test/empty"
workingDirectory: "./test/specify-package-manager"
packageManager: "npm"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Expand All @@ -125,7 +117,7 @@ jobs:
- name: Support unspecified packageManager with no lockfile
uses: ./
with:
workingDirectory: "./test/empty"
workingDirectory: "./test/unspecified-package-manager"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run
Expand Down Expand Up @@ -159,3 +151,14 @@ jobs:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run

- name: Change directory to pre-installed-wrangler and install dependencies
run: |
cd ./test/pre-installed-wrangler
npm install
- name: Support pre-installed wrangler
uses: ./
with:
workingDirectory: "./test/pre-installed-wrangler"
command: action-test
16 changes: 12 additions & 4 deletions .github/workflows/workerHealthCheck.cjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const { execSync } = require("child_process");

function workerHealthCheck() {
const url =
"https://wrangler-action-test.devprod-testing7928.workers.dev/secret-health-check";
function workerHealthCheck(workerName) {
const url = `https://${workerName}.devprod-testing7928.workers.dev/secret-health-check`;

const buffer = execSync(`curl ${url}`);

Expand All @@ -17,4 +16,13 @@ function workerHealthCheck() {
return response;
}

workerHealthCheck();
const args = Array.from(process.argv);
const workerName = args.pop();

if (!workerName) {
throw new Error(
"Please provide the worker name as an argument when calling this program.",
);
}

workerHealthCheck(workerName);
61 changes: 61 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
setFailed,
setOutput,
} from "@actions/core";
import { getExecOutput } from "@actions/exec";
import semverEq from "semver/functions/eq";
import { exec, execShell } from "./exec";
import { checkWorkingDirectory, semverCompare } from "./utils";
import { getPackageManager } from "./packageManagers";
Expand All @@ -21,6 +23,7 @@ const DEFAULT_WRANGLER_VERSION = "3.13.2";
*/
const config = {
WRANGLER_VERSION: getInput("wranglerVersion") || DEFAULT_WRANGLER_VERSION,
didUserProvideWranglerVersion: Boolean(getInput("wranglerVersion")),
secrets: getMultilineInput("secrets"),
workingDirectory: checkWorkingDirectory(getInput("workingDirectory")),
CLOUDFLARE_API_TOKEN: getInput("apiToken"),
Expand Down Expand Up @@ -82,6 +85,64 @@ async function installWrangler() {
);
}

startGroup("🔍 Checking for existing Wrangler installation");
let installedVersion = "";
let installedVersionSatisfiesRequirement = false;
try {
const { stdout } = await getExecOutput(
packageManager.exec,
["wrangler", "--version"],
{
cwd: config["workingDirectory"],
silent: config.QUIET_MODE,
},
);
// There are two possible outputs from `wrangler --version`:
// ` ⛅️ wrangler 3.48.0 (update available 3.53.1)`
// and
// `3.48.0`
const versionMatch =
stdout.match(/wrangler (\d+\.\d+\.\d+)/) ??
stdout.match(/^(\d+\.\d+\.\d+)/);
if (versionMatch) {
installedVersion = versionMatch[1];
}
if (config.didUserProvideWranglerVersion) {
installedVersionSatisfiesRequirement = semverEq(
installedVersion,
config["WRANGLER_VERSION"],
);
}
if (!config.didUserProvideWranglerVersion && installedVersion) {
info(
`✅ No wrangler version specified, using pre-installed wrangler version ${installedVersion}`,
true,
);
endGroup();
return;
}
if (
config.didUserProvideWranglerVersion &&
installedVersionSatisfiesRequirement
) {
info(`✅ Using Wrangler ${installedVersion}`, true);
endGroup();
return;
}
info(
"⚠️ Wrangler not found or version is incompatible. Installing...",
true,
);
} catch (error) {
debug(`Error checking Wrangler version: ${error}`);
info(
"⚠️ Wrangler not found or version is incompatible. Installing...",
true,
);
} finally {
endGroup();
}

startGroup("📥 Installing Wrangler");
try {
await exec(
Expand Down
1 change: 0 additions & 1 deletion test/base/index.ts → test/build-quiet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default {
return new Response("OK");
}

// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions test/build-quiet/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name = "wrangler-action-test-build-quiet"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
1 change: 0 additions & 1 deletion test/bun/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default {
return new Response("OK");
}

// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
Expand Down
1 change: 0 additions & 1 deletion test/environment/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export default {
return new Response(`${SECRET1} ${SECRET2}`);
}

// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
Expand Down
1 change: 0 additions & 1 deletion test/npm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default {
return new Response("OK");
}

// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
Expand Down
25 changes: 25 additions & 0 deletions test/only-build/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};

export default {
fetch(request: Request, env: Env) {
const url = new URL(request.url);

if (url.pathname === "/secret-health-check") {
const { SECRET1, SECRET2 } = env;

if (SECRET1 !== "SECRET_1_VALUE" || SECRET2 !== "SECRET_2_VALUE") {
throw new Error("SECRET1 or SECRET2 is not defined");
}

return new Response("OK");
}

return Response.json({
...request,
headers: Object.fromEntries(request.headers),
});
},
};
10 changes: 10 additions & 0 deletions test/only-build/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions test/only-build/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "wrangler-action-test",
"license": "MIT",
"private": true
}
2 changes: 1 addition & 1 deletion test/base/wrangler.toml → test/only-build/wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name = "wrangler-action-test"
name = "wrangler-action-test-only-build"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
1 change: 0 additions & 1 deletion test/pnpm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default {
return new Response("OK");
}

// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
Expand Down
25 changes: 25 additions & 0 deletions test/pre-installed-wrangler/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};

export default {
fetch(request: Request, env: Env) {
const url = new URL(request.url);

if (url.pathname === "/secret-health-check") {
const { SECRET1, SECRET2 } = env;

if (SECRET1 !== "SECRET_1_VALUE" || SECRET2 !== "SECRET_2_VALUE") {
throw new Error("SECRET1 or SECRET2 is not defined");
}

return new Response("OK");
}

return Response.json({
...request,
headers: Object.fromEntries(request.headers),
});
},
};
18 changes: 18 additions & 0 deletions test/pre-installed-wrangler/mock_packages/wrangler/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env node
"use strict";

const args = Array.from(process.argv);
const command = args.pop();
switch (command) {
case "--version":
console.log(`
⛅️ wrangler 1.1.1 (update available 1.2.3)
------------------------------------------`);
process.exit(0);
case "action-test":
console.log("Test successful.");
process.exit(0);
default:
console.error("Invalid command");
process.exit(1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"private": true,
"name": "wrangler",
"version": "1.1.1",
"main": "index.js",
"bin": "index.js"
}
Loading

0 comments on commit 0545ad2

Please sign in to comment.