Skip to content
upload-cloud

GitHub Action

Cloudflare Pages Publisher Action

1.0.0 Latest version

Cloudflare Pages Publisher Action

upload-cloud

Cloudflare Pages Publisher Action

Publish files from a github branch to Cloudflare Pages

Installation

Copy and paste the following snippet into your .yml file.

              

- name: Cloudflare Pages Publisher Action

uses: Aetherinox/[email protected]

Learn more about this action in Aetherinox/cloudflare-publish-action

Choose a version

Cloudflare Pages ☁️ Github Action


A forked copy of the Github action Cloudflare Pages which is updated to utilize NodeJS 20+ and continues updates.


Test Status Last Commit Size All Contributors





About

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.




Usage

  1. Create an API token within the Cloudflare Dashboard with the "Cloudflare Pages — Edit" permission.
  2. Within the example below, replace CLOUDFLARE_API_TOKEN with your given API token.
  3. 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

Get Account ID

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


Generate an API Token

To generate an API token:

  1. Log in to the Cloudflare Dashboard
  2. Select My Profile from the dropdown menu of your user icon on the top right of your dashboard.
  3. Select API Tokens > Create Token
  4. Under Custom Token, select Get Started
  5. Name your API Token in the Token name field
  6. Under Permissions, select Account, Cloudflare Pages and Edit
  7. Select Continue to Summary > Create Token


More information can be found on our guide for making Direct Upload deployments with continous integration.


Define Branch

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.


Define Working Directory

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.


Wrangler v3

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'



Outputs

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



Examples

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' }}




Contributors ✨

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: