mirror of
https://github.com/cloudflare/wrangler-action.git
synced 2024-11-23 10:33:24 +01:00
feat: rewrite Wrangler Action in TypeScript
* Removes dependencies such as Docker, decreasing spin-up time * Adds community-requested features, including bulk secrets API utilization from Wrangler * Fixes CI/CD * Adds testing * Improves command implementation * Begins using Node for the Action engine/runner * Openly discusses all changes with the community GitHub Discussions opened and Issues monitored BREAKING CHANGES: * Docker is no longer a dependency * Wrangler v1 is no longer supported Additional related Internal tickets: Major Version Default: https://jira.cfdata.org/browse/DEVX-632 Rewrite Project: DEVX-804,802,800,632
This commit is contained in:
parent
4c10c1822a
commit
edb2a58814
29 changed files with 5153 additions and 424 deletions
159
.github/workflows/deploy.yml
vendored
159
.github/workflows/deploy.yml
vendored
|
@ -1,91 +1,110 @@
|
|||
on: push
|
||||
name: Wrangler Action Self Testing
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
wrangler_action_self_testing:
|
||||
runs-on: ubuntu-latest
|
||||
name: Lint
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Lint shell script
|
||||
uses: azohra/shell-linter@v0.3.0
|
||||
with:
|
||||
path: "entrypoint.sh"
|
||||
build-only:
|
||||
runs-on: ubuntu-latest
|
||||
name: Only build the app
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build app
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "latest"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Unit Tests
|
||||
run: npm run test
|
||||
|
||||
- name: Check Formatting
|
||||
run: npm run check
|
||||
|
||||
- name: Build Action
|
||||
run: npm run build
|
||||
|
||||
- name: Only build app
|
||||
uses: ./
|
||||
with:
|
||||
workingDirectory: "./test/base"
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
workingDirectory: "test"
|
||||
publish: false
|
||||
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"
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
environment: dev
|
||||
secrets: |
|
||||
SECRET1
|
||||
SECRET2
|
||||
preCommands: echo "*** pre commands ***"
|
||||
postCommands: |
|
||||
echo "*** post commands ***"
|
||||
wrangler build
|
||||
echo "******"
|
||||
env:
|
||||
SECRET1: ${{ secrets.SECRET1 }}
|
||||
SECRET2: ${{ secrets.SECRET2 }}
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
name: Publish app
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish app
|
||||
uses: ./
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
environment: "production"
|
||||
workingDirectory: 'test'
|
||||
publish_legacy_credentials:
|
||||
runs-on: ubuntu-latest
|
||||
name: Publish app with legacy credentials
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish app
|
||||
uses: ./
|
||||
with:
|
||||
apiKey: ${{ secrets.CLOUDFLARE_API_KEY }}
|
||||
email: ${{ secrets.CLOUDFLARE_EMAIL }}
|
||||
environment: "production"
|
||||
workingDirectory: 'test'
|
||||
publish_hardcoded_wrangler_version:
|
||||
runs-on: ubuntu-latest
|
||||
name: Publish app with hardcoded Wrangler version
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish app
|
||||
uses: ./
|
||||
with:
|
||||
apiKey: ${{ secrets.CLOUDFLARE_API_KEY }}
|
||||
email: ${{ secrets.CLOUDFLARE_EMAIL }}
|
||||
environment: "production"
|
||||
wranglerVersion: '1.5.0'
|
||||
workingDirectory: 'test'
|
||||
publish_secrets:
|
||||
runs-on: ubuntu-latest
|
||||
name: Publish app with secrets
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish app
|
||||
|
||||
- name: Clean up Deployed Environment Worker
|
||||
uses: ./
|
||||
with:
|
||||
workingDirectory: "./test/base"
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
environment: "production"
|
||||
workingDirectory: "test"
|
||||
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"
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
secrets: |
|
||||
SECRET1
|
||||
SECRET2
|
||||
preCommands: echo "*** pre command ***"
|
||||
postCommands: |
|
||||
echo "*** post commands ***"
|
||||
echo "******"
|
||||
env:
|
||||
SECRET1: ${{ secrets.SECRET1 }}
|
||||
SECRET2: ${{ secrets.SECRET2 }}
|
||||
SECRET2: ${{ secrets.SECRET2 }}
|
||||
|
||||
- name: Health Check Deployed Worker
|
||||
run: node .github/workflows/workerHealthCheck.cjs
|
||||
shell: bash
|
||||
|
||||
- name: Deploy app secrets w/ default version
|
||||
uses: ./
|
||||
with:
|
||||
workingDirectory: "./test/base"
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
secrets: |
|
||||
SECRET1
|
||||
SECRET2
|
||||
env:
|
||||
SECRET1: ${{ secrets.SECRET1 }}
|
||||
SECRET2: ${{ secrets.SECRET2 }}
|
||||
|
||||
- name: Health Check Deployed Worker
|
||||
run: node .github/workflows/workerHealthCheck.cjs
|
||||
shell: bash
|
||||
|
||||
- name: Clean Up Deployed Workers
|
||||
uses: ./
|
||||
with:
|
||||
workingDirectory: "./test/base"
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: delete --name wrangler-action-test --force
|
||||
# END Setup and teardown of Workers w/ Secrets Tests
|
||||
|
|
18
.github/workflows/workerHealthCheck.cjs
vendored
Normal file
18
.github/workflows/workerHealthCheck.cjs
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
const { execSync } = require("child_process");
|
||||
|
||||
function workerHealthCheck() {
|
||||
const url =
|
||||
"https://wrangler-action-test.devprod-testing7928.workers.dev/secret-health-check";
|
||||
|
||||
const buffer = execSync(`curl ${url}`);
|
||||
|
||||
const response = buffer.toString();
|
||||
|
||||
response.includes("OK")
|
||||
? console.log(`Status: Worker is up! Secrets: ${response}`)
|
||||
: console.log(`Worker is down!`);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
workerHealthCheck();
|
95
.gitignore
vendored
Normal file
95
.gitignore
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
dist
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Node ###
|
||||
node_modules
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
|
||||
# Moved from ./templates for ignoring all locks in templates
|
||||
templates/**/*-lock.*
|
||||
templates/**/*.lock
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
6
.prettierrc
Normal file
6
.prettierrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"printWidth": 80,
|
||||
"singleQuote": false,
|
||||
"semi": true,
|
||||
"useTabs": true
|
||||
}
|
64
CHANGELOG.md
64
CHANGELOG.md
|
@ -1,23 +1,61 @@
|
|||
# 2.0.0 (Breaking update)
|
||||
# Changelog
|
||||
|
||||
## Additions
|
||||
- [Version 3.0.0](#version-300)
|
||||
- [Version 2.0.0](#version-200)
|
||||
|
||||
* New `command` input
|
||||
* This allows you to specify the Wrangler command you would like to run.
|
||||
## Version 3.0.0 (Breaking update)
|
||||
|
||||
### Additions
|
||||
|
||||
- **Rewritten Wrangler Action in TypeScript.**
|
||||
- Bulk secrets API utilization from Wrangler.
|
||||
- Added testing for improved reliability.
|
||||
- Implemented multiline support for the `command` input to allow running multiple Wrangler commands.
|
||||
- Now using Node for the Action engine/runner.
|
||||
- Open discussions with the community on all changes through GitHub Discussions and monitored Issues.
|
||||
|
||||
### Removals
|
||||
|
||||
- Removed Docker as a dependency.
|
||||
- Dropped support for Wrangler v1.
|
||||
|
||||
### Changes
|
||||
|
||||
- Fixed CI/CD issues.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Wrangler v1 is no longer supported.
|
||||
- Please update to the latest version of Wrangler.
|
||||
- Updated default version of Wrangler to v3.4.0
|
||||
|
||||
### Additional Notes
|
||||
|
||||
- Major Version Default: [DEVX-632](https://jira.cfdata.org/browse/DEVX-632)
|
||||
- Rewrite Project Tickets: [DEVX-804](https://jira.cfdata.org/browse/DEVX-804), [DEVX-802](https://jira.cfdata.org/browse/DEVX-802), [DEVX-800](https://jira.cfdata.org/browse/DEVX-800), [DEVX-632](https://jira.cfdata.org/browse/DEVX-632)
|
||||
|
||||
---
|
||||
|
||||
## Version 2.0.0 (Breaking update)
|
||||
|
||||
### Additions
|
||||
|
||||
- New `command` input
|
||||
- This allows you to specify the Wrangler command you would like to run.
|
||||
For example, if you want to publish the production version of your Worker you may run `publish --env=production`.
|
||||
* This opens up other possibilities too like publishing a Pages project: `pages publish <directory> --project-name=<name>`.
|
||||
* New `accountId` input
|
||||
* This allows you to specify your account ID.
|
||||
- This opens up other possibilities too like publishing a Pages project: `pages publish <directory> --project-name=<name>`.
|
||||
- New `accountId` input
|
||||
- This allows you to specify your account ID.
|
||||
|
||||
## Removals
|
||||
### Removals
|
||||
|
||||
* Removed `publish` input (refer to [Breaking changes](#breaking-changes)).
|
||||
- Removed `publish` input (refer to [Breaking changes](#breaking-changes)).
|
||||
|
||||
## Changes
|
||||
### Changes
|
||||
|
||||
-- no changes --
|
||||
|
||||
## __Breaking changes__
|
||||
### Breaking changes
|
||||
|
||||
* `publish` has been removed.
|
||||
* You should instead do `command: publish`.
|
||||
- `publish` has been removed.
|
||||
- You should instead do `command:
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
FROM node:16
|
||||
ENV XDG_CONFIG_HOME /github/workspace
|
||||
ENV WRANGLER_HOME /github/workspace
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
44
README.md
44
README.md
|
@ -23,7 +23,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
```
|
||||
|
@ -39,7 +39,7 @@ jobs:
|
|||
deploy:
|
||||
name: Deploy
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
```
|
||||
|
@ -51,7 +51,7 @@ jobs:
|
|||
deploy:
|
||||
name: Deploy
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiKey: ${{ secrets.CF_API_KEY }}
|
||||
email: ${{ secrets.CF_EMAIL }}
|
||||
|
@ -65,10 +65,10 @@ If you need to install a specific version of Wrangler to use for deployment, you
|
|||
jobs:
|
||||
deploy:
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
wranglerVersion: '1.6.0'
|
||||
wranglerVersion: "1.6.0"
|
||||
```
|
||||
|
||||
Optionally, you can also pass a `workingDirectory` key to the action. This will allow you to specify a subdirectory of the repo to run the Wrangler command from.
|
||||
|
@ -77,24 +77,24 @@ Optionally, you can also pass a `workingDirectory` key to the action. This will
|
|||
jobs:
|
||||
deploy:
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
workingDirectory: 'subfoldername'
|
||||
workingDirectory: "subfoldername"
|
||||
```
|
||||
|
||||
[Worker secrets](https://developers.cloudflare.com/workers/tooling/wrangler/secrets/) can be optionally passed as a new line deliminated string of names in `secrets`. Each secret name must match an environment variable name specified in the `env` attribute. 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.
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deploy:
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
secrets: |
|
||||
SECRET1
|
||||
SECRET2
|
||||
SECRET1
|
||||
SECRET2
|
||||
env:
|
||||
SECRET1: ${{ secrets.SECRET1 }}
|
||||
SECRET2: ${{ secrets.SECRET2 }}
|
||||
|
@ -106,7 +106,7 @@ If you need to run additional shell commands before or after your command, you c
|
|||
jobs:
|
||||
deploy:
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
preCommands: echo "*** pre command ***"
|
||||
|
@ -122,7 +122,7 @@ You can use the `command` option to do specific actions such as running `wrangle
|
|||
jobs:
|
||||
deploy:
|
||||
steps:
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
command: whoami
|
||||
|
@ -147,7 +147,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Publish
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
```
|
||||
|
@ -168,7 +168,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Publish
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
|
@ -182,7 +182,7 @@ If you would like to deploy your Workers application on a recurring basis – fo
|
|||
```yaml
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 * * * *'
|
||||
- cron: "0 * * * *"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
|
@ -191,7 +191,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Publish app
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
```
|
||||
|
@ -207,9 +207,9 @@ on:
|
|||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Choose an environment to deploy to: <dev|staging|prod>'
|
||||
description: "Choose an environment to deploy to: <dev|staging|prod>"
|
||||
required: true
|
||||
default: 'dev'
|
||||
default: "dev"
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -217,7 +217,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Publish app
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
command: publish --env ${{ github.event.inputs.environment }}
|
||||
|
@ -245,8 +245,8 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Publish app
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
uses: cloudflare/wrangler-action@3.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
```
|
||||
```
|
||||
|
|
21
action.yml
21
action.yml
|
@ -2,17 +2,11 @@ name: "Deploy to Cloudflare Workers with Wrangler"
|
|||
branding:
|
||||
icon: "upload-cloud"
|
||||
color: "orange"
|
||||
description: "Deploy your Cloudflare Workers and Pages projects from GitHub using Wrangler"
|
||||
description: "Deploy your Cloudflare projects from GitHub using Wrangler"
|
||||
runs:
|
||||
using: "docker"
|
||||
image: "Dockerfile"
|
||||
using: "node16"
|
||||
main: "dist/index.js"
|
||||
inputs:
|
||||
apiKey:
|
||||
description: "(Legacy) Your Cloudflare API Key"
|
||||
required: false
|
||||
email:
|
||||
description: "(Legacy) Your Cloudflare Email"
|
||||
required: false
|
||||
apiToken:
|
||||
description: "Your Cloudflare API Token"
|
||||
required: false
|
||||
|
@ -29,7 +23,7 @@ inputs:
|
|||
description: "The version of Wrangler you'd like to use to publish your Workers project"
|
||||
required: false
|
||||
secrets:
|
||||
description: "A new line deliminated string of environment variable names that should be configured as Worker secrets"
|
||||
description: "A string of environment variable names, separated by newlines. These will be bound to your Worker as Secrets and must match the names of environment variables declared in `env` of this workflow."
|
||||
required: false
|
||||
preCommands:
|
||||
description: "Commands to execute before publishing the Workers project"
|
||||
|
@ -38,5 +32,8 @@ inputs:
|
|||
description: "Commands to execute after publishing the Workers project"
|
||||
required: false
|
||||
command:
|
||||
description: "The Wrangler command you wish to run. For example: \"publish\" - this will publish your Worker"
|
||||
required: false
|
||||
description: 'The Wrangler command (along with any arguments) you wish to run. Multiple Wrangler commands can be run by separating each command with a newline. Defaults to `"deploy"`.'
|
||||
required: false
|
||||
vars:
|
||||
description: "A string of environment variable names, separated by newlines. These will be bound to your Worker using the values of matching environment variables declared in `env` of this workflow."
|
||||
required: false
|
||||
|
|
161
entrypoint.sh
161
entrypoint.sh
|
@ -1,161 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export HOME="/github/workspace"
|
||||
export WRANGLER_HOME="/github/workspace"
|
||||
|
||||
mkdir -p "$HOME/.wrangler"
|
||||
chmod -R 770 "$HOME/.wrangler"
|
||||
|
||||
export API_CREDENTIALS=""
|
||||
|
||||
# Used to execute any specified pre and post commands
|
||||
execute_commands() {
|
||||
echo "$ Running: $1"
|
||||
COMMANDS=$1
|
||||
while IFS= read -r COMMAND; do
|
||||
CHUNKS=()
|
||||
|
||||
for CHUNK in $COMMAND; do
|
||||
CHUNKS+=("$CHUNK")
|
||||
done
|
||||
|
||||
eval "${CHUNKS[@]}"
|
||||
|
||||
CHUNKS=()
|
||||
done <<< "$COMMANDS"
|
||||
}
|
||||
|
||||
secret_not_found() {
|
||||
echo "::error::Specified secret \"$1\" not found in environment variables."
|
||||
exit 1
|
||||
}
|
||||
|
||||
WRANGLER_VERSION=2
|
||||
|
||||
# If no Wrangler version is specified install v2.
|
||||
if [ -z "$INPUT_WRANGLERVERSION" ]; then
|
||||
npm i -g wrangler
|
||||
|
||||
# If Wrangler version starts with 1 then install wrangler v1
|
||||
elif [[ "$INPUT_WRANGLERVERSION" == 1* ]]; then
|
||||
npm i -g "@cloudflare/wrangler@$INPUT_WRANGLERVERSION"
|
||||
WRANGLER_VERSION=1
|
||||
|
||||
# Else install Wrangler 2
|
||||
else
|
||||
npm i -g "wrangler@$INPUT_WRANGLERVERSION"
|
||||
WRANGLER_VERSION=2
|
||||
fi
|
||||
|
||||
# If an API token is detected as input
|
||||
if [ -n "$INPUT_APITOKEN" ]; then
|
||||
|
||||
# Wrangler v1 uses CF_API_TOKEN but v2 uses CLOUDFLARE_API_TOKEN
|
||||
if [ $WRANGLER_VERSION == 1 ]; then
|
||||
export CF_API_TOKEN="$INPUT_APITOKEN"
|
||||
else
|
||||
export CLOUDFLARE_API_TOKEN="$INPUT_APITOKEN"
|
||||
fi
|
||||
|
||||
export API_CREDENTIALS="API Token"
|
||||
fi
|
||||
|
||||
# If an API key and email are detected as input
|
||||
if [ -n "$INPUT_APIKEY" ] && [ -n "$INPUT_EMAIL" ]; then
|
||||
|
||||
# Wrangler v1 uses CF_ but v2 uses CLOUDFLARE_
|
||||
if [ $WRANGLER_VERSION == 1 ]; then
|
||||
export CF_EMAIL="$INPUT_EMAIL"
|
||||
export CF_API_KEY="$INPUT_APIKEY"
|
||||
else
|
||||
echo "::error::Wrangler v2 does not support using the API Key. You should instead use an API token."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export API_CREDENTIALS="Email and API Key"
|
||||
fi
|
||||
|
||||
if [ -n "$INPUT_ACCOUNTID" ]; then
|
||||
|
||||
if [ $WRANGLER_VERSION == 1 ]; then
|
||||
export CF_ACCOUNT_ID="$INPUT_ACCOUNTID"
|
||||
else
|
||||
export CLOUDFLARE_ACCOUNT_ID="$INPUT_ACCOUNTID"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ -n "$INPUT_APIKEY" ] && [ -z "$INPUT_EMAIL" ]
|
||||
then
|
||||
echo "Provided an API key without an email for authentication. Please pass in 'apiKey' and 'email' to the action."
|
||||
fi
|
||||
|
||||
if [ -z "$INPUT_APIKEY" ] && [ -n "$INPUT_EMAIL" ]
|
||||
then
|
||||
echo "Provided an email without an API key for authentication. Please pass in 'apiKey' and 'email' to the action."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$API_CREDENTIALS" ]
|
||||
then
|
||||
>&2 echo "Unable to find authentication details. Please pass in an 'apiToken' as an input to the action, or a legacy 'apiKey' and 'email'."
|
||||
exit 1
|
||||
else
|
||||
echo "Using $API_CREDENTIALS authentication"
|
||||
fi
|
||||
|
||||
# If a working directory is detected as input
|
||||
if [ -n "$INPUT_WORKINGDIRECTORY" ]
|
||||
then
|
||||
cd "$INPUT_WORKINGDIRECTORY"
|
||||
fi
|
||||
|
||||
# If precommands is detected as input
|
||||
if [ -n "$INPUT_PRECOMMANDS" ]
|
||||
then
|
||||
execute_commands "$INPUT_PRECOMMANDS"
|
||||
fi
|
||||
|
||||
# If we have secrets, set them
|
||||
for SECRET in $INPUT_SECRETS; do
|
||||
VALUE=$(printenv "$SECRET") || secret_not_found "$SECRET"
|
||||
|
||||
if [ -z "$INPUT_ENVIRONMENT" ]; then
|
||||
echo "$VALUE" | wrangler secret put "$SECRET"
|
||||
else
|
||||
echo "$VALUE" | wrangler secret put "$SECRET" --env "$INPUT_ENVIRONMENT"
|
||||
fi
|
||||
done
|
||||
|
||||
# If there's no input command then default to publish otherwise run it
|
||||
if [ -z "$INPUT_COMMAND" ]; then
|
||||
echo "::notice:: No command was provided, defaulting to 'publish'"
|
||||
|
||||
if [ -z "$INPUT_ENVIRONMENT" ]; then
|
||||
wrangler publish
|
||||
else
|
||||
wrangler publish --env "$INPUT_ENVIRONMENT"
|
||||
fi
|
||||
|
||||
else
|
||||
if [ -n "$INPUT_ENVIRONMENT" ]; then
|
||||
echo "::notice::Since you have specified an environment you need to make sure to pass in '--env $INPUT_ENVIRONMENT' to your command."
|
||||
fi
|
||||
|
||||
execute_commands "wrangler $INPUT_COMMAND"
|
||||
fi
|
||||
|
||||
# If postcommands is detected as input
|
||||
if [ -n "$INPUT_POSTCOMMANDS" ]
|
||||
then
|
||||
execute_commands "$INPUT_POSTCOMMANDS"
|
||||
fi
|
||||
|
||||
# If a working directory is detected as input, revert to the
|
||||
# original directory before continuing with the workflow
|
||||
if [ -n "$INPUT_WORKINGDIRECTORY" ]
|
||||
then
|
||||
cd $HOME
|
||||
fi
|
4368
package-lock.json
generated
Normal file
4368
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
42
package.json
Normal file
42
package.json
Normal file
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "wrangler-action",
|
||||
"version": "3.0.0",
|
||||
"description": "GitHub Action to use [Wrangler](https://developers.cloudflare.com/workers/cli-wrangler/).",
|
||||
"author": "wrangler@cloudflare.com",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/cloudflare/wrangler-action/issues"
|
||||
},
|
||||
"homepage": "https://github.com/cloudflare/wrangler-action#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/cloudflare/wrangler-action.git"
|
||||
},
|
||||
"keywords": [
|
||||
"script",
|
||||
"cli",
|
||||
"serverless",
|
||||
"cloudflare",
|
||||
"cloudflare-workers",
|
||||
"typescript"
|
||||
],
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "vitest",
|
||||
"format": "prettier --write .",
|
||||
"check": "prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20230710.1",
|
||||
"@types/node": "^20.4.2",
|
||||
"prettier": "^3.0.0",
|
||||
"typescript": "^5.1.6",
|
||||
"vitest": "^0.33.0",
|
||||
"@changesets/cli": "^2.26.2"
|
||||
}
|
||||
}
|
64
src/index.test.ts
Normal file
64
src/index.test.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import { expect, test, describe } from "vitest";
|
||||
import { checkWorkingDirectory, getNpxCmd, semverCompare } from "./index";
|
||||
import path from "node:path";
|
||||
|
||||
const config = {
|
||||
WRANGLER_VERSION: "mockVersion",
|
||||
secrets: ["mockSercret", "mockSecretAgain"],
|
||||
workingDirectory: "./mockWorkingDirectory",
|
||||
CLOUDFLARE_API_TOKEN: "mockAPIToken",
|
||||
CLOUDFLARE_ACCOUNT_ID: "mockAccountID",
|
||||
ENVIRONMENT: undefined,
|
||||
VARS: ["mockVar", "mockVarAgain"],
|
||||
COMMANDS: ["mockCommand", "mockCommandAgain"],
|
||||
};
|
||||
|
||||
test("getNpxCmd ", async () => {
|
||||
process.env.RUNNER_OS = "Windows";
|
||||
expect(getNpxCmd()).toBe("npx.cmd");
|
||||
|
||||
process.env.RUNNER_OS = "Mac";
|
||||
expect(getNpxCmd()).toBe("npx");
|
||||
|
||||
process.env.RUNNER_OS = "Linux";
|
||||
expect(getNpxCmd()).toBe("npx");
|
||||
|
||||
delete process.env.RUNNER_OS;
|
||||
});
|
||||
|
||||
describe("semverCompare", () => {
|
||||
test("should return false if the second argument is equal to the first argument", () => {
|
||||
const isVersion1LessThanVersion2 = semverCompare("1.2.3", "1.2.3");
|
||||
|
||||
expect(isVersion1LessThanVersion2).toBe(false);
|
||||
});
|
||||
|
||||
test("should return true if the first argument is less than the second argument", () => {
|
||||
const isVersion1LessThanVersion2 = semverCompare("1.2.2", "1.2.3");
|
||||
|
||||
expect(isVersion1LessThanVersion2).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("checkWorkingDirectory", () => {
|
||||
test("should return the normalized path if the directory exists", () => {
|
||||
const normalizedPath = checkWorkingDirectory(".");
|
||||
expect(normalizedPath).toBe(path.normalize("."));
|
||||
});
|
||||
|
||||
test("should fail if the directory does not exist", () => {
|
||||
try {
|
||||
checkWorkingDirectory("/does/not/exist");
|
||||
} catch (error) {
|
||||
expect(error.message).toMatchInlineSnapshot();
|
||||
}
|
||||
});
|
||||
|
||||
test("should fail if an error occurs while checking/creating the directory", () => {
|
||||
try {
|
||||
checkWorkingDirectory("/does/not/exist");
|
||||
} catch (error) {
|
||||
expect(error.message).toMatchInlineSnapshot();
|
||||
}
|
||||
});
|
||||
});
|
285
src/index.ts
Executable file
285
src/index.ts
Executable file
|
@ -0,0 +1,285 @@
|
|||
import {
|
||||
getInput,
|
||||
getMultilineInput,
|
||||
info,
|
||||
setFailed,
|
||||
endGroup,
|
||||
startGroup,
|
||||
} from "@actions/core";
|
||||
import { execSync, exec } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import * as util from "node:util";
|
||||
const execAsync = util.promisify(exec);
|
||||
|
||||
const DEFAULT_WRANGLER_VERSION = "3.4.0";
|
||||
|
||||
/**
|
||||
* A configuration object that contains all the inputs & immutable state for the action.
|
||||
*/
|
||||
const config = {
|
||||
WRANGLER_VERSION: getInput("wranglerVersion") || DEFAULT_WRANGLER_VERSION,
|
||||
secrets: getMultilineInput("secrets"),
|
||||
workingDirectory: checkWorkingDirectory(getInput("workingDirectory")),
|
||||
CLOUDFLARE_API_TOKEN: getInput("apiToken"),
|
||||
CLOUDFLARE_ACCOUNT_ID: getInput("accountId"),
|
||||
ENVIRONMENT: getInput("environment"),
|
||||
VARS: getMultilineInput("vars"),
|
||||
COMMANDS: getMultilineInput("command"),
|
||||
} as const;
|
||||
|
||||
function getNpxCmd() {
|
||||
return process.env.RUNNER_OS === "Windows" ? "npx.cmd" : "npx";
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to compare two semver versions. If the second arg is greater than the first arg, it returns true.
|
||||
*/
|
||||
function semverCompare(version1: string, version2: string) {
|
||||
if (version2 === "latest") return true;
|
||||
|
||||
const version1Parts = version1.split(".");
|
||||
const version2Parts = version2.split(".");
|
||||
|
||||
for (const version1Part of version1Parts) {
|
||||
const version2Part = version2Parts.shift();
|
||||
|
||||
if (version1Part !== version2Part && version2Part) {
|
||||
return version1Part < version2Part ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
installWrangler();
|
||||
authenticationSetup();
|
||||
await execCommands(getMultilineInput("preCommands"), "Pre");
|
||||
await uploadSecrets();
|
||||
await wranglerCommands();
|
||||
await execCommands(getMultilineInput("postCommands"), "Post");
|
||||
}
|
||||
|
||||
function checkWorkingDirectory(workingDirectory = ".") {
|
||||
try {
|
||||
const normalizedPath = path.normalize(workingDirectory);
|
||||
if (existsSync(normalizedPath)) {
|
||||
return normalizedPath;
|
||||
} else {
|
||||
setFailed(`🚨 Directory ${workingDirectory} does not exist.`);
|
||||
}
|
||||
} catch (error) {
|
||||
setFailed(
|
||||
`🚨 While checking/creating directory ${workingDirectory} received ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function installWrangler() {
|
||||
if (config["WRANGLER_VERSION"].startsWith("1")) {
|
||||
setFailed(
|
||||
`🚨 Wrangler v1 is no longer supported by this action. Please use major version 2 or greater`,
|
||||
);
|
||||
}
|
||||
startGroup("📥 Installing Wrangler");
|
||||
const command = `npm install wrangler@${config["WRANGLER_VERSION"]}`;
|
||||
info(`Running command: ${command}`);
|
||||
execSync(command, { cwd: config["workingDirectory"], env: process.env });
|
||||
info(`✅ Wrangler installed`);
|
||||
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(`🚀 ${cmdType} Commands Group`);
|
||||
|
||||
const arrPromises = commands.map(async (command) => {
|
||||
const cmd = command.startsWith("wrangler")
|
||||
? `${getNpxCmd()} ${command}`
|
||||
: command;
|
||||
|
||||
info(`🚀 Executing command: ${cmd}`);
|
||||
|
||||
return await execAsync(cmd, {
|
||||
cwd: config["workingDirectory"],
|
||||
env: process.env,
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(arrPromises);
|
||||
endGroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to get the secret from the environment variables.
|
||||
*/
|
||||
function getSecret(secret: string) {
|
||||
if (!secret) {
|
||||
setFailed("No secret provided");
|
||||
}
|
||||
|
||||
const value = process.env[secret];
|
||||
if (!value) {
|
||||
setFailed(`Secret ${secret} not found`);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
async function legacyUploadSecrets(
|
||||
secrets: string[],
|
||||
environment?: string,
|
||||
workingDirectory?: string,
|
||||
) {
|
||||
try {
|
||||
const arrPromises = secrets
|
||||
.map((secret) => {
|
||||
const command = `echo ${getSecret(
|
||||
secret,
|
||||
)} | ${getNpxCmd()} wrangler secret put ${secret}`;
|
||||
return environment ? command.concat(`--env ${environment}`) : command;
|
||||
})
|
||||
.map(
|
||||
async (command) =>
|
||||
await execAsync(command, {
|
||||
cwd: workingDirectory,
|
||||
env: process.env,
|
||||
}),
|
||||
);
|
||||
|
||||
await Promise.all(arrPromises);
|
||||
} catch {
|
||||
setFailed(`🚨 Error uploading secrets`);
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadSecrets() {
|
||||
const secrets: string[] = config["secrets"];
|
||||
const environment = config["ENVIRONMENT"];
|
||||
const workingDirectory = config["workingDirectory"];
|
||||
|
||||
if (!secrets.length) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
startGroup("🔑 Uploading Secrets");
|
||||
|
||||
if (semverCompare(config["WRANGLER_VERSION"], "3.4.0"))
|
||||
return legacyUploadSecrets(secrets, environment, workingDirectory);
|
||||
|
||||
const secretObj = secrets.reduce((acc: any, secret: string) => {
|
||||
acc[secret] = getSecret(secret);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const environmentSuffix = !environment.length
|
||||
? ""
|
||||
: ` --env ${environment}`;
|
||||
|
||||
const secretCmd = `echo "${JSON.stringify(secretObj).replaceAll(
|
||||
'"',
|
||||
'\\"',
|
||||
)}" | ${getNpxCmd()} wrangler secret:bulk ${environmentSuffix}`;
|
||||
|
||||
execSync(secretCmd, {
|
||||
cwd: workingDirectory,
|
||||
env: process.env,
|
||||
stdio: "ignore",
|
||||
});
|
||||
info(`✅ Uploaded secrets`);
|
||||
} catch {
|
||||
setFailed(`🚨 Error uploading secrets`);
|
||||
} finally {
|
||||
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 {
|
||||
setFailed(`🚨 ${envVar} not found in variables.`);
|
||||
}
|
||||
});
|
||||
|
||||
return envVarArray.length > 0 ? `--var ${envVarArray.join(" ").trim()}` : "";
|
||||
}
|
||||
|
||||
function defaultCommandBehavior() {
|
||||
const environment = config["ENVIRONMENT"];
|
||||
const wranglerVersion = config["WRANGLER_VERSION"];
|
||||
const workingDirectory = config["workingDirectory"];
|
||||
|
||||
const deployCommand = semverCompare("2.20.0", wranglerVersion)
|
||||
? "deploy"
|
||||
: "publish";
|
||||
|
||||
info(`📌 No Wrangler commands were provided, executing default deployment.`);
|
||||
|
||||
if (environment.length === 0) {
|
||||
execSync(
|
||||
`${getNpxCmd()} wrangler ${deployCommand} ${getVarArgs()}`.trim(),
|
||||
{
|
||||
cwd: workingDirectory,
|
||||
env: process.env,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
execSync(
|
||||
`${getNpxCmd()} wrangler ${deployCommand} --env ${environment} ${getVarArgs()}`.trim(),
|
||||
{ cwd: workingDirectory, env: process.env },
|
||||
);
|
||||
}
|
||||
endGroup();
|
||||
}
|
||||
|
||||
async function wranglerCommands() {
|
||||
const commands = config["COMMANDS"];
|
||||
const environment = config["ENVIRONMENT"];
|
||||
|
||||
if (!commands.length) {
|
||||
defaultCommandBehavior();
|
||||
return;
|
||||
}
|
||||
startGroup("🚀 Executing Wrangler Commands");
|
||||
|
||||
const arrPromises = commands.map(async (command) => {
|
||||
if (environment.length > 0 && !command.includes(`--env ${environment}`)) {
|
||||
command.concat(`--env ${environment}`);
|
||||
}
|
||||
const result = await execAsync(
|
||||
`${getNpxCmd()} wrangler ${command} ${getVarArgs()}`,
|
||||
{
|
||||
cwd: config["workingDirectory"],
|
||||
env: process.env,
|
||||
},
|
||||
);
|
||||
info(result.stdout);
|
||||
return result;
|
||||
});
|
||||
await Promise.all(arrPromises);
|
||||
endGroup();
|
||||
}
|
||||
|
||||
main().catch(() => setFailed("🚨 Action failed"));
|
||||
|
||||
export {
|
||||
wranglerCommands,
|
||||
execCommands,
|
||||
uploadSecrets,
|
||||
authenticationSetup,
|
||||
installWrangler,
|
||||
checkWorkingDirectory,
|
||||
getNpxCmd,
|
||||
semverCompare,
|
||||
};
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
dist
|
26
test/base/index.ts
Normal file
26
test/base/index.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
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");
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
return Response.json({
|
||||
...request,
|
||||
headers: Object.fromEntries(request.headers),
|
||||
});
|
||||
},
|
||||
};
|
3
test/base/package.json
Normal file
3
test/base/package.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"name": "wrangler-action-test"
|
||||
}
|
4
test/base/public/index.html
Normal file
4
test/base/public/index.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
<h1>My Static Site Test</h1>
|
||||
<p>To Test Secrets go to /secret</p>
|
||||
<a href="/secret">Secrets</a>
|
||||
<footer>a footer</footer>
|
11
test/base/wrangler.toml
Normal file
11
test/base/wrangler.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
name = "wrangler-action-test"
|
||||
main = "./index.ts"
|
||||
compatibility_date = "2023-07-07"
|
||||
workers_dev = true
|
||||
|
||||
[site]
|
||||
bucket = "./public"
|
||||
|
||||
# [vars]
|
||||
# SECRET1 = "value1"
|
||||
# SECRET2 = "value2"
|
21
test/environment/index.ts
Normal file
21
test/environment/index.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
type Env = {
|
||||
SECRET1?: string;
|
||||
SECRET2?: string;
|
||||
};
|
||||
|
||||
export default {
|
||||
fetch(request: Request, env: Env) {
|
||||
const url = new URL(request.url);
|
||||
|
||||
if (url.pathname === "/secret") {
|
||||
const { SECRET1 = "", SECRET2 = "" } = env;
|
||||
return new Response(`${SECRET1} ${SECRET2}`);
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
return Response.json({
|
||||
...request,
|
||||
headers: Object.fromEntries(request.headers),
|
||||
});
|
||||
},
|
||||
};
|
3
test/environment/package.json
Normal file
3
test/environment/package.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"name": "wrangler-action-environment-test"
|
||||
}
|
4
test/environment/public/index.html
Normal file
4
test/environment/public/index.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
<h1>My Static Site Test</h1>
|
||||
<p>To Test Secrets go to /secret</p>
|
||||
<a href="/secret">Secrets</a>
|
||||
<footer>a footer</footer>
|
12
test/environment/wrangler.toml
Normal file
12
test/environment/wrangler.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
name = "wrangler-action-environment-test"
|
||||
main = "./index.ts"
|
||||
compatibility_date = "2023-07-07"
|
||||
workers_dev = true
|
||||
|
||||
[site]
|
||||
bucket = "./public"
|
||||
|
||||
[env.dev]
|
||||
name = "wrangler-action-dev-environment-test"
|
||||
[env.dev.vars]
|
||||
DEV_VAR = "example_production_token"
|
|
@ -1,6 +0,0 @@
|
|||
<h1>My Static Site Test</h1>
|
||||
<p>This is the content of my site</p>
|
||||
|
||||
<footer>
|
||||
And this is my footer
|
||||
</footer>
|
|
@ -1,88 +0,0 @@
|
|||
import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'
|
||||
|
||||
/**
|
||||
* The DEBUG flag will do two things that help during development:
|
||||
* 1. we will skip caching on the edge, which makes it easier to
|
||||
* debug.
|
||||
* 2. we will return an error message on exception in your response rather
|
||||
* than the default 404.html page.
|
||||
*/
|
||||
const DEBUG = false
|
||||
|
||||
addEventListener('fetch', event => {
|
||||
try {
|
||||
event.respondWith(handleEvent(event))
|
||||
} catch (e) {
|
||||
if (DEBUG) {
|
||||
return event.respondWith(
|
||||
new Response(e.message || e.toString(), {
|
||||
status: 500,
|
||||
}),
|
||||
)
|
||||
}
|
||||
event.respondWith(new Response('Internal Error', { status: 500 }))
|
||||
}
|
||||
})
|
||||
|
||||
async function handleEvent(event) {
|
||||
const url = new URL(event.request.url)
|
||||
let options = {}
|
||||
|
||||
/**
|
||||
* You can add custom logic to how we fetch your assets
|
||||
* by configuring the function `mapRequestToAsset`
|
||||
*/
|
||||
// options.mapRequestToAsset = handlePrefix(/^\/docs/)
|
||||
|
||||
// Path to test secrets passed through Wrangler Action. Create SECRET1 and SECRET2 secrets
|
||||
// in the Action repo to something innocuous like "Hello" and "World!".
|
||||
if (url.pathname === "/secret") {
|
||||
let sec1 = (typeof SECRET1 !== 'undefined') ? SECRET1 : ""
|
||||
let sec2 = (typeof SECRET2 !== 'undefined') ? SECRET2 : ""
|
||||
return new Response(`${sec1} ${sec2}`)
|
||||
}
|
||||
|
||||
try {
|
||||
if (DEBUG) {
|
||||
// customize caching
|
||||
options.cacheControl = {
|
||||
bypassCache: true,
|
||||
}
|
||||
}
|
||||
return await getAssetFromKV(event, options)
|
||||
} catch (e) {
|
||||
// if an error is thrown try to serve the asset at 404.html
|
||||
if (!DEBUG) {
|
||||
try {
|
||||
let notFoundResponse = await getAssetFromKV(event, {
|
||||
mapRequestToAsset: req => new Request(`${new URL(req.url).origin}/404.html`, req),
|
||||
})
|
||||
|
||||
return new Response(notFoundResponse.body, { ...notFoundResponse, status: 404 })
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return new Response(e.message || e.toString(), { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Here's one example of how to modify a request to
|
||||
* remove a specific prefix, in this case `/docs` from
|
||||
* the url. This can be useful if you are deploying to a
|
||||
* route on a zone, or if you only want your static content
|
||||
* to exist at a specific path.
|
||||
*/
|
||||
function handlePrefix(prefix) {
|
||||
return request => {
|
||||
// compute the default (e.g. / -> index.html)
|
||||
let defaultAssetKey = mapRequestToAsset(request)
|
||||
let url = new URL(defaultAssetKey.url)
|
||||
|
||||
// strip the prefix from the path for lookup
|
||||
url.pathname = url.pathname.replace(prefix, '/')
|
||||
|
||||
// inherit all other props from the default request
|
||||
return new Request(url.toString(), defaultAssetKey)
|
||||
}
|
||||
}
|
21
test/workers-site/package-lock.json
generated
21
test/workers-site/package-lock.json
generated
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "worker",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@cloudflare/kv-asset-handler": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.0.5.tgz",
|
||||
"integrity": "sha512-7yLMAUZD1XQNKzmktYCcUUPB+wXmQENv1MMi8QEMs0rzL01e0XEyCUUDauRXHzxi7dBbSUGA5RS23h890ncKog==",
|
||||
"requires": {
|
||||
"mime": "^2.4.4"
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
||||
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"private": true,
|
||||
"name": "worker",
|
||||
"version": "1.0.0",
|
||||
"description": "A template for kick starting a Cloudflare Workers project",
|
||||
"main": "index.js",
|
||||
"author": "Ashley Lewis <ashleymichal@gmail.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cloudflare/kv-asset-handler": "^0.0.5"
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
name = "static-test"
|
||||
type = "webpack"
|
||||
workers_dev = true
|
||||
account_id = "dc56444c4c955a1653106ccf997c1067"
|
||||
|
||||
[env.production]
|
||||
name = "static-test-prod"
|
||||
|
||||
[site]
|
||||
bucket = "./public"
|
||||
entry-point = "workers-site"
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"files": ["./src/index.ts"],
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"composite": true,
|
||||
"incremental": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"isolatedModules": true,
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"lib": ["ESNext"],
|
||||
"types": ["node", "@cloudflare/workers-types"]
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"],
|
||||
"include": ["src/index.ts"]
|
||||
}
|
Loading…
Reference in a new issue