Skip to content

Commit

Permalink
Merge pull request #7 from WalshyDev/feature/support-api-tokens
Browse files Browse the repository at this point in the history
Support API Tokens
  • Loading branch information
WalshyDev authored May 8, 2022
2 parents 9ab07b4 + 8d1b631 commit 1f60f5e
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 38 deletions.
46 changes: 31 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,32 @@ Wait for a Cloudflare Pages build to finish so you can do actions like purge cac

## Usage
```yml
- name: Await CF Pages
uses: WalshyDev/cf-pages-await@v1
with:
accountEmail: ${{ secrets.CF_ACCOUNT_EMAIL }}
apiKey: ${{ secrets.CF_API_KEY }}
accountId: '4e599df4216133509abaac54b109a647'
project: 'example-pages-project'
# Add this if you want GitHub Deployments (see below)
githubToken: ${{ secrets.GITHUB_TOKEN }}
# Add this if you want to wait for a deployment triggered by a specfied commit
commitHash: ${{ steps.push-changes.outputs.commit-hash }}
name: Deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
# Allow GITHUB_TOKEN to write deployments for my action (https://docs.github.com/en/actions/security-guides/automatic-token-authentication)
permissions:
contents: read
deployments: write
steps:
- name: Await CF Pages
uses: WalshyDev/cf-pages-await@v1
with:
# Uncomment these two lines if you wish to use the Global API Key (Not recommended!)
# accountEmail: ${{ secrets.CF_ACCOUNT_EMAIL }}
# apiKey: ${{ secrets.CF_API_KEY }}

# Use an API token (Recommended!)
apiToken: ${{ secrets.CF_API_TOKEN }}

accountId: '4e599df4216133509abaac54b109a647'
project: 'example-pages-project'
# Add this if you want GitHub Deployments (see below)
githubToken: ${{ secrets.GITHUB_TOKEN }}
# Add this if you want to wait for a deployment triggered by a specfied commit
commitHash: ${{ steps.push-changes.outputs.commit-hash }}
```
### Example
Expand All @@ -29,17 +44,18 @@ jobs:
- name: Wait for CF Pages
id: cf-pages
uses: WalshyDev/cf-pages-await@v1
permissions:
contents: read
deployments: write
with:
accountEmail: ${{ secrets.CF_ACCOUNT_EMAIL }}
apiKey: ${{ secrets.CF_API_KEY }}
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: '4e599df4216133509abaac54b109a647'
project: 'test'
# Add this if you want GitHub Deployments (see below)
githubToken: ${{ secrets.GITHUB_TOKEN }}
- run: |
curl -X \
-H "X-Auth-Email: ${{ secrets.CF_ACCOUNT_EMAIL }}" \
-H "X-Auth-Key: ${{ secrets.CF_API_KEY }}" \
-H "Authorization: ${{ secrets.CF_API_TOKEN }}" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}' \
https://api.cloudflare.com/client/v4/zones/8d0c8239f88f98a8cb82ec7bb29b8556/purge_cache
Expand Down
14 changes: 9 additions & 5 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ description: 'Wait for Cloudflare Pages to build'
author: 'WalshyDev'
inputs:
accountEmail:
description: 'Cloudflare account email (Needed for auth)'
required: true
description: 'Cloudflare account email (Not recommended)'
required: false
apiKey:
description: 'Cloudflare API Key (Tokens aren''t supported in the API yet :( )'
required: true
description: 'Cloudflare API Key (Not recommended)'
required: false
apiToken:
description: 'Cloudflare API Token (Recommended)'
required: false

