Compare commits

...

83 Commits

Author SHA1 Message Date
Maximo Guk 9fde81df51 test branch 2025-02-09 17:11:11 -06:00
Maximo Guk 4ff07f4310 Use wrangler outputs for version upload and wrangler deploy 2025-02-09 17:10:09 -06:00
Maximo Guk 4fb15f8b7a Bump @changesets/cli to 2.27.12 and vitest to 2.1.9 2025-02-09 16:51:41 -06:00
Maximo Guk e8cd5f0968 Merge pull request #350 from cloudflare/maximo/handle-failures-in-create-github-deployment-and-job-summary
Handle failures in createGitHubDeployment and createGitHubJobSummary
2025-02-09 16:51:09 -06:00
Maximo Guk e209094e62 Handle failures in createGitHubDeployment and createGitHubJobSummary 2025-02-09 16:49:07 -06:00
Maximo Guk 181b9fb5d6 Merge pull request #346 from cloudflare/changeset-release/main
Version Packages
2025-01-17 09:54:16 -06:00
github-actions[bot] aac328d155 Version Packages 2025-01-17 15:47:45 +00:00
Maximo Guk fc89533f1e Merge pull request #345 from cloudflare/fix/pages-gh-deployment
fix: pages github deployment not triggering due to incorrect condition #2
2025-01-17 09:47:27 -06:00
Maximo Guk e819570b2d Remove stages from pages-deploy-detailed artifact and add changeset 2025-01-17 09:31:23 -06:00
Alexandre Pereira 923db6f87f fix: pages github deployment not triggering due to missing pages artifact stages 2025-01-17 11:30:50 +00:00
Courtney Sims d5031c3dbe Merge pull request #340 from armandsalle/patch-1
Update typo in README.md
2024-12-18 16:22:28 -06:00
Armand SALLE 17da943335 Update typo in README.md 2024-12-14 23:12:56 +01:00
Maximo Guk 3aee84cd6d Merge pull request #330 from cloudflare/changeset-release/main
Version Packages
2024-11-26 16:09:40 -04:00
github-actions[bot] 9d9bee8bfd Version Packages 2024-11-26 19:27:54 +00:00
Maximo Guk ee57f258dc Merge pull request #334 from cloudflare/maximo/bump-default-wrangler-version
Bump default wrangler version to 3.90.0
2024-11-26 15:26:40 -04:00
Maximo Guk 9fed19aa4e Bump default wrangler version to 3.90.0 2024-11-26 07:47:24 -06:00
Maximo Guk 3c6e4da7b3 Merge pull request #332 from uFloppyDisk/chore/action-input-fix
chore(action.yml): rename gitHubToken input in action.yml;
2024-11-25 23:09:49 -04:00
Pawel Bartusiak 1c0eef186f chore(action.yml): rename input;
Rename 'githubToken' input to 'gitHubToken' in action.yml to reflect the key used for intake in the script;
2024-11-25 19:00:09 -08:00
Maximo Guk b19342b08c Merge pull request #325 from cloudflare/maximo/add-github-deployments-parity-for-pages-deployments-in-wrangler-action
Add GitHub deployments for parity with pages-action
2024-11-21 14:52:58 -04:00
Jacob Hands d44c80928a Merge pull request #315 from Alexkuva/patch-1
chore: Add environment parameter for worker secret
2024-11-19 14:34:40 -06:00
Maximo Guk cada7a6312 Add tests for github service, and move all github deployments logic to be inside of github.ts 2024-11-19 12:08:36 -06:00
Maximo Guk 1e92eee7d2 Restructure text fixtures directories, add test-utils.ts and add msw dep 2024-11-19 11:38:18 -06:00
Maximo Guk e7e5400334 Remove pages specific outputs from wrangler deploy command 2024-11-19 11:38:18 -06:00
Maximo Guk d58f116d72 Add github deployments to wrangler action for pages parity 2024-11-19 11:38:18 -06:00
Maximo Guk 64b6339110 Update dependencies and add @actions/github 2024-11-19 11:38:17 -06:00
Courtney Sims ac2fd0ec8f Merge pull request #324 from cloudflare/courtney-sims-documentation-update
Update documentation
2024-11-13 16:49:06 -06:00
Courtney Sims 0140ffbc93 Update documentation 2024-11-13 12:06:27 -06:00
Courtney Sims cc4ede3f06 Merge pull request #322 from cloudflare/courtney-sims-testing
Add tests for installWrangler
2024-11-13 09:15:02 -06:00
Courtney Sims 9bf87caf2b Pin node version 2024-11-12 17:25:56 -06:00
Courtney Sims 81f8814855 BANDA-484: Add tests for InstallWrangler 2024-11-12 11:54:43 -06:00
Maximo Guk 6c6d3321ef Merge pull request #320 from cloudflare/changeset-release/main
Version Packages
2024-11-06 11:27:06 -04:00
github-actions[bot] bc61e66e47 Version Packages 2024-11-05 21:26:00 +00:00
Maximo Guk 0e2b86ba21 Merge pull request #319 from cloudflare/maximo/add-changeset-for-wrangler-artifacts-dir
Add missing changeset for using randomUUID for wrangler artifacts dir
2024-11-05 17:25:38 -04:00
Maximo Guk 59c0462940 Add missing changeset for using randomUUID for wrangler artifacts dir 2024-11-05 15:20:12 -06:00
Maximo Guk 4c3f0c27ea Merge pull request #318 from cloudflare/maximo/use-random-uuid-for-wrangler-artifacts-dir
Use random UUID when creating wrangler artifacts output directory
2024-11-05 17:05:58 -04:00
Maximo Guk 4d045615a9 Use random UUID when creating wrangler artifacts output directory 2024-11-05 14:41:27 -06:00
Maximo Guk a7a2388d7b Merge pull request #313 from cloudflare/changeset-release/main
Version Packages
2024-11-04 11:31:39 -04:00
Alex 95555f6ed0 add environment parameter for worker secret
Add environment parameter for worker secret in readme.md

linked issue example: https://github.com/cloudflare/wrangler-action/issues/251
2024-11-02 17:02:18 +01:00
github-actions[bot] 2171bbdd69 Version Packages 2024-11-01 18:40:47 +00:00
Maximo Guk 4f4ff59d17 Merge pull request #312 from cloudflare/maximo/unrevert-add-parity-with-wrangler-action
Unrevert add parity with wrangler action
2024-11-01 15:40:25 -03:00
Maximo Guk 122ee5cf5b Moves wrangler output to tmpdir rather than /opt/ since /opt/ is owned by root.
- Github self hosted runners may not have permissions to write to /opt/

- Also fallsback to trying to extract the deployment-url and deployment-alias-url from stdout when WRANGLER_OUTPUT_DIR is not specified
2024-11-01 13:29:38 -05:00
Maximo Guk 44d79edf44 Reapply "Add parity with pages-action for pages deploy outputs"
This reverts commit 10d5b9c1c1.
2024-10-31 00:47:44 -05:00
Maximo Guk b2be7abbfc Merge pull request #310 from cloudflare/changeset-release/main
Version Packages
2024-10-24 11:56:05 -03:00
github-actions[bot] b7158dc9a4 Version Packages 2024-10-24 14:49:52 +00:00
Maximo Guk 43767e73de Merge pull request #309 from cloudflare/maximo/revert-add-parity-with-pages-action
Revert add parity with pages action
2024-10-24 11:48:43 -03:00
Maximo Guk 10d5b9c1c1 Revert "Add parity with pages-action for pages deploy outputs"
This reverts commit 3ec7f8943e.
2024-10-24 08:45:19 -05:00
Courtney Sims c01035706f Merge pull request #305 from cloudflare/changeset-release/main
Version Packages
2024-10-23 15:53:47 -05:00
github-actions[bot] fa96c39bd4 Version Packages 2024-10-23 19:55:00 +00:00
Courtney Sims 78dad1df07 Merge pull request #303 from cloudflare/courtney-sims-enable-outputs
Add parity with pages-action for Pages deploy outputs
2024-10-23 14:54:26 -05:00
Courtney Sims 3ec7f8943e Add parity with pages-action for pages deploy outputs 2024-10-23 10:18:55 -05:00
Maximo Guk cd8a317efb Merge pull request #299 from cloudflare/changeset-release/main
Version Packages
2024-10-08 13:03:50 -03:00
github-actions[bot] 6aa2e8946a Version Packages 2024-10-07 21:39:16 +00:00
Maximo Guk de0526e09b Merge pull request #278 from acusti/patch-1
When checking for existing wrangler install, match wrangler version even if multiline output
2024-10-07 18:38:52 -03:00
Maximo Guk 84316ca95c Merge pull request #298 from cloudflare/maximo/add-changeset-for-update-wrangler-version
Add changeset for update wrangler version from 3.13.2 to 3.78.10
2024-10-07 18:37:59 -03:00
Maximo Guk 134b5c2a32 Add changeset for update wrangler version from 3.13.2 to 3.78.10 2024-10-07 16:30:14 -05:00
Andrew Patton 47d51f25c1 Match wrangler version even if multiline output cloudflare#277 2024-10-07 20:54:34 +00:00
Somhairle MacLeòid 93fff4f656 Merge pull request #295 from Ankcorn/main 2024-10-04 22:01:44 +01:00
Maximo Guk 66334dff0a Merge pull request #297 from cloudflare/changeset-release/main
Version Packages
2024-10-02 11:46:26 -03:00
github-actions[bot] 9966912c1b Version Packages 2024-10-01 22:12:10 +00:00
Maximo Guk 7b9aec5185 Merge pull request #291 from Ambroos/add-pages-deployment-alias
Add deployment-alias-url for pages deployments with Wrangler 3.78.0+
2024-10-01 19:11:49 -03:00
Ankcorn c0e117f512 WO-202: update wrangler version 2024-09-27 11:42:53 +01:00
Maximo Guk bcff5386ec Merge pull request #294 from Cherry/chore/bun-lockfile-new
chore: add support for new bun.lock
2024-09-26 12:38:45 -03:00
Maximo Guk c15498da36 Merge pull request #293 from cloudflare/hrushikeshdeshpande-updating-semgrep-docker-image
Updating semgrep docker image for the exising semgrep workflow.
2024-09-26 12:32:17 -03:00
James Ross 8bc5c5f050 chore: add support for new bun.lock 2024-09-26 01:02:47 +01:00
Hrushikesh Deshpande ac21b71592 Updating semgrep docker image for the exising semgrep workflow. 2024-09-25 18:32:41 -04:00
Maximo Guk f111269956 Merge pull request #292 from cloudflare/hrushikeshdeshpande-updating-semgrep-yml
Update semgrep.yml
2024-09-21 12:54:17 -05:00
hrushikeshdeshpande 570d521df6 Update semgrep.yml
Updating Semgrep.yml file - Semgrep is a tool that will be used to scan Cloudflare's public repos for Supply chain, code and secrets. This work is part of Application & Product Security team's initiative to onboard Semgrep onto all of Cloudflare's public repos.

