A forked copy of the Github action Cloudflare Pages which is updated to utilize NodeJS 20+ and continues updates.
GitHub Action for creating Cloudflare Pages deployments, using the Direct Upload feature and Wrangler integration.
This action was originally found on the official Cloudflare Github page, but the action has lacked updates to more recent libraries.
Specifying wranglerVersion: '3'
will utilize the newer wrangler deploy
command over v2's deprecated publish
command.
- Create an API token within the Cloudflare Dashboard with the "Cloudflare Pages — Edit" permission.
- Within the example below, replace
CLOUDFLARE_API_TOKEN
with your given API token. - Create a new Github action file
.github/workflows/cfpage-publish.yml
in your repository with the following:
run-name: "☁️ CF › Deploy"
name: "☁️ CF › Deploy"
on: [push]
jobs:
job-publish:
name: >-
📦 Publish to Cloudflare
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: "☑️ Checkout"
id: task_publish_checkout
uses: actions/checkout@v4
- name: "☁️ Publish to Cloudflare Pages"
id: task_publish_push
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} # Cloudflare API Token at https://dash.cloudflare.com/profile/api-tokens
accountId: ACCOUNT_ID # Cloudflare account ID available on right side of CF website
projectName: PROJECT_NAME # Project name assigned at creation. view on workers-and-pages section of CF website
directory: BUILD_OUTPUT_FOLDER # Output directory for built website
gitHubToken: ${{ secrets.GITHUB_TOKEN }} # Optional: Enable this if you want to have GitHub Deployments triggered
branch: main # Branch website published to; by default this will be the branch which triggered this workflow
workingDirectory: my-site # Working directory
wranglerVersion: '3' # Optional: Change the Wrangler version, allows you to point to a specific version or a tag such as `beta`
commitMsg: 'Your commit message' # Optional: Commit message to attach
commitDirty: false # Optional: Whether or not the workspace should be considered dirty for this deployment
skipCaching: false # Optional: Skip asset caching which speeds up builds
Replace with following variables with your own:
ACCOUNT_ID
PROJECT_NAME
BUILD_OUTPUT_FOLDER
To find your account ID, log in to the Cloudflare Dashboard > select your zone in Account Home > find your account ID in Overview under API on the right-side menu. If you have not added a zone, add one by selecting Add site . You can purchase a domain from Cloudflare’s registrar.
If you do not have a zone registered to your account, you can also get your account ID from the pages.dev
URL. E.g: https://dash.cloudflare.com/<ACCOUNT_ID>/pages
To generate an API token:
- Log in to the Cloudflare Dashboard
- Select My Profile from the dropdown menu of your user icon on the top right of your dashboard.
- Select API Tokens >
Create Token
- Under
Custom Token
, selectGet Started
- Name your API Token in the Token name field
- Under
Permissions
, selectAccount
,Cloudflare Pages
andEdit
- Select Continue to
Summary
>Create Token
More information can be found on our guide for making Direct Upload deployments with continous integration.
The branch name is used by Cloudflare Pages to determine if the deployment is production or preview. Read more about git branch build controls.
If you are in a Git workspace, Wrangler will automatically pull the branch information for you. You can override this
manually by adding the argument branch: BRANCH_NAME
.
By default Wrangler will run in the root package directory. If your app lives in a monorepo and you want to run Wrangler from its directory, add workingDirectory: PACKAGE_DIRECTORY
.
Some people may store their website in the root directory of a branch; if so, specify ./
as your working directory.
You can use the newly released Wrangler v3 with the wranglerVersion
property.
- name: "☁️ Publish to Cloudflare Pages"
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ACCOUNT_ID
projectName: PROJECT_NAME
directory: BUILD_OUTPUT_FOLDER
wranglerVersion: '3'
This action will return the following outputs:
Name | Description |
---|---|
id |
The ID of the pages deployment |
url |
The URL of the pages deployment |
alias |
The alias if it exists otherwise the deployment URL |
environment |
The environment that was deployed to |
A few examples of this Github action are provided below:
Deploy cloudflare pages on push with deploy outputs
This example allows you to run the action either manually, or on push for the branches master
or main
. It includes input declarations when using workflow_dispatch
.
run-name: "☁️ CF › Deploy"
name: "☁️ CF › Deploy"
on:
push:
branches:
- main
- master
jobs:
job-publish:
name: >-
📦 Publish to Cloudflare
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: "☑️ Checkout"
id: task_publish_checkout
uses: actions/checkout@v4
- name: "☁️ Publish to Cloudflare Pages"
id: task_publish_push
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ACCOUNT_ID
projectName: PROJECT_NAME
directory: BUILD_OUTPUT_FOLDER
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: main
workingDirectory: my-site
wranglerVersion: '3'
- name: "📝 Outputs"
run: |
echo "ID ........... ${{ steps.task_publish_push.outputs.id }}"
echo "URL .......... ${{ steps.task_publish_push.outputs.url }}"
echo "Environment .. ${{ steps.task_publish_push.outputs.environment }}"
echo "Alias ........ ${{ steps.task_publish_push.outputs.alias }}"
- name: "📝 Outputs to Summary"
run: |
echo "Deployed to ${{ steps.task_publish_push.outputs.url }}" >> $GITHUB_STEP_SUMMARY
Ensure you change the values above to your own.
Run npm, @cloudflare/next-on-pages (Next.js), and deploy to cloudflare pages
@cloudflare/next-on-pages is a CLI tool that you can use to build and develop Next.js applications so that they can run on the Cloudflare Pages platform.
run-name: "☁️ CF › Deploy"
name: "☁️ CF › Deploy"
on:
push:
branches:
- main
- master
jobs:
job-publish:
name: >-
📦 Publish to Cloudflare
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
statuses: write
steps:
- name: "☑️ Checkout"
id: task_publish_checkout
uses: actions/checkout@v4
- name: "📦 Install Packages"
id: task_publish_install_packages
run: npm install
- name: "🔨 Build"
id: task_publish_build_nextonpages
run: npx @cloudflare/next-on-pages@1
- name: "☁️ Publish to Cloudflare Pages"
id: task_publish_push
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ACCOUNT_ID
projectName: PROJECT_NAME
directory: BUILD_OUTPUT_FOLDER
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: main
workingDirectory: my-site
wranglerVersion: '3'
- name: "📝 Outputs"
run: |
echo "ID ........... ${{ steps.task_publish_push.outputs.id }}"
echo "URL .......... ${{ steps.task_publish_push.outputs.url }}"
echo "Environment .. ${{ steps.task_publish_push.outputs.environment }}"
echo "Alias ........ ${{ steps.task_publish_push.outputs.alias }}"
- name: "📝 Outputs to Summary"
run: |
echo "Deployed to ${{ steps.task_publish_push.outputs.url }}" >> $GITHUB_STEP_SUMMARY
Ensure you change the values above to your own.
Run on push + workflow dispatch (with inputs)
This example allows you to run the action either manually, or on push for the branches master
or main
. It includes input declarations when using workflow_dispatch
.
run-name: "☁️ CF › Deploy"
name: "☁️ CF › Deploy"
on:
push:
branches:
- main
- master
workflow_dispatch:
inputs:
PROJECT_NAME:
description: "Project Name"
required: true
default: 'my-site'
type: string
CLOUDFLARE_ACCOUNT_ID:
description: "Cloudflare Account ID"
required: true
default: 'XXXXXXXXXXXXXXXX'
type: string
DIRECTORY_BUILD_OUTPUT:
description: "Build Output Dir"
required: true
default: './'
type: string
DIRECTORY_WORKING:
description: "Working Dir"
required: true
default: './'
type: string
WRANGLER_VERSION:
description: "Wrangler Version"
required: true
default: '3'
type: string
BRANCH:
description: 'Website Branch'
required: true
default: 'main'
type: choice
options:
- main
- master
jobs:
job-publish:
name: >-
📦 Publish to Cloudflare
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: "☑️ Checkout"
id: task_publish_checkout
uses: actions/checkout@v4
- name: "☁️ Publish to Cloudflare Pages"
id: task_publish_push
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ inputs.PROJECT_NAME || 'my-site' }}
directory: ${{ inputs.DIRECTORY_BUILD_OUTPUT || './' }}
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ inputs.BRANCH || 'main' }}
workingDirectory: ${{ inputs.DIRECTORY_WORKING || './' }}
wranglerVersion: ${{ inputs.WRANGLER_VERSION || '3' }}
Ensure you change the values above to your own.
Verify & create project using Cloudflare APU, then push to cloudflare (with inputs)
This example adds the usage of the Cloudflare api to first check if your project name actually exists on Cloudflare, creates the project if not, and then pushes to Cloudflare pages.
run-name: "☁️ CF › Deploy"
name: "☁️ CF › Deploy"
on:
push:
branches:
- main
- master
workflow_dispatch:
inputs:
PROJECT_NAME:
description: "Project Name"
required: true
default: 'my-site'
type: string
CLOUDFLARE_ACCOUNT_ID:
description: "Cloudflare Account ID"
required: true
default: 'XXXXXXXXXXXXXXXX'
type: string
DIRECTORY_BUILD_OUTPUT:
description: "Build Output Dir"
required: true
default: './'
type: string
DIRECTORY_WORKING:
description: "Working Dir"
required: true
default: './'
type: string
WRANGLER_VERSION:
description: "Wrangler Version"
required: true
default: '3'
type: string
BRANCH:
description: 'Website Branch'
required: true
default: 'main'
type: choice
options:
- main
- master
jobs:
job-publish:
name: >-
📦 Publish to Cloudflare
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: "☑️ Checkout"
id: task_publish_checkout
uses: actions/checkout@v4
- name: "☁️ CF › Check Project"
id: task_publish_project_verify
shell: bash
run: |
check=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}/pages/projects/${{ inputs.PROJECT_NAME || 'my-site' }}" \
-H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \
-H "Content-Type:application/json" | jq -r '.success')
echo "result=$check" >> $GITHUB_OUTPUT
- name: "☁️ CF › Create Project (if nonexistent)"
id: task_publish_project_create
shell: bash
if: steps.task_publish_project_verify.outputs.result != 'true'
run: |
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}/pages/projects" \
-H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \
-H "Content-Type:application/json" \
--data '{"name":"${{ inputs.PROJECT_NAME || 'my-site' }}", "production_branch":"${{ inputs.BRANCH || 'main' }}"}'
- name: "☁️ Publish to Cloudflare Pages"
id: task_publish_push
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ inputs.PROJECT_NAME || 'my-site' }}
directory: ${{ inputs.DIRECTORY_BUILD_OUTPUT || './' }}
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ inputs.BRANCH || 'main' }}
workingDirectory: ${{ inputs.DIRECTORY_WORKING || './' }}
wranglerVersion: ${{ inputs.WRANGLER_VERSION || '3' }}
Configure node + pre-install wrangler, and push to cloudflare (with inputs)
This example adds the usage of the Cloudflare api to first check if your project name actually exists on Cloudflare, creates the project if not, and then pushes to Cloudflare pages.
run-name: "☁️ CF › Deploy"
name: "☁️ CF › Deploy"
on:
push:
branches:
- main
- master
workflow_dispatch:
inputs:
PROJECT_NAME:
description: "Project Name"
required: true
default: 'my-site'
type: string
CLOUDFLARE_ACCOUNT_ID:
description: "Cloudflare Account ID"
required: true
default: 'XXXXXXXXXXXXXXXX'
type: string
DIRECTORY_BUILD_OUTPUT:
description: "Build Output Dir"
required: true
default: './'
type: string
DIRECTORY_WORKING:
description: "Working Dir"
required: true
default: './'
type: string
WRANGLER_VERSION:
description: "Wrangler Version"
required: true
default: '3'
type: string
BRANCH:
description: 'Website Branch'
required: true
default: 'main'
type: choice
options:
- main
- master
jobs:
job-publish:
name: >-
📦 Publish to Cloudflare
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: "☑️ Checkout"
id: task_publish_checkout
uses: actions/checkout@v4
- name: "⚙️ Setup › Node"
id: task_publish_node_setup
uses: actions/setup-node@v4
with:
node-version: '20.x'
- name: "📦 NPM › Install Wrangler"
id: task_publish_npm_install
run: |
npm install -g npm@latest
npm install --global wrangler
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "☁️ CF › Check Project"
id: task_publish_project_verify
shell: bash
run: |
check=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}/pages/projects/${{ inputs.PROJECT_NAME || 'my-site' }}" \
-H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \
-H "Content-Type:application/json" | jq -r '.success')
echo "result=$check" >> $GITHUB_OUTPUT
- name: "☁️ CF › Create Project (if nonexistent)"
id: task_publish_project_create
shell: bash
if: steps.task_publish_project_verify.outputs.result != 'true'
run: |
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}/pages/projects" \
-H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \
-H "Content-Type:application/json" \
--data '{"name":"${{ inputs.PROJECT_NAME || 'my-site' }}", "production_branch":"${{ inputs.BRANCH || 'main' }}"}'
- name: "☁️ Publish to Cloudflare Pages"
id: task_publish_push
uses: aetherinox/cloudflare-publish-action@latest
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID || inputs.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ inputs.PROJECT_NAME || 'my-site' }}
directory: ${{ inputs.DIRECTORY_BUILD_OUTPUT || './' }}
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ inputs.BRANCH || 'main' }}
workingDirectory: ${{ inputs.DIRECTORY_WORKING || './' }}
wranglerVersion: ${{ inputs.WRANGLER_VERSION || '3' }}
We are always looking for contributors. If you feel that you can provide something useful to this package, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:
The following people have helped get this project going: