diff --git a/.github/workflows/deploy.yml.disabled b/.github/workflows/deploy.yml.disabled new file mode 100644 index 00000000..0382ea6b --- /dev/null +++ b/.github/workflows/deploy.yml.disabled @@ -0,0 +1,33 @@ +on: push + +jobs: + deploy: + runs-on: ubuntu-latest + name: Deploy + steps: + - uses: actions/checkout@master + - name: Lint shell script + uses: azohra/shell-linter@v0.1.0 + with: + path: "entrypoint.sh" + - name: Publish app with api token + uses: signalnerve/wrangler-action@1.1.0 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + environment: "production" + workingDirectory: 'test' + - name: Publish app with legacy credentials + uses: signalnerve/wrangler-action@1.1.0 + with: + apiKey: ${{ secrets.CLOUDFLARE_API_KEY }} + email: ${{ secrets.CLOUDFLARE_EMAIL }} + environment: "production" + workingDirectory: 'test' + - name: Publish app with hardcoded Wrangler version + uses: signalnerve/wrangler-action@1.1.0 + with: + apiKey: ${{ secrets.CLOUDFLARE_API_KEY }} + email: ${{ secrets.CLOUDFLARE_EMAIL }} + environment: "production" + wranglerVersion: '1.5.0' + workingDirectory: 'test' diff --git a/README.md b/README.md index aef40e51..bf7714c9 100644 --- a/README.md +++ b/README.md @@ -21,52 +21,75 @@ jobs: steps: - uses: actions/checkout@master - name: Publish - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - apiKey: ${{ secrets.CF_API_KEY }} - email: ${{ secrets.CF_EMAIL }} + apiToken: ${{ secrets.CF_API_TOKEN }} ``` -## Configuration +## Authentication + +You'll need to configure Wrangler using GitHub's Secrets feature - go to "Settings -> Secrets" and add your Cloudflare API token (for help finding this, see the [Workers documentation](https://developers.cloudflare.com/workers/quickstart/#api-token)). Your API token is encrypted by GitHub, and the action won't print it into logs, so it should be safe! + +With your API token set as a secret for your repository, pass it to the action in the `with` block of your workflow. Below, I've set the secret name to `CF_API_TOKEN`: -You'll need to configure Wrangler using GitHub's Secrets feature - go to "Settings -> Secrets" and add your Cloudflare API key and email (for help finding these, see the [Workers documentation](https://developers.cloudflare.com/workers/quickstart/#finding-your-cloudflare-api-keys)). Your API key and email are encrypted by GitHub, and the action won't print them into logs, so they should be safe! +```yaml +jobs: + deploy: + name: Deploy + steps: + uses: cloudflare/wrangler-action@1.1.0 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} +``` -With your API key and email set as secrets for your repository, pass them to the action in the `with` block of your workflow. Below, I've set the secret names to `CF_API_KEY` and `CF_EMAIL`: +`wrangler-action` also supports using your [global API key and email](https://developers.cloudflare.com/workers/quickstart/#global-api-key) as an authentication method, although API tokens are preferred. Pass in `apiKey` and `email` to the GitHub Action to use this method: ```yaml jobs: deploy: name: Deploy steps: - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: apiKey: ${{ secrets.CF_API_KEY }} email: ${{ secrets.CF_EMAIL }} ``` -Optionally, you can also pass an `environment` key to the action. If you're using Wrangler's [environments](https://github.com/cloudflare/wrangler/blob/master/docs/content/environments.md) feature, you can customize _where_ the action deploys to by passing the matching environment in the `with` block of your workflow: +## Configuration + +If you're using Wrangler's [environments](https://github.com/cloudflare/wrangler/blob/master/docs/content/environments.md) feature, you can customize _where_ the action deploys to by passing an `environment` in the `with` block of your workflow: ```yaml jobs: deploy: - # ... previous configuration ... steps: - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - # ... api key and email ... + apiToken: ${{ secrets.CF_API_TOKEN }} environment: 'production' ``` +If you need to install a specific version of Wrangler to use for deployment, you can also pass the input `wranglerVersion` to install a specific version of Wrangler from NPM. This should be a [SemVer](https://semver.org/)-style version number, such as `1.6.0`: + +```yaml +jobs: + deploy: + steps: + uses: cloudflare/wrangler-action@1.1.0 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} + 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. ```yaml jobs: deploy: - # ... previous configuration ... steps: - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - # ... api key and email ... + apiToken: ${{ secrets.CF_API_TOKEN }} workingDirectory: 'subfoldername' ``` @@ -89,10 +112,9 @@ jobs: steps: - uses: actions/checkout@master - name: Publish - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - apiKey: ${{ secrets.CF_API_KEY }} - email: ${{ secrets.CF_EMAIL }} + apiToken: ${{ secrets.CF_API_TOKEN }} ``` Note that there are a number of possible events, like `push`, that can be used to trigger a workflow. For more details on the events available, check out the [GitHub Actions documentation](https://help.github.com/en/articles/workflow-syntax-for-github-actions#on). @@ -113,10 +135,9 @@ jobs: steps: - uses: actions/checkout@master - name: Publish app - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - apiKey: ${{ secrets.CF_API_KEY }} - email: ${{ secrets.CF_EMAIL }} + apiToken: ${{ secrets.CF_API_TOKEN }} ``` If you need help defining the correct cron syntax, check out [crontab.guru](https://crontab.guru/), which provides a friendly user interface for validating your cron schedule. @@ -136,10 +157,9 @@ jobs: steps: - uses: actions/checkout@master - name: Publish app - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - apiKey: ${{ secrets.CF_API_KEY }} - email: ${{ secrets.CF_EMAIL }} + apiToken: ${{ secrets.CF_API_TOKEN }} ``` To make the GitHub API request, you can deploy a custom [Cloudflare Workers](https://workers.cloudflare.com) function, which will send a `POST` request to GitHub's API and trigger a new deploy: @@ -188,8 +208,7 @@ jobs: - name: Build site run: 'npm run build' - name: Publish - uses: cloudflare/wrangler-action@1.0.0 + uses: cloudflare/wrangler-action@1.1.0 with: - apiKey: ${{ secrets.CF_API_KEY }} - email: ${{ secrets.CF_EMAIL }} + apiToken: ${{ secrets.CF_API_TOKEN }} ``` diff --git a/action.yml b/action.yml index 818bc271..33ace1a2 100644 --- a/action.yml +++ b/action.yml @@ -8,12 +8,14 @@ runs: image: 'Dockerfile' inputs: apiKey: - description: "Your Cloudflare API Key" - required: true + description: "(Legacy) Your Cloudflare API Key" + apiToken: + description: "Your Cloudflare API Token" email: - description: "Your Cloudflare Email" - required: true + description: "(Legacy) Your Cloudflare Email" environment: description: "The environment you'd like to publish your Workers project to - must be defined in wrangler.toml" workingDirectory: description: "The relative path which Wrangler commands should be run from" + wranglerVersion: + description: "The version of Wrangler you'd like to use to publish your Workers project" diff --git a/entrypoint.sh b/entrypoint.sh index 43740fb8..599b3cc6 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -6,35 +6,71 @@ export HOME="/github/workspace" export NVM_DIR="/github/workspace/nvm" export WRANGLER_HOME="/github/workspace" -# h/t https://github.com/elgohr/Publish-Docker-Github-Action -sanitize() { - if [ -z "${1}" ] - then - >&2 echo "Unable to find ${2}. Did you add a GitHub secret called key ${2}, and pass in secrets.${2} in your workflow?" - exit 1 - fi -} - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.0/install.sh | bash + +# Comments beginning with "shellcheck" use shellcheck, a shell script linter. +# The below comments ignore shellcheck linting on the instructions provided +# by NVM. + +# shellcheck source=/dev/null [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +# shellcheck source=/dev/null [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" mkdir -p "$HOME/.wrangler" chmod -R 770 "$HOME/.wrangler" -sanitize "${INPUT_EMAIL}" "email" -sanitize "${INPUT_APIKEY}" "apiKey" +export API_CREDENTIALS="" + +# If an API token is detected as input +if [ -n "$INPUT_APITOKEN" ] +then + export CF_API_TOKEN="$INPUT_APITOKEN" + export API_CREDENTIALS="API Token" +fi -export CF_EMAIL="$INPUT_EMAIL" -export CF_API_KEY="$INPUT_APIKEY" +# If an API key and email are detected as input +if [ -n "$INPUT_APIKEY" ] && [ -n "$INPUT_EMAIL" ] +then + export CF_EMAIL="$INPUT_EMAIL" + export CF_API_KEY="$INPUT_APIKEY" + export API_CREDENTIALS="Email and API Key" +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 -npm i @cloudflare/wrangler -g +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 Wrangler version is detected as input +if [ -z "$INPUT_WRANGLERVERSION" ] +then + npm i @cloudflare/wrangler -g +else + npm i "@cloudflare/wrangler@$INPUT_WRANGLERVERSION" -g +fi -if ! [ -z "$INPUT_WORKINGDIRECTORY" ] +# If a working directory is detected as input +if [ -n "$INPUT_WORKINGDIRECTORY" ] then - cd $INPUT_WORKINGDIRECTORY + cd "$INPUT_WORKINGDIRECTORY" fi +# If an environment is detected as input if [ -z "$INPUT_ENVIRONMENT" ] then wrangler publish @@ -42,7 +78,9 @@ else wrangler publish -e "$INPUT_ENVIRONMENT" fi -if ! [ -z "$INPUT_WORKINGDIRECTORY" ] +# 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 diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 00000000..1521c8b7 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +dist diff --git a/test/public/index.html b/test/public/index.html new file mode 100644 index 00000000..fcdd36ce --- /dev/null +++ b/test/public/index.html @@ -0,0 +1,6 @@ +
This is the content of my site
+ + diff --git a/test/workers-site/.cargo-ok b/test/workers-site/.cargo-ok new file mode 100644 index 00000000..e69de29b diff --git a/test/workers-site/index.js b/test/workers-site/index.js new file mode 100644 index 00000000..f980a77d --- /dev/null +++ b/test/workers-site/index.js @@ -0,0 +1,80 @@ +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/) + + 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) + } +} \ No newline at end of file diff --git a/test/workers-site/package-lock.json b/test/workers-site/package-lock.json new file mode 100644 index 00000000..f551c60b --- /dev/null +++ b/test/workers-site/package-lock.json @@ -0,0 +1,21 @@ +{ + "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==" + } + } +} diff --git a/test/workers-site/package.json b/test/workers-site/package.json new file mode 100644 index 00000000..4d9ce6f6 --- /dev/null +++ b/test/workers-site/package.json @@ -0,0 +1,12 @@ +{ + "private": true, + "name": "worker", + "version": "1.0.0", + "description": "A template for kick starting a Cloudflare Workers project", + "main": "index.js", + "author": "Ashley Lewis