In case of any questions, please reach out to "Hrushikesh Deshpande" on cf internal chat.
2024-09-21 12:06:53 -04:00
Hrushikesh Deshpande 174337b3b4 Adding semgrep yaml file 2024-09-19 21:54:02 -04:00
Ambroos Vaes a1467a0c8f Add deployment-alias-url for pages deployments with Wrangler 3.78.0+ 2024-09-19 18:54:02 +02:00
Maximo Guk 3ea6e3f132 Merge pull request #272 from cloudflare/changeset-release/main
Version Packages
2024-07-02 08:31:12 -05:00
github-actions[bot] ea11499226 Version Packages 2024-06-20 21:23:25 +00:00
Maximo Guk 8f2f89521c Merge pull request #271 from cloudflare/maximo/fixup-235
Unreverts #235 and don't automatically install wrangler when checking if it present
2024-06-20 16:23:02 -05:00
Maximo Guk 66efca2cbb Invoke wrangler to check if it's installed, but don't auto-install through npx/bunx 2024-06-15 23:22:47 -05:00
Maximo Guk aa5d18dd1e Revert "Revert "(feat): Use existing wrangler installation when appropriate (#235)""
This reverts commit 2d275a8f2d.
2024-06-15 22:57:11 -05:00
Maximo Guk b84268f0e0 Merge pull request #268 from cloudflare/changeset-release/main
Version Packages
2024-05-24 10:18:03 -05:00
github-actions[bot] d1b97ebf4d Version Packages 2024-05-24 15:16:10 +00:00
Jacob Hands baf8bc61f1 Merge pull request #265 from Maximo-Guk/maximo/revert-235
Revert "(feat): Use existing wrangler installation when appropriate #235"
2024-05-24 10:15:49 -05:00
Jacob Hands 8edd152f63 Update CODEOWNERS (#266) 2024-05-24 16:13:49 +01:00
Maximo Guk 2d275a8f2d Revert "(feat): Use existing wrangler installation when appropriate (#235)"
This reverts commit 0545ad285a.
2024-05-24 10:04:14 -05:00
github-actions[bot] 8ef515f899 Version Packages (#262)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-23 15:58:20 +01:00
dependabot[bot] 9b27cf271c Bump undici from 5.28.3 to 5.28.4 (#249)
Bumps [undici](https://github.com/nodejs/undici) from 5.28.3 to 5.28.4.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.3...v5.28.4)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-15 14:01:17 +01:00
dependabot[bot] 405a82610b Bump vite from 5.0.12 to 5.2.8 (#248)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.12 to 5.2.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-15 13:13:16 +01:00
Adishwar Rishi 0545ad285a (feat): Use existing wrangler installation when appropriate (#235)
* (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>
2024-05-15 09:53:41 +01:00
107 changed files with 40840 additions and 3228 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
with multi-package repos, or single-package repos to help you version and deploy your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
+5
View File
@@ -0,0 +1,5 @@
---
"wrangler-action": patch
---
Handle failures in createGitHubDeployment and createGitHubJobSummary
+5
View File
@@ -0,0 +1,5 @@
---
"wrangler-action": minor
---
Use wrangler outputs for version upload and wrangler deploy
+29 -25
View File
@@ -14,7 +14,8 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "latest"
# Pinned due to compatibility issues on 23.2.0
node-version: "22"
cache: "npm"
- name: Install modules and build
@@ -29,7 +30,7 @@ jobs:
- name: Only build app
uses: ./
with:
workingDirectory: "./test/base"
workingDirectory: "./src/test/fixtures/only-build"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run
@@ -38,20 +39,20 @@ jobs:
uses: ./
with:
quiet: true
workingDirectory: "./test/base"
workingDirectory: "./src/test/fixtures/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:
workingDirectory: "./test/environment"
workingDirectory: "./src/test/fixtures/environment"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
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
@@ -59,21 +60,12 @@ jobs:
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: "./src/test/fixtures/secrets-v2"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
secrets: |
@@ -84,13 +76,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: "./src/test/fixtures/secrets-default"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
secrets: |
@@ -101,22 +93,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: "./src/test/fixtures/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: "./src/test/fixtures/specify-package-manager"
packageManager: "npm"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
@@ -125,7 +118,7 @@ jobs:
- name: Support unspecified packageManager with no lockfile
uses: ./
with:
workingDirectory: "./test/empty"
workingDirectory: "./src/test/fixtures/unspecified-package-manager"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run
@@ -133,7 +126,7 @@ jobs:
- name: Support npm package manager
uses: ./
with:
workingDirectory: "./test/npm"
workingDirectory: "./src/test/fixtures/npm"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run
@@ -144,7 +137,7 @@ jobs:
- name: Support yarn package manager
uses: ./
with:
workingDirectory: "./test/yarn"
workingDirectory: "./src/test/fixtures/yarn"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --dry-run
@@ -155,7 +148,18 @@ jobs:
- name: Support pnpm package manager
uses: ./
with:
workingDirectory: "./test/pnpm"
workingDirectory: "./src/test/fixtures/pnpm"
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 ./src/test/fixtures/pre-installed-wrangler
npm install
- name: Support pre-installed wrangler
uses: ./
with:
workingDirectory: "./src/test/fixtures/pre-installed-wrangler"
command: action-test
+2 -1
View File
@@ -27,7 +27,8 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "latest"
# Pinned due to compatibility issues on 23.2.0
node-version: "22"
cache: "npm"
- name: Install modules
+24
View File
@@ -0,0 +1,24 @@
on:
pull_request: {}
workflow_dispatch: {}
push:
branches:
- main
- master
schedule:
- cron: "0 0 * * *"
name: Semgrep config
jobs:
semgrep:
name: semgrep/ci
runs-on: ubuntu-latest
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
SEMGREP_URL: https://cloudflare.semgrep.dev
SEMGREP_APP_URL: https://cloudflare.semgrep.dev
SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- run: semgrep ci
+12 -4
View File
@@ -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}`);
@@ -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);
-1
View File
@@ -1,4 +1,3 @@
dist
.idea
.vscode
+72
View File
@@ -1,5 +1,77 @@
# Changelog
## 3.13.1
### Patch Changes
- [#345](https://github.com/cloudflare/wrangler-action/pull/345) [`e819570`](https://github.com/cloudflare/wrangler-action/commit/e819570b2d0a69816a1c2e9d2f2954e278748d80) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - fix: Pages GitHub Deployment not triggering
## 3.13.0
### Minor Changes
- [#325](https://github.com/cloudflare/wrangler-action/pull/325) [`cada7a6`](https://github.com/cloudflare/wrangler-action/commit/cada7a63124ded3471bef7e8001b76356b838e40) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - Add GitHub deployments and job summaries for parity with pages-action
- [#334](https://github.com/cloudflare/wrangler-action/pull/334) [`9fed19a`](https://github.com/cloudflare/wrangler-action/commit/9fed19aa4ed79946f009e8aad7437a922e62d523) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - Bump default wrangler version to 3.90.0
## 3.12.1
### Patch Changes
- [#319](https://github.com/cloudflare/wrangler-action/pull/319) [`59c04629408d58978884fadd18755f1a15f96157`](https://github.com/cloudflare/wrangler-action/commit/59c04629408d58978884fadd18755f1a15f96157) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - Fixes #317: Generate a new output directory with a randomUUID in the tmpDir, so that when the action is executed multiple times, we use the artifacts from that run, opposed to the artifacts from a previous run.
## 3.12.0
### Minor Changes
- [#312](https://github.com/cloudflare/wrangler-action/pull/312) [`122ee5cf5b66847e0b6cfa67ecd9e03e38a67a42`](https://github.com/cloudflare/wrangler-action/commit/122ee5cf5b66847e0b6cfa67ecd9e03e38a67a42) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - This reapplies [303](https://github.com/cloudflare/wrangler-action/pull/303) add parity with pages-action for pages deploy outputs. Thanks @courtney-sims! - Support pages-deployment-id, pages-environment, pages-deployment-alias-url and deployment-url outputs for Pages deploys when wrangler version is >=3.81.0. deployment-alias-url was also deprecated in favour of pages-deployment-alias.
## 3.11.0
### Minor Changes
- [#309](https://github.com/cloudflare/wrangler-action/pull/309) [`10d5b9c1c1826adaec0a9ee49fdf5b91113508ef`](https://github.com/cloudflare/wrangler-action/commit/10d5b9c1c1826adaec0a9ee49fdf5b91113508ef) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - Revert "Add parity with pages-action for pages deploy outputs"
## 3.10.0
### Minor Changes
- [#303](https://github.com/cloudflare/wrangler-action/pull/303) [`3ec7f8943ef83351f743cfaa8763a9056ef70993`](https://github.com/cloudflare/wrangler-action/commit/3ec7f8943ef83351f743cfaa8763a9056ef70993) Thanks [@courtney-sims](https://github.com/courtney-sims)! - Support id, environment, url, and alias outputs for Pages deploys.
## 3.9.0
### Minor Changes
- [#298](https://github.com/cloudflare/wrangler-action/pull/298) [`134b5c2a3252d66b8c4d1cddd0b9baaeed6a4daa`](https://github.com/cloudflare/wrangler-action/commit/134b5c2a3252d66b8c4d1cddd0b9baaeed6a4daa) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - Update wrangler version from 3.13.2 to 3.78.10
### Patch Changes
- [#278](https://github.com/cloudflare/wrangler-action/pull/278) [`47d51f25c113ee9205110728599b43ed6a1e273b`](https://github.com/cloudflare/wrangler-action/commit/47d51f25c113ee9205110728599b43ed6a1e273b) Thanks [@acusti](https://github.com/acusti)! - fix: Detect existing wrangler install even when wrangler version output is multiline
## 3.8.0
### Minor Changes
- [#291](https://github.com/cloudflare/wrangler-action/pull/291) [`a1467a0c8f2a058f8d43a4d0c40a55176ed5efe6`](https://github.com/cloudflare/wrangler-action/commit/a1467a0c8f2a058f8d43a4d0c40a55176ed5efe6) Thanks [@Ambroos](https://github.com/Ambroos)! - Adds `deployment-alias-url` output for Pages deployment aliases (since Wrangler v3.78.0): https://github.com/cloudflare/workers-sdk/pull/6643
## 3.7.0
### Minor Changes
- [#271](https://github.com/cloudflare/wrangler-action/pull/271) [`66efca2cbb82a5a49df6af2e14c4b58d53b0e266`](https://github.com/cloudflare/wrangler-action/commit/66efca2cbb82a5a49df6af2e14c4b58d53b0e266) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - This unreverts #235 ensuring wrangler-action will re-use existing wrangler installations, thanks @AdiRishi! and ensures we don't automatically install wrangler when checking if it present
## 3.6.1
### Patch Changes
- [#265](https://github.com/cloudflare/wrangler-action/pull/265) [`2d275a8f2d279dc91912c1ff8023af109ef3280c`](https://github.com/cloudflare/wrangler-action/commit/2d275a8f2d279dc91912c1ff8023af109ef3280c) Thanks [@Maximo-Guk](https://github.com/Maximo-Guk)! - Reverts #235 which may have caused the latest version of wrangler to be installed, if no wrangler version was found
## 3.6.0
### Minor Changes
- [#235](https://github.com/cloudflare/wrangler-action/pull/235) [`0545ad285acaff2b92053d636ee17fb303b4c5f5`](https://github.com/cloudflare/wrangler-action/commit/0545ad285acaff2b92053d636ee17fb303b4c5f5) Thanks [@AdiRishi](https://github.com/AdiRishi)! - wrangler-action will now re-use existing wrangler installations when available
## 3.5.0
### Minor Changes
+2 -2
View File
@@ -1,3 +1,3 @@
* @cloudflare/wrangler
* @cloudflare/wrangler @cloudflare/banda-team
CHANGELOG.md @cloudflare/wrangler-admins
CHANGELOG.md @cloudflare/wrangler-admins @cloudflare/banda-team
+21
View File
@@ -0,0 +1,21 @@
# Contributing Guide
## Releases
### Changesets
Every non-trivial change to the project - those that should appear in the changelog - must be captured in a "changeset". We use the changesets tool for creating changesets, publishing versions and updating the changelog.
Create a changeset for the current change.
> npx changeset
> Select which workspaces are affected by the change and whether the version requires a major, minor or patch release.
> Update the generated changeset with a description of the change.
> Include the generate changeset in the current commit.
> git add ./changeset/\*.md
### Version Packages PRs
Once you merge your PR, a new Version Packages PR will be opened in the wrangler-action repo. Once that PR is merged, your change will be released. Example: https://github.com/cloudflare/wrangler-action/pull/305
Note: Version Packages PRs are only generated if there's been at least one PR merged with a changeset.
+58 -5
View File
@@ -76,7 +76,7 @@ jobs:
workingDirectory: "subfoldername"
```
[Worker secrets](https://developers.cloudflare.com/workers/tooling/wrangler/secrets/) can optionally be passed in via `secrets` as a string of names separated by newlines. Each secret name must match the name of an environment variable specified in the `env` field. This creates or replaces the value for the Worker secret using the `wrangler secret put` command.
[Worker secrets](https://developers.cloudflare.com/workers/tooling/wrangler/secrets/) can optionally be passed in via `secrets` as a string of names separated by newlines. Each secret name must match the name of an environment variable specified in the `env` field. This creates or replaces the value for the Worker secret using the `wrangler secret put` command. It's also possible to specify worker environment using environment parameter.
```yaml
jobs:
@@ -85,6 +85,7 @@ jobs:
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
environment: production
secrets: |
SECRET1
SECRET2
@@ -121,6 +122,20 @@ jobs:
command: whoami
```
You can also add a command that spans multiple lines:
```yaml
jobs:
deploy:
steps:
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: |
pages project list
pages deploy .vercel/output/static --project-name=demo-actions --branch=test
```
## Use cases
### Deploy when commits are merged to main
@@ -158,6 +173,9 @@ jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
permissions:
contents: read
deployments: write
steps:
- uses: actions/checkout@v4
- name: Deploy
@@ -166,6 +184,8 @@ jobs:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy YOUR_DIST_FOLDER --project-name=example
# Optional: Enable this if you want to have GitHub Deployments triggered
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
```
### Deploying on a schedule
@@ -220,7 +240,7 @@ For more advanced usage or to programmatically trigger the workflow from scripts
### Upload a Worker Version
To create a new version of your Worker that is not deployed immediately, use the `wrangler versions upload --experimental-versions` command. Worker versions created in this way can then be deployed all at once at a later time or gradually deployed using the `wranger versions deploy --experimental-versions` command or via the Cloudflare dashboard under the Deployments tab. For now, the `--experimental-versions` flag and wrangler v3.40.0 or above is required to use this feature.
To create a new version of your Worker that is not deployed immediately, use the `wrangler versions upload` command. Worker versions created in this way can then be deployed all at once at a later time or gradually deployed using the `wrangler versions deploy` command or via the Cloudflare dashboard under the Deployments tab. Wrangler v3.40.0 or above is required to use this feature.
```yaml
jobs:
@@ -234,11 +254,27 @@ jobs:
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: versions upload --experimental-versions
command: versions upload
```
## Advanced Usage
### Setting A Worker Secret for A Specific Environment
There is an environment parameter that can be set within the workflow to enable this. Example:
```yaml
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env production
secrets: |
SUPER_SECRET
environment: production
env:
SUPER_SECRET: ${{ secrets.SUPER_SECRET }}
```
### Using Wrangler Command Output in Subsequent Steps
More advanced workflows may need to parse the resulting output of Wrangler commands. To do this, you can use the `command-output` output variable in subsequent steps. For example, if you want to print the output of the Wrangler command, you can do the following:
@@ -262,7 +298,7 @@ Now when you run your workflow, you will see the full output of the Wrangler com
> Note: the `command-stderr` output variable is also available if you need to parse the standard error output of the Wrangler command.
### Using the `deployment-url` Output Variable
### Using the `deployment-url` and `pages-deployment-alias-url` Output Variables
If you are executing a Wrangler command that results in either a Workers or Pages deployment, you can utilize the `deployment-url` output variable to get the URL of the deployment. For example, if you want to print the deployment URL after deploying your application, you can do the following:
@@ -287,9 +323,26 @@ The resulting output will look something like this:
https://<your_pages_site>.pages.dev
```
Pages deployments will also provide their alias URL (since Wrangler v3.78.0). You can use the `pages-deployment-alias-url` output variable to get the URL of the deployment alias. This is useful for, for example, branch aliases for preview deployments.
If the sample action above was used to deploy a branch other than main, you could use the following to get the branch URL:
```yaml
- name: print pages-deployment-alias-url
env:
DEPLOYMENT_ALIAS_URL: ${{ steps.deploy.outputs.pages-deployment-alias-url }}
run: echo $DEPLOYMENT_ALIAS_URL
```
Resulting in:
```text
https://new-feature.<your_pages_site>.pages.dev
```
### Using a different package manager
By default, this action will detect which package manager to use, based on the presence of a `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, or `bun.lockb` file.
By default, this action will detect which package manager to use, based on the presence of a `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, or `bun.lockb`/`bun.lock` file.
If you need to use a specific package manager for your application, you can set the `packageManager` input to `npm`, `yarn`, `pnpm`, or `bun`. You don't need to set this option unless you want to override the default behavior.
+9
View File
@@ -44,6 +44,9 @@ inputs:
packageManager:
description: "The package manager you'd like to use to install and run wrangler. If not specified, the preferred package manager will be inferred based on the presence of a lockfile or fallback to using npm if no lockfile is found. Valid values are `npm` | `pnpm` | `yarn` | `bun`."
required: false
gitHubToken:
description: "GitHub Token"
required: false
outputs:
command-output:
description: "The output of the Wrangler command (comes from stdout)"
@@ -51,3 +54,9 @@ outputs:
description: "The error output of the Wrangler command (comes from stderr)"
deployment-url:
description: "If the command was a Workers or Pages deployment, this will be the URL of the deployment"
pages-deployment-alias-url:
description: "If the command was a Pages deployment, this will be the URL of the deployment alias (if it exists) - needs wrangler >= 3.78.0"
pages-deployment-id:
description: "If the command was a Pages deployment, this will be the ID of the deployment - needs wrangler >= 3.81.0"
pages-environment:
description: "If the command was a Pages deployment, this will be the environment of the deployment - needs wrangler >= 3.81.0"
+2
View File
@@ -0,0 +1,2 @@
import { WranglerActionConfig } from "./wranglerAction";
export declare function handleCommandOutputParsing(config: WranglerActionConfig, command: string, stdOut: string): Promise<void>;
+6
View File
@@ -0,0 +1,6 @@
import { exec as _childProcessExec } from "node:child_process";
export { exec } from "@actions/exec";
declare const childProcessExec: typeof _childProcessExec.__promisify__;
export declare function execShell(command: string, { silent, ...options }?: Parameters<typeof childProcessExec>[1] & {
silent?: boolean;
}): Promise<number | null>;
+1
View File
@@ -0,0 +1 @@
export {};
+37332
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
+24
View File
@@ -0,0 +1,24 @@
export interface PackageManager {
install: string;
exec: string;
execNoInstall: string;
}
export declare function getPackageManager(name: string, { workingDirectory }?: {
workingDirectory?: string;
}): {
readonly install: "npm i";
readonly exec: "npx";
readonly execNoInstall: "npx --no-install";
} | {
readonly install: "yarn add";
readonly exec: "yarn";
readonly execNoInstall: "yarn";
} | {
readonly install: "pnpm add";
readonly exec: "pnpm exec";
readonly execNoInstall: "pnpm exec";
} | {
readonly install: "bun i";
readonly exec: "bunx";
readonly execNoInstall: "bun run";
};
+1
View File
@@ -0,0 +1 @@
export {};
+23
View File
@@ -0,0 +1,23 @@
import { getOctokit } from "@actions/github";
import { OutputEntryPagesDeployment } from "../wranglerArtifactManager";
import { WranglerActionConfig } from "../wranglerAction";
type Octokit = ReturnType<typeof getOctokit>;
export declare function createGitHubDeployment({ config, octokit, productionBranch, environment, deploymentId, projectName, deploymentUrl, }: {
config: WranglerActionConfig;
octokit: Octokit;
productionBranch: string;
environment: string;
deploymentId: string | null;
projectName: string;
deploymentUrl?: string;
}): Promise<void>;
export declare function createJobSummary({ commitHash, deploymentUrl, aliasUrl, }: {
commitHash: string;
deploymentUrl?: string;
aliasUrl?: string;
}): Promise<void>;
/**
* Create github deployment, if GITHUB_TOKEN is present in config
*/
export declare function createGitHubDeploymentAndJobSummary(config: WranglerActionConfig, pagesArtifactFields: OutputEntryPagesDeployment): Promise<void>;
export {};
+1
View File
@@ -0,0 +1 @@
export {};
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+2
View File
@@ -0,0 +1,2 @@
declare const _default: {};
export default _default;
@@ -0,0 +1,2 @@
declare const _default: {};
export default _default;
+8
View File
@@ -0,0 +1,8 @@
type Env = {
SECRET1?: string;
SECRET2?: string;
};
declare const _default: {
fetch(request: Request, env: Env): Response;
};
export default _default;
+6
View File
@@ -0,0 +1,6 @@
export declare function mockGithubDeployments({ githubUser, githubRepoName, }: {
githubUser: string;
githubRepoName: string;
}): {
handlers: import("msw").HttpHandler[];
};
+4
View File
@@ -0,0 +1,4 @@
import { WranglerActionConfig } from "../wranglerAction";
export declare function getTestConfig({ config, }?: {
config?: Partial<WranglerActionConfig>;
}): WranglerActionConfig;
+9
View File
@@ -0,0 +1,9 @@
import { WranglerActionConfig } from "./wranglerAction";
/**
* A helper function to compare two semver versions. If the second arg is greater than the first arg, it returns true.
*/
export declare function semverCompare(version1: string, version2: string): boolean;
export declare function checkWorkingDirectory(workingDirectory?: string): string;
export declare function info(config: WranglerActionConfig, message: string, bypass?: boolean): void;
export declare function warn(config: WranglerActionConfig, message: string, bypass?: boolean): void;
export declare function error(config: WranglerActionConfig, message: string, bypass?: boolean): void;
+1
View File
@@ -0,0 +1 @@
export {};
+54
View File
@@ -0,0 +1,54 @@
import { z } from "zod";
import { PackageManager } from "./packageManagers";
import { info } from "./utils";
export type WranglerActionConfig = z.infer<typeof wranglerActionConfig>;
export declare const wranglerActionConfig: z.ZodObject<{
WRANGLER_VERSION: z.ZodString;
didUserProvideWranglerVersion: z.ZodBoolean;
secrets: z.ZodArray<z.ZodString, "many">;
workingDirectory: z.ZodString;
CLOUDFLARE_API_TOKEN: z.ZodString;
CLOUDFLARE_ACCOUNT_ID: z.ZodString;
ENVIRONMENT: z.ZodString;
VARS: z.ZodArray<z.ZodString, "many">;
COMMANDS: z.ZodArray<z.ZodString, "many">;
QUIET_MODE: z.ZodBoolean;
PACKAGE_MANAGER: z.ZodString;
WRANGLER_OUTPUT_DIR: z.ZodString;
GITHUB_TOKEN: z.ZodString;
}, "strip", z.ZodTypeAny, {
WRANGLER_VERSION: string;
didUserProvideWranglerVersion: boolean;
secrets: string[];
workingDirectory: string;
CLOUDFLARE_API_TOKEN: string;
CLOUDFLARE_ACCOUNT_ID: string;
ENVIRONMENT: string;
VARS: string[];
COMMANDS: string[];
QUIET_MODE: boolean;
PACKAGE_MANAGER: string;
WRANGLER_OUTPUT_DIR: string;
GITHUB_TOKEN: string;
}, {
WRANGLER_VERSION: string;
didUserProvideWranglerVersion: boolean;
secrets: string[];
workingDirectory: string;
CLOUDFLARE_API_TOKEN: string;
CLOUDFLARE_ACCOUNT_ID: string;
ENVIRONMENT: string;
VARS: string[];
COMMANDS: string[];
QUIET_MODE: boolean;
PACKAGE_MANAGER: string;
WRANGLER_OUTPUT_DIR: string;
GITHUB_TOKEN: string;
}>;
declare function main(config: WranglerActionConfig, packageManager: PackageManager): Promise<void>;
declare function installWrangler(config: WranglerActionConfig, packageManager: PackageManager): Promise<void>;
declare function authenticationSetup(config: WranglerActionConfig): void;
declare function execCommands(config: WranglerActionConfig, packageManager: PackageManager, commands: string[], cmdType: string): Promise<void>;
declare function uploadSecrets(config: WranglerActionConfig, packageManager: PackageManager): Promise<void>;
declare function wranglerCommands(config: WranglerActionConfig, packageManager: PackageManager): Promise<void>;
export { authenticationSetup, execCommands, info, installWrangler, main, uploadSecrets, wranglerCommands, };
+1
View File
@@ -0,0 +1 @@
export {};
+200
View File
@@ -0,0 +1,200 @@
import { z } from "zod";
export type OutputEntryPagesDeployment = z.infer<typeof OutputEntryPagesDeployment>;
declare const OutputEntryPagesDeployment: z.ZodObject<z.objectUtil.extendShape<{
version: z.ZodLiteral<1>;
type: z.ZodString;
}, {
type: z.ZodLiteral<"pages-deploy-detailed">;
pages_project: z.ZodNullable<z.ZodString>;
deployment_id: z.ZodNullable<z.ZodString>;
url: z.ZodOptional<z.ZodString>;
alias: z.ZodOptional<z.ZodString>;
environment: z.ZodEnum<["production", "preview"]>;
production_branch: z.ZodOptional<z.ZodString>;
deployment_trigger: z.ZodOptional<z.ZodObject<{
metadata: z.ZodObject<{
/** Commit hash of the deployment trigger metadata for the pages project */
commit_hash: z.ZodString;
}, "strip", z.ZodTypeAny, {
commit_hash: string;
}, {
commit_hash: string;
}>;
}, "strip", z.ZodTypeAny, {
metadata: {
commit_hash: string;
};
}, {
metadata: {
commit_hash: string;
};
}>>;
}>, "strip", z.ZodTypeAny, {
type: "pages-deploy-detailed";
environment: "production" | "preview";
version: 1;
pages_project: string | null;
deployment_id: string | null;
url?: string | undefined;
alias?: string | undefined;
production_branch?: string | undefined;
deployment_trigger?: {
metadata: {
commit_hash: string;
};
} | undefined;
}, {
type: "pages-deploy-detailed";
environment: "production" | "preview";
version: 1;
pages_project: string | null;
deployment_id: string | null;
url?: string | undefined;
alias?: string | undefined;
production_branch?: string | undefined;
deployment_trigger?: {
metadata: {
commit_hash: string;
};
} | undefined;
}>;
export type OutputEntryDeployment = z.infer<typeof OutputEntryDeployment>;
declare const OutputEntryDeployment: z.ZodObject<z.objectUtil.extendShape<{
version: z.ZodLiteral<1>;
type: z.ZodString;
}, {
type: z.ZodLiteral<"deploy">;
/** A list of URLs that represent the HTTP triggers associated with this deployment */
/** basically, for wrangler-action purposes this is the deployment urls */
targets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
}>, "strip", z.ZodTypeAny, {
type: "deploy";
version: 1;
targets?: string[] | undefined;
}, {
type: "deploy";
version: 1;
targets?: string[] | undefined;
}>;
export type OutputEntryVersionUpload = z.infer<typeof OutputEntryVersionUpload>;
declare const OutputEntryVersionUpload: z.ZodObject<z.objectUtil.extendShape<{
version: z.ZodLiteral<1>;
type: z.ZodString;
}, {
type: z.ZodLiteral<"version-upload">;
/** The preview URL associated with this version upload */
preview_url: z.ZodOptional<z.ZodString>;
}>, "strip", z.ZodTypeAny, {
type: "version-upload";
version: 1;
preview_url?: string | undefined;
}, {
type: "version-upload";
version: 1;
preview_url?: string | undefined;
}>;
export type SupportedOutputEntry = z.infer<typeof SupportedOutputEntry>;
declare const SupportedOutputEntry: z.ZodDiscriminatedUnion<"type", [z.ZodObject<z.objectUtil.extendShape<{
version: z.ZodLiteral<1>;
type: z.ZodString;
}, {
type: z.ZodLiteral<"pages-deploy-detailed">;
pages_project: z.ZodNullable<z.ZodString>;
deployment_id: z.ZodNullable<z.ZodString>;
url: z.ZodOptional<z.ZodString>;
alias: z.ZodOptional<z.ZodString>;
environment: z.ZodEnum<["production", "preview"]>;
production_branch: z.ZodOptional<z.ZodString>;
deployment_trigger: z.ZodOptional<z.ZodObject<{
metadata: z.ZodObject<{
/** Commit hash of the deployment trigger metadata for the pages project */
commit_hash: z.ZodString;
}, "strip", z.ZodTypeAny, {
commit_hash: string;
}, {
commit_hash: string;
}>;
}, "strip", z.ZodTypeAny, {
metadata: {
commit_hash: string;
};
}, {
metadata: {
commit_hash: string;
};
}>>;
}>, "strip", z.ZodTypeAny, {
type: "pages-deploy-detailed";
environment: "production" | "preview";
version: 1;
pages_project: string | null;
deployment_id: string | null;
url?: string | undefined;
alias?: string | undefined;
production_branch?: string | undefined;
deployment_trigger?: {
metadata: {
commit_hash: string;
};
} | undefined;
}, {
type: "pages-deploy-detailed";
environment: "production" | "preview";
version: 1;
pages_project: string | null;
deployment_id: string | null;
url?: string | undefined;
alias?: string | undefined;
production_branch?: string | undefined;
deployment_trigger?: {
metadata: {
commit_hash: string;
};
} | undefined;
}>, z.ZodObject<z.objectUtil.extendShape<{
version: z.ZodLiteral<1>;
type: z.ZodString;
}, {
type: z.ZodLiteral<"deploy">;
/** A list of URLs that represent the HTTP triggers associated with this deployment */
/** basically, for wrangler-action purposes this is the deployment urls */
targets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
}>, "strip", z.ZodTypeAny, {
type: "deploy";
version: 1;
targets?: string[] | undefined;
}, {
type: "deploy";
version: 1;
targets?: string[] | undefined;
}>, z.ZodObject<z.objectUtil.extendShape<{
version: z.ZodLiteral<1>;
type: z.ZodString;
}, {
type: z.ZodLiteral<"version-upload">;
/** The preview URL associated with this version upload */
preview_url: z.ZodOptional<z.ZodString>;
}>, "strip", z.ZodTypeAny, {
type: "version-upload";
version: 1;
preview_url?: string | undefined;
}, {
type: "version-upload";
version: 1;
preview_url?: string | undefined;
}>]>;
/**
* Parses file names in a directory to find wrangler artifact files
*
* @param artifactDirectory
* @returns All artifact files from the directory
*/
export declare function getWranglerArtifacts(artifactDirectory: string): Promise<string[]>;
/**
* Searches for a supported wrangler OutputEntry
*
* @param artifactDirectory
* @returns The first SupportedOutputEntry found within a wrangler artifact directory
*/
export declare function getOutputEntry(artifactDirectory: string): Promise<SupportedOutputEntry | null>;
export {};
+1
View File
@@ -0,0 +1 @@
export {};
+1264 -2813
View File
File diff suppressed because it is too large Load Diff
+18 -12
View File
@@ -1,6 +1,6 @@
{
"name": "wrangler-action",
"version": "3.5.0",
"version": "3.13.1",
"description": "GitHub Action to use [Wrangler](https://developers.cloudflare.com/workers/cli-wrangler/).",
"author": "wrangler@cloudflare.com",
"license": "MIT OR Apache-2.0",
@@ -29,18 +29,24 @@
"check": "prettier --check ."
},
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1"
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/github": "^6.0.0",
"zod": "^3.23.8"
},
"devDependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.26.2",
"@cloudflare/workers-types": "^4.20231121.0",
"@types/node": "^20.10.4",
"@vercel/ncc": "^0.38.1",
"prettier": "^3.1.0",
"semver": "^7.5.4",
"typescript": "^5.3.3",
"vitest": "^1.0.3"
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.12",
"@cloudflare/workers-types": "^4.20241022.0",
"@types/mock-fs": "^4.13.4",
"@types/node": "^22.9.0",
"@types/semver": "^7.5.8",
"@vercel/ncc": "^0.38.2",
"mock-fs": "^5.4.1",
"msw": "^2.6.4",
"prettier": "^3.3.3",
"semver": "^7.6.3",
"typescript": "^5.6.3",
"vitest": "^2.1.9"
}
}
+180
View File
@@ -0,0 +1,180 @@
import { setOutput } from "@actions/core";
import { info, WranglerActionConfig } from "./wranglerAction";
import {
getOutputEntry,
OutputEntryDeployment,
OutputEntryPagesDeployment,
OutputEntryVersionUpload,
} from "./wranglerArtifactManager";
import { createGitHubDeploymentAndJobSummary } from "./service/github";
// fallback to trying to extract the deployment-url and pages-deployment-alias-url from stdout for wranglerVersion < 3.81.0
function extractDeploymentUrlsFromStdout(stdOut: string): {
deploymentUrl?: string;
aliasUrl?: string;
} {
let deploymentUrl = "";
let aliasUrl = "";
// Try to extract the deployment URL
const deploymentUrlMatch = stdOut.match(/https?:\/\/[a-zA-Z0-9-./]+/);
if (deploymentUrlMatch && deploymentUrlMatch[0]) {
deploymentUrl = deploymentUrlMatch[0].trim();
}
// And also try to extract the alias URL (since wrangler@3.78.0)
const aliasUrlMatch = stdOut.match(/alias URL: (https?:\/\/[a-zA-Z0-9-./]+)/);
if (aliasUrlMatch && aliasUrlMatch[1]) {
aliasUrl = aliasUrlMatch[1].trim();
}
return { deploymentUrl, aliasUrl };
}
async function handlePagesDeployOutputEntry(
config: WranglerActionConfig,
pagesDeployOutputEntry: OutputEntryPagesDeployment,
) {
setOutput("deployment-url", pagesDeployOutputEntry.url);
// DEPRECATED: deployment-alias-url in favour of pages-deployment-alias, drop in next wrangler-action major version change
setOutput("deployment-alias-url", pagesDeployOutputEntry.alias);
setOutput("pages-deployment-alias-url", pagesDeployOutputEntry.alias);
setOutput("pages-deployment-id", pagesDeployOutputEntry.deployment_id);
setOutput("pages-environment", pagesDeployOutputEntry.environment);
// Create github deployment, if GITHUB_TOKEN is present in config
await createGitHubDeploymentAndJobSummary(config, pagesDeployOutputEntry);
}
/**
* If no wrangler output file found, fallback to extracting deployment-url from stdout.
* @deprecated Use {@link handlePagesDeployOutputEntry} instead.
*/
function handlePagesDeployCommand(
config: WranglerActionConfig,
stdOut: string,
) {
info(
config,
"Unable to find a WRANGLER_OUTPUT_DIR, environment and id fields will be unavailable for output. Have you updated wrangler to version >=3.81.0?",
);
// DEPRECATED: deployment-alias-url in favour of pages-deployment-alias, drop in next wrangler-action major version change
const { deploymentUrl, aliasUrl } = extractDeploymentUrlsFromStdout(stdOut);
setOutput("deployment-url", deploymentUrl);
// DEPRECATED: deployment-alias-url in favour of pages-deployment-alias, drop in next wrangler-action major version change
setOutput("deployment-alias-url", aliasUrl);
setOutput("pages-deployment-alias-url", aliasUrl);
}
function handleWranglerDeployOutputEntry(
config: WranglerActionConfig,
wranglerDeployOutputEntry: OutputEntryDeployment,
) {
// If no deployment urls found in wrangler output file, log that we couldn't find any urls and return.
if (
!wranglerDeployOutputEntry.targets ||
wranglerDeployOutputEntry.targets.length === 0
) {
info(config, "No deployment-url found in wrangler deploy output file");
return;
}
// If more than 1 deployment url found, log that we're going to set deployment-url to the first match.
// In a future wrangler-action version we should consider how we're going to output multiple deployment-urls
if (wranglerDeployOutputEntry.targets.length > 1) {
info(
config,
"Multiple deployment urls found in wrangler deploy output file, deployment-url will be set to the first url",
);
}
setOutput("deployment-url", wranglerDeployOutputEntry.targets[0]);
}
/**
* If no wrangler output file found, fallback to extracting deployment-url from stdout.
* @deprecated Use {@link handleWranglerDeployOutputEntry} instead.
*/
function handleWranglerDeployCommand(
config: WranglerActionConfig,
stdOut: string,
) {
info(
config,
"Unable to find a WRANGLER_OUTPUT_DIR, deployment-url may have an unreliable output. Have you updated wrangler to version >=3.88.0?",
);
const { deploymentUrl } = extractDeploymentUrlsFromStdout(stdOut);
setOutput("deployment-url", deploymentUrl);
}
function handleVersionsUploadOutputEntry(
versionsOutputEntry: OutputEntryVersionUpload,
) {
setOutput("deployment-url", versionsOutputEntry.preview_url);
}
/**
* If no wrangler output file found, log a message stating deployment-url will be unavailable for output.
* @deprecated Use {@link handleVersionsOutputEntry} instead.
*/
function handleVersionsOutputCommand(config: WranglerActionConfig) {
info(
config,
"Unable to find a WRANGLER_OUTPUT_DIR, deployment-url will be unavailable for output. Have you updated wrangler to version >=3.88.0?",
);
}
function handleDeprectatedStdoutParsing(
config: WranglerActionConfig,
command: string,
stdOut: string,
) {
// Check if this command is a pages deployment
if (
command.startsWith("pages deploy") ||
command.startsWith("pages publish")
) {
handlePagesDeployCommand(config, stdOut);
return;
}
// Check if this command is a workers deployment
if (command.startsWith("deploy") || command.startsWith("publish")) {
handleWranglerDeployCommand(config, stdOut);
return;
}
// Check if this command is a versions deployment
if (command.startsWith("versions upload")) {
handleVersionsOutputCommand(config);
return;
}
}
export async function handleCommandOutputParsing(
config: WranglerActionConfig,
command: string,
stdOut: string,
) {
// get first OutputEntry found within wrangler artifact output directory
const outputEntry = await getOutputEntry(config.WRANGLER_OUTPUT_DIR);
if (outputEntry === null) {
// if no outputEntry found, fallback to deprecated stdOut parsing
handleDeprectatedStdoutParsing(config, command, stdOut);
return;
}
switch (outputEntry.type) {
case "pages-deploy-detailed":
await handlePagesDeployOutputEntry(config, outputEntry);
break;
case "deploy":
handleWranglerDeployOutputEntry(config, outputEntry);
break;
case "version-upload":
handleVersionsUploadOutputEntry(outputEntry);
break;
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ export async function execShell(
await promise;
return child.exitCode;
} catch (err: any) {
} catch (err) {
if (isExecAsyncException(err)) {
process.stderr.write(err.stderr);
throw new Error(`Process failed with exit code ${err.code}`);
+14 -281
View File
@@ -1,26 +1,18 @@
import {
getBooleanInput,
getInput,
getMultilineInput,
endGroup as originalEndGroup,
error as originalError,
info as originalInfo,
debug,
startGroup as originalStartGroup,
setFailed,
setOutput,
} from "@actions/core";
import { exec, execShell } from "./exec";
import { checkWorkingDirectory, semverCompare } from "./utils";
import { getBooleanInput, getInput, getMultilineInput } from "@actions/core";
import { tmpdir } from "os";
import { join } from "path";
import { getPackageManager } from "./packageManagers";
import { checkWorkingDirectory } from "./utils";
import { main, WranglerActionConfig } from "./wranglerAction";
const DEFAULT_WRANGLER_VERSION = "3.13.2";
const DEFAULT_WRANGLER_VERSION = "3.90.0";
/**
* A configuration object that contains all the inputs & immutable state for the action.
*/
const config = {
const config: WranglerActionConfig = {
WRANGLER_VERSION: getInput("wranglerVersion") || DEFAULT_WRANGLER_VERSION,
didUserProvideWranglerVersion: Boolean(getInput("wranglerVersion")),
secrets: getMultilineInput("secrets"),
workingDirectory: checkWorkingDirectory(getInput("workingDirectory")),
CLOUDFLARE_API_TOKEN: getInput("apiToken"),
@@ -30,274 +22,15 @@ const config = {
COMMANDS: getMultilineInput("command"),
QUIET_MODE: getBooleanInput("quiet"),
PACKAGE_MANAGER: getInput("packageManager"),
WRANGLER_OUTPUT_DIR: `${join(
tmpdir(),
`wranglerArtifacts-${crypto.randomUUID()}`,
)}`,
GITHUB_TOKEN: getInput("gitHubToken", { required: false }),
} as const;
const packageManager = getPackageManager(config.PACKAGE_MANAGER, {
workingDirectory: config.workingDirectory,
});
function info(message: string, bypass?: boolean): void {
if (!config.QUIET_MODE || bypass) {
originalInfo(message);
}
}
function error(message: string, bypass?: boolean): void {
if (!config.QUIET_MODE || bypass) {
originalError(message);
}
}
function startGroup(name: string): void {
if (!config.QUIET_MODE) {
originalStartGroup(name);
}
}
function endGroup(): void {
if (!config.QUIET_MODE) {
originalEndGroup();
}
}
async function main() {
try {
authenticationSetup();
await installWrangler();
await execCommands(getMultilineInput("preCommands"), "pre");
await uploadSecrets();
await wranglerCommands();
await execCommands(getMultilineInput("postCommands"), "post");
info("🏁 Wrangler Action completed", true);
} catch (err: unknown) {
err instanceof Error && error(err.message);
setFailed("🚨 Action failed");
}
}
async function installWrangler() {
if (config["WRANGLER_VERSION"].startsWith("1")) {
throw new Error(
`Wrangler v1 is no longer supported by this action. Please use major version 2 or greater`,
);
}
startGroup("📥 Installing Wrangler");
try {
await exec(
packageManager.install,
[`wrangler@${config["WRANGLER_VERSION"]}`],
{
cwd: config["workingDirectory"],
silent: config["QUIET_MODE"],
},
);
info(`✅ Wrangler installed`, true);
} finally {
endGroup();
}
}
function authenticationSetup() {
process.env.CLOUDFLARE_API_TOKEN = config["CLOUDFLARE_API_TOKEN"];
process.env.CLOUDFLARE_ACCOUNT_ID = config["CLOUDFLARE_ACCOUNT_ID"];
}
async function execCommands(commands: string[], cmdType: string) {
if (!commands.length) {
return;
}
startGroup(`🚀 Running ${cmdType}Commands`);
try {
for (const command of commands) {
const cmd = command.startsWith("wrangler")
? `${packageManager.exec} ${command}`
: command;
await execShell(cmd, {
cwd: config["workingDirectory"],
silent: config["QUIET_MODE"],
});
}
} finally {
endGroup();
}
}
function getSecret(secret: string) {
if (!secret) {
throw new Error("Secret name cannot be blank.");
}
const value = process.env[secret];
if (!value) {
throw new Error(`Value for secret ${secret} not found in environment.`);
}
return value;
}
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;
}
async function legacyUploadSecrets(
secrets: string[],
environment?: string,
workingDirectory?: string,
) {
for (const secret of secrets) {
const args = ["wrangler", "secret", "put", secret];
if (environment) {
args.push("--env", environment);
}
await exec(packageManager.exec, args, {
cwd: workingDirectory,
silent: config["QUIET_MODE"],
input: Buffer.from(getSecret(secret)),
});
}
}
async function uploadSecrets() {
const secrets: string[] = config["secrets"];
const environment = config["ENVIRONMENT"];
const workingDirectory = config["workingDirectory"];
if (!secrets.length) {
return;
}
startGroup("🔑 Uploading secrets...");
try {
if (semverCompare(config["WRANGLER_VERSION"], "3.4.0")) {
return legacyUploadSecrets(secrets, environment, workingDirectory);
}
const args = ["wrangler", "secret:bulk"];
if (environment) {
args.push("--env", environment);
}
await exec(packageManager.exec, args, {
cwd: workingDirectory,
silent: config["QUIET_MODE"],
input: Buffer.from(
JSON.stringify(
Object.fromEntries(
secrets.map((secret) => [secret, getSecret(secret)]),
),
),
),
});
} catch (err: unknown) {
if (err instanceof Error) {
error(err.message);
err.stack && debug(err.stack);
}
throw new Error(`Failed to upload secrets.`);
} finally {
endGroup();
}
}
async function wranglerCommands() {
startGroup("🚀 Running Wrangler Commands");
try {
const commands = config["COMMANDS"];
const environment = config["ENVIRONMENT"];
if (!commands.length) {
const wranglerVersion = config["WRANGLER_VERSION"];
const deployCommand = semverCompare("2.20.0", wranglerVersion)
? "deploy"
: "publish";
commands.push(deployCommand);
}
for (let command of commands) {
const args = [];
if (environment && !command.includes("--env")) {
args.push("--env", environment);
}
if (
config["VARS"].length &&
(command.startsWith("deploy") || command.startsWith("publish")) &&
!command.includes("--var")
) {
args.push("--var");
for (const v of config["VARS"]) {
args.push(`${v}:${getEnvVar(v)}`);
}
}
// Used for saving the wrangler output
let stdOut = "";
let stdErr = "";
// Construct the options for the exec command
const options = {
cwd: config["workingDirectory"],
silent: config["QUIET_MODE"],
listeners: {
stdout: (data: Buffer) => {
stdOut += data.toString();
},
stderr: (data: Buffer) => {
stdErr += data.toString();
},
},
};
// Execute the wrangler command
await exec(`${packageManager.exec} wrangler ${command}`, args, options);
// Set the outputs for the command
setOutput("command-output", stdOut);
setOutput("command-stderr", stdErr);
// Check if this command is a workers or pages deployment
if (
command.startsWith("deploy") ||
command.startsWith("publish") ||
command.startsWith("pages publish") ||
command.startsWith("pages deploy")
) {
// If this is a workers or pages deployment, try to extract the deployment URL
let deploymentUrl = "";
const deploymentUrlMatch = stdOut.match(/https?:\/\/[a-zA-Z0-9-./]+/);
if (deploymentUrlMatch && deploymentUrlMatch[0]) {
deploymentUrl = deploymentUrlMatch[0].trim();
setOutput("deployment-url", deploymentUrl);
}
}
}
} finally {
endGroup();
}
}
main();
export {
authenticationSetup,
execCommands,
installWrangler,
uploadSecrets,
wranglerCommands,
};
main(config, packageManager);
+62 -46
View File
@@ -3,92 +3,108 @@ import { getPackageManager } from "./packageManagers";
describe("getPackageManager", () => {
test("should use provided value instead of inferring from lockfile", () => {
expect(getPackageManager("npm", { workingDirectory: "test/npm" }))
.toMatchInlineSnapshot(`
expect(
getPackageManager("npm", { workingDirectory: "src/test/fixtures/npm" }),
).toMatchInlineSnapshot(`
{
"exec": "npx",
"execNoInstall": "npx --no-install",
"install": "npm i",
}
`);
expect(getPackageManager("yarn", { workingDirectory: "test/npm" }))
.toMatchInlineSnapshot(`
{
"exec": "yarn",
"install": "yarn add",
}
`);
expect(
getPackageManager("yarn", { workingDirectory: "src/test/fixtures/npm" }),
).toMatchInlineSnapshot(`
{
"exec": "yarn",
"execNoInstall": "yarn",
"install": "yarn add",
}
`);
expect(getPackageManager("pnpm", { workingDirectory: "test/npm" }))
.toMatchInlineSnapshot(`
expect(
getPackageManager("pnpm", { workingDirectory: "src/test/fixtures/npm" }),
).toMatchInlineSnapshot(`
{
"exec": "pnpm exec",
"execNoInstall": "pnpm exec",
"install": "pnpm add",
}
`);
expect(getPackageManager("bun", { workingDirectory: "test/bun" }))
.toMatchInlineSnapshot(`
expect(
getPackageManager("bun", { workingDirectory: "src/test/fixtures/bun" }),
).toMatchInlineSnapshot(`
{
"exec": "bunx",
"execNoInstall": "bun run",
"install": "bun i",
}
`);
});
test("should use npm if no value provided and package-lock.json exists", () => {
expect(getPackageManager("", { workingDirectory: "test/npm" }))
expect(getPackageManager("", { workingDirectory: "src/test/fixtures/npm" }))
.toMatchInlineSnapshot(`
{
"exec": "npx",
"install": "npm i",
}
`);
{
"exec": "npx",
"execNoInstall": "npx --no-install",
"install": "npm i",
}
`);
});
test("should use yarn if no value provided and yarn.lock exists", () => {
expect(getPackageManager("", { workingDirectory: "test/yarn" }))
.toMatchInlineSnapshot(`
{
"exec": "yarn",
"install": "yarn add",
}
`);
expect(
getPackageManager("", { workingDirectory: "src/test/fixtures/yarn" }),
).toMatchInlineSnapshot(`
{
"exec": "yarn",
"execNoInstall": "yarn",
"install": "yarn add",
}
`);
});
test("should use pnpm if no value provided and pnpm-lock.yaml exists", () => {
expect(getPackageManager("", { workingDirectory: "test/pnpm" }))
.toMatchInlineSnapshot(`
{
"exec": "pnpm exec",
"install": "pnpm add",
}
`);
expect(
getPackageManager("", { workingDirectory: "src/test/fixtures/pnpm" }),
).toMatchInlineSnapshot(`
{
"exec": "pnpm exec",
"execNoInstall": "pnpm exec",
"install": "pnpm add",
}
`);
});
test("should use bun if no value provided and bun.lockb exists", () => {
expect(getPackageManager("", { workingDirectory: "test/bun" }))
expect(getPackageManager("", { workingDirectory: "src/test/fixtures/bun" }))
.toMatchInlineSnapshot(`
{
"exec": "bunx",
"install": "bun i",
}
{
"exec": "bunx",
"execNoInstall": "bun run",
"install": "bun i",
}
`);
});
test("should use npm if no value provided and no lockfile is present", () => {
expect(getPackageManager("", { workingDirectory: "test/empty" }))
.toMatchInlineSnapshot(`
{
"exec": "npx",
"install": "npm i",
}
`);
expect(
getPackageManager("", { workingDirectory: "src/test/fixtures/empty" }),
).toMatchInlineSnapshot(`
{
"exec": "npx",
"execNoInstall": "npx --no-install",
"install": "npm i",
}
`);
});
test("should throw if an invalid value is provided", () => {
expect(() =>
getPackageManager("cargo", { workingDirectory: "test/npm" }),
getPackageManager("cargo", { workingDirectory: "src/test/fixtures/npm" }),
).toThrowError();
});
});
+10 -2
View File
@@ -1,27 +1,32 @@
import { existsSync } from "node:fs";
import * as path from "node:path";
interface PackageManager {
export interface PackageManager {
install: string;
exec: string;
execNoInstall: string;
}
const PACKAGE_MANAGERS = {
npm: {
install: "npm i",
exec: "npx",
execNoInstall: "npx --no-install",
},
yarn: {
install: "yarn add",
exec: "yarn",
execNoInstall: "yarn",
},
pnpm: {
install: "pnpm add",
exec: "pnpm exec",
execNoInstall: "pnpm exec",
},
bun: {
install: "bun i",
exec: "bunx",
execNoInstall: "bun run",
},
} as const satisfies Readonly<Record<string, PackageManager>>;
@@ -39,7 +44,10 @@ function detectPackageManager(
if (existsSync(path.join(workingDirectory, "pnpm-lock.yaml"))) {
return "pnpm";
}
if (existsSync(path.join(workingDirectory, "bun.lockb"))) {
if (
existsSync(path.join(workingDirectory, "bun.lockb")) ||
existsSync(path.join(workingDirectory, "bun.lock"))
) {
return "bun";
}
return null;
+59
View File
@@ -0,0 +1,59 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { setupServer } from "msw/node";
import { createGitHubDeployment, createJobSummary } from "./github";
import { getOctokit } from "@actions/github";
import { mockGithubDeployments } from "../test/mocks";
import { getTestConfig } from "../test/test-utils";
import mockfs from "mock-fs";
import { readFile } from "fs/promises";
afterEach(() => {
mockfs.restore();
});
describe("github", () => {
it("Calls createGitHubDeployment successfully", async () => {
const githubUser = "mock-user";
const githubRepoName = "wrangler-action";
const server = setupServer(
...mockGithubDeployments({ githubUser, githubRepoName }).handlers,
);
server.listen({ onUnhandledRequest: "error" });
vi.stubEnv("GITHUB_REPOSITORY", `${githubUser}/${githubRepoName}`);
const testConfig = getTestConfig();
const octokit = getOctokit(testConfig.GITHUB_TOKEN, { request: fetch });
await createGitHubDeployment({
config: testConfig,
octokit,
productionBranch: "production-branch",
deploymentId: "fake-deployment-id",
projectName: "fake-project-name",
deploymentUrl: "https://fake-deployment-url.com",
environment: "production",
});
server.close();
});
it("Calls createJobSummary successfully", async () => {
vi.stubEnv("GITHUB_STEP_SUMMARY", "summary");
mockfs({
summary: mockfs.file(),
});
await createJobSummary({
commitHash: "fake-commit-hash",
deploymentUrl: "https://fake-deployment-url.com",
aliasUrl: "https://fake-alias-url.com",
});
expect((await readFile("summary")).toString()).toMatchInlineSnapshot(`
"
# Deploying with Cloudflare Pages
| Name | Result |
| ----------------------- | - |
| **Last commit:** | fake-commit-hash |
| **Preview URL**: | https://fake-deployment-url.com |
| **Branch Preview URL**: | https://fake-alias-url.com |
"
`);
});
});
+128
View File
@@ -0,0 +1,128 @@
import { summary } from "@actions/core";
import { context, getOctokit } from "@actions/github";
import { env } from "process";
import { info, warn } from "../utils";
import { OutputEntryPagesDeployment } from "../wranglerArtifactManager";
import { WranglerActionConfig } from "../wranglerAction";
type Octokit = ReturnType<typeof getOctokit>;
export async function createGitHubDeployment({
config,
octokit,
productionBranch,
environment,
deploymentId,
projectName,
deploymentUrl,
}: {
config: WranglerActionConfig;
octokit: Octokit;
productionBranch: string;
environment: string;
deploymentId: string | null;
projectName: string;
deploymentUrl?: string;
}) {
const githubBranch = env.GITHUB_HEAD_REF || env.GITHUB_REF_NAME;
const productionEnvironment = githubBranch === productionBranch;
const deployment = await octokit.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: githubBranch || context.ref,
auto_merge: false,
description: "Cloudflare Pages",
required_contexts: [],
environment,
production_environment: productionEnvironment,
});
if (deployment.status !== 201) {
info(config, "Error creating GitHub deployment");
return;
}
await octokit.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deployment.data.id,
environment,
environment_url: deploymentUrl,
production_environment: productionEnvironment,
// don't have project_name or deployment_id I think
log_url: `https://dash.cloudflare.com/${config.CLOUDFLARE_ACCOUNT_ID}/pages/view/${projectName}/${deploymentId}`,
description: "Cloudflare Pages",
state: "success",
auto_inactive: false,
});
}
export async function createJobSummary({
commitHash,
deploymentUrl,
aliasUrl,
}: {
commitHash: string;
deploymentUrl?: string;
aliasUrl?: string;
}) {
await summary
.addRaw(
`
# Deploying with Cloudflare Pages
| Name | Result |
| ----------------------- | - |
| **Last commit:** | ${commitHash} |
| **Preview URL**: | ${deploymentUrl} |
| **Branch Preview URL**: | ${aliasUrl} |
`,
)
.write();
}
/**
* Create github deployment, if GITHUB_TOKEN is present in config
*/
export async function createGitHubDeploymentAndJobSummary(
config: WranglerActionConfig,
pagesArtifactFields: OutputEntryPagesDeployment,
) {
if (
config.GITHUB_TOKEN &&
pagesArtifactFields.production_branch &&
pagesArtifactFields.pages_project &&
pagesArtifactFields.deployment_trigger
) {
const octokit = getOctokit(config.GITHUB_TOKEN);
const [createGitHubDeploymentRes, createJobSummaryRes] =
await Promise.allSettled([
createGitHubDeployment({
config,
octokit,
deploymentUrl: pagesArtifactFields.url,
productionBranch: pagesArtifactFields.production_branch,
environment: pagesArtifactFields.environment,
deploymentId: pagesArtifactFields.deployment_id,
projectName: pagesArtifactFields.pages_project,
}),
createJobSummary({
commitHash:
pagesArtifactFields.deployment_trigger.metadata.commit_hash.substring(
0,
8,
),
deploymentUrl: pagesArtifactFields.url,
aliasUrl: pagesArtifactFields.alias,
}),
]);
if (createGitHubDeploymentRes.status === "rejected") {
warn(config, "Creating Github Deployment failed");
}
if (createJobSummaryRes.status === "rejected") {
warn(config, "Creating Github Job summary failed");
}
}
}
@@ -17,7 +17,6 @@ export default {
return new Response("OK");
}
// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
+4
View File
@@ -0,0 +1,4 @@
name = "wrangler-action-test-build-quiet"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
-1
View File
@@ -17,7 +17,6 @@ export default {
return new Response("OK");
}
// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
@@ -12,7 +12,6 @@ export default {
return new Response(`${SECRET1} ${SECRET2}`);
}
// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
-1
View File
@@ -17,7 +17,6 @@ export default {
return new Response("OK");
}
// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
@@ -17,7 +17,6 @@ export default {
return new Response("OK");
}
// @ts-expect-error
return Response.json({
...request,
headers: Object.fromEntries(request.headers),
+10
View File
@@ -0,0 +1,10 @@
{
"name": "wrangler-action-test",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wrangler-action-test"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"name": "wrangler-action-test",
"license": "MIT",
"private": true
}
@@ -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
+25
View File
@@ -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),
});
},
};
+25
View File
@@ -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),
});
},
};
@@ -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);
}
@@ -0,0 +1,7 @@
{
"private": true,
"name": "wrangler",
"version": "1.1.1",
"main": "index.js",
"bin": "index.js"
}
+30
View File
@@ -0,0 +1,30 @@
{
"name": "wrangler-action-pre-installed-wrangler-test",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "wrangler-action-pre-installed-wrangler-test",
"license": "MIT",
"devDependencies": {
"wrangler": "file:mock_packages/wrangler"
}
},
"mock_packages/wrangler": {
"version": "1.1.1",
"dev": true,
"bin": {
"wrangler": "index.js"
}
},
"node_modules/wrangler": {
"resolved": "mock_packages/wrangler",
"link": true
}
},
"dependencies": {
"wrangler": {
"version": "file:mock_packages/wrangler"
}
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"name": "wrangler-action-pre-installed-wrangler-test",
"license": "MIT",
"private": true,
"devDependencies": {
"wrangler": "file:mock_packages/wrangler"
}
}
+25
View File
@@ -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
View File
@@ -0,0 +1,10 @@
{
"name": "wrangler-action-test",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wrangler-action-test"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"name": "wrangler-action-test",
"license": "MIT",
"private": true
}
+4
View File
@@ -0,0 +1,4 @@
name = "wrangler-action-test-secrets-default"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
+25
View File
@@ -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
View File
@@ -0,0 +1,10 @@
{
"name": "wrangler-action-test",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wrangler-action-test"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"name": "wrangler-action-test",
"license": "MIT",
"private": true
}
@@ -1,4 +1,4 @@
name = "wrangler-action-test"
name = "wrangler-action-test-secrets-v2"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
@@ -0,0 +1,4 @@
name = "wrangler-action-test-specify-package-manager"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
@@ -0,0 +1 @@
export default {};
@@ -0,0 +1,5 @@
{
"name": "wrangler-action-detect-package-manager-test",
"license": "MIT",
"private": true
}
@@ -0,0 +1,4 @@
name = "wrangler-action-test-unspecified-package-manager"
main = "./index.ts"
compatibility_date = "2023-07-07"
workers_dev = true
+25
View File
@@ -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),
});
},
};
+34
View File
@@ -0,0 +1,34 @@
import { http, HttpResponse } from "msw";
import { z } from "zod";
export function mockGithubDeployments({
githubUser,
githubRepoName,
}: {
githubUser: string;
githubRepoName: string;
}) {
return {
handlers: [
http.post(
`https://api.github.com/repos/${githubUser}/${githubRepoName}/deployments`,
async ({ request }) => {
if (request.headers.get("Authorization") === null) {
return HttpResponse.text("error: no auth token", { status: 400 });
}
const GithubDeploymentsRequest = z.object({
auto_merge: z.literal(false),
description: z.literal("Cloudflare Pages"),
required_contexts: z.array(z.string()).length(0),
environment: z.literal("production"),
production_environment: z.literal(false),
});
// validate request body
GithubDeploymentsRequest.parse(await request.json());
return HttpResponse.json(null);
},
),
],
};
}
+26
View File
@@ -0,0 +1,26 @@
import { WranglerActionConfig } from "../wranglerAction";
export function getTestConfig({
config = {},
}: {
config?: Partial<WranglerActionConfig>;
} = {}): WranglerActionConfig {
return Object.assign(
{
WRANGLER_VERSION: "3.81.0",
didUserProvideWranglerVersion: false,
secrets: [],
workingDirectory: "/src/test/fixtures",
CLOUDFLARE_API_TOKEN: "foo",
CLOUDFLARE_ACCOUNT_ID: "bar",
ENVIRONMENT: "dev",
VARS: [],
COMMANDS: [],
QUIET_MODE: false,
PACKAGE_MANAGER: "npm",
WRANGLER_OUTPUT_DIR: "/tmp/wranglerArtifacts",
GITHUB_TOKEN: "xxxxyy23213123132131",
} as const satisfies WranglerActionConfig,
config,
);
}

Some files were not shown because too many files have changed in this diff Show More