accountId:
description: 'Cloudflare account ID'
required: true
Expand All @@ -32,7 +36,7 @@ outputs:
success:
description: 'If the build passed or failed'
runs:
using: 'node12'
using: 'node16'
main: 'dist/action.js'
branding:
icon: 'cloud'
Expand Down
28 changes: 20 additions & 8 deletions dist/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -11273,17 +11273,22 @@ var waiting = true;
var ghDeployment;
var markedAsInProgress = false;
async function run() {
const accountEmail = core.getInput("accountEmail", { required: true, trimWhitespace: true });
const apiKey = core.getInput("apiKey", { required: true, trimWhitespace: true });
const accountEmail = core.getInput("accountEmail", { required: false, trimWhitespace: true });
const apiKey = core.getInput("apiKey", { required: false, trimWhitespace: true });
const apiToken = core.getInput("apiToken", { required: false, trimWhitespace: true });
const accountId = core.getInput("accountId", { required: true, trimWhitespace: true });
const project = core.getInput("project", { required: true, trimWhitespace: true });
const token = core.getInput("githubToken", { required: false, trimWhitespace: true });
const commitHash = core.getInput("commitHash", { required: false, trimWhitespace: true });
if (!validateAuthInputs(apiToken, accountEmail, apiKey)) {
return;
}
const authHeaders = apiToken !== "" ? { Authorization: `Bearer ${apiToken}` } : { "X-Auth-Email": accountEmail, "X-Auth-Key": apiKey };
console.log("Waiting for Pages to finish building...");
let lastStage = "";
while (waiting) {
await sleep();
const deployment = await pollApi(accountEmail, apiKey, accountId, project, commitHash);
const deployment = await pollApi(authHeaders, accountId, project, commitHash);
if (!deployment) {
console.log("Waiting for the deployment to start...");
continue;
Expand Down Expand Up @@ -11317,16 +11322,23 @@ async function run() {
}
}
}
async function pollApi(accountEmail, apiKey, accountId, project, commitHash) {
function validateAuthInputs(token, email, key) {
if (token !== "") {
return true;
}
if (email !== "" && key !== "") {
return true;
}
core.setFailed("Please specify authentication details! Set either `apiToken` or `accountEmail` + `accountKey`!");
return false;
}
async function pollApi(authHeaders, accountId, project, commitHash) {
var _a2, _b, _c;
let res;
let body;
try {
res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/pages/projects/${project}/deployments?sort_by=created_on&sort_order=desc`, {
headers: {
"X-Auth-Email": accountEmail,
"X-Auth-Key": apiKey
}
headers: { ...authHeaders }
});
} catch (e) {
core.error(`Failed to send request to CF API - network issue? ${e.message}`);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cf-pages-await",
"version": "1.1.0",
"version": "1.3.0",
"description": "Wait for a Cloudflare Pages build to finish",
"main": "index.js",
"keywords": [],
Expand Down
37 changes: 28 additions & 9 deletions src/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,38 @@ import * as github from '@actions/github';
import fetch, { Response } from 'node-fetch';

import { context } from '@actions/github/lib/utils';
import { ApiResponse, Deployment } from './types';
import { ApiResponse, AuthHeaders, Deployment } from './types';

let waiting = true;
// @ts-ignore - Typing GitHub's responses is a pain in the ass
let ghDeployment;
let markedAsInProgress = false;

export default async function run() {
const accountEmail = core.getInput('accountEmail', { required: true, trimWhitespace: true });
const apiKey = core.getInput('apiKey', { required: true, trimWhitespace: true });
const accountEmail = core.getInput('accountEmail', { required: false, trimWhitespace: true });
const apiKey = core.getInput('apiKey', { required: false, trimWhitespace: true });
const apiToken = core.getInput('apiToken', { required: false, trimWhitespace: true })

const accountId = core.getInput('accountId', { required: true, trimWhitespace: true });
const project = core.getInput('project', { required: true, trimWhitespace: true });
const token = core.getInput('githubToken', { required: false, trimWhitespace: true });
const commitHash = core.getInput('commitHash', { required: false, trimWhitespace: true });

// Validate we have either token or both email + key
if (!validateAuthInputs(apiToken, accountEmail, apiKey)) {
return;
}

const authHeaders: AuthHeaders = apiToken !== '' ? { Authorization: `Bearer ${apiToken}` } : { 'X-Auth-Email': accountEmail, 'X-Auth-Key': apiKey };

console.log('Waiting for Pages to finish building...');
let lastStage = '';

while (waiting) {
// We want to wait a few seconds, don't want to spam the API :)
await sleep();

const deployment: Deployment|undefined = await pollApi(accountEmail, apiKey, accountId, project, commitHash);
const deployment: Deployment|undefined = await pollApi(authHeaders, accountId, project, commitHash);
if (!deployment) {
console.log('Waiting for the deployment to start...');
continue;
Expand Down Expand Up @@ -70,7 +79,20 @@ export default async function run() {
}
}

async function pollApi(accountEmail: string, apiKey: string, accountId: string, project: string, commitHash: string): Promise<Deployment|undefined> {
function validateAuthInputs(token: string, email: string, key: string) {
if (token !== '') {
return true;
}

if (email !== '' && key !== '') {
return true;
}

core.setFailed('Please specify authentication details! Set either `apiToken` or `accountEmail` + `accountKey`!');
return false;
}

async function pollApi(authHeaders: AuthHeaders, accountId: string, project: string, commitHash: string): Promise<Deployment|undefined> {
// curl -X GET "https://api.cloudflare.com/client/v4/accounts/:account_id/pages/projects/:project_name/deployments" \
// -H "X-Auth-Email: [email protected]" \
// -H "X-Auth-Key: c2547eb745079dac9320b638f5e225cf483cc5cfdda41"
Expand All @@ -79,10 +101,7 @@ async function pollApi(accountEmail: string, apiKey: string, accountId: string,
// Try and fetch, may fail due to a network issue
try {
res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/pages/projects/${project}/deployments?sort_by=created_on&sort_order=desc`, {
headers: {
'X-Auth-Email': accountEmail,
'X-Auth-Key': apiKey,
}
headers: { ...authHeaders },
});
} catch(e) {
// @ts-ignore
Expand Down
6 changes: 6 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export interface ApiResponse {
result: Deployment[];
}

export interface AuthHeaders {
Authorization?: string;
'X-Auth-Email'?: string;
'X-Auth-Key'?: string;
}

export interface Deployment {
id: string;
short_id: string;
Expand Down

0 comments on commit 1f60f5e

Please sign in to comment.