Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve CloudFlare cache clear logging and GitHub Stars bugfix #1587

Merged
merged 7 commits into from
Jul 19, 2020
1 change: 1 addition & 0 deletions gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ exports.createSchemaCustomization = api =>
exports.sourceNodes = api => callOnModels(models, 'sourceNodes', api)
exports.onCreateNode = api => callOnModels(models, 'onCreateNode', api)
exports.createPages = api => callOnModels(models, 'createPages', api)
exports.createResolvers = api => callOnModels(models, 'createResolvers', api)
exports.onPostBuild = api => callOnModels(models, 'onPostBuild', api)

exports.onCreatePage = ({ page, actions }) => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"develop": "gatsby develop",
"dev": "gatsby develop",
"build": "gatsby build",
"start": "./scripts/clear-cloudflare-cache.js; node ./src/server/index.js",
"start": "./src/server/index.js",
"heroku-postbuild": "./scripts/deploy-with-s3.js",
"test": "jest",
"format-staged": "pretty-quick --staged --no-restage --bail",
Expand Down
65 changes: 37 additions & 28 deletions scripts/clear-cloudflare-cache.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/usr/bin/env node
/* global process */

// This script runs just before the app starts. If we are running the
// production heroku app (the only one with the below env variables)
// the cache gets cleared.
// This script is run inside the S3 deploy script, after everything else, to
// clear the CloudFlare cache of stale page data programmatically.
//
// To clear the cache yourself, you can use the button in the
// cloudflare dashboard ("Caching tab > Purge everything"), or run
// this script with the required environment variables:
// cloudflare dashboard ("Caching tab > Purge everything")
//
// This module requires three environment variables to run:
//
// - CONTEXT: The exported function will immediately return without doing
// anything if this variable is not set to "production"
//
// - CLOUDFLARE_TOKEN: a token with the "Zone.Cache Purge" permission.
// You can generate this token in "My Profile > API Tokens"
Expand All @@ -17,9 +17,23 @@

const fetch = require('isomorphic-fetch')

const { CLOUDFLARE_TOKEN, CLOUDFLARE_ZONE_ID, CONTEXT } = process.env
module.exports = async function () {
const { CLOUDFLARE_TOKEN, CLOUDFLARE_ZONE_ID, CONTEXT } = process.env

if (CONTEXT !== 'production') {
console.log(
'Skipping CloudFlare cache purge because CONTEXT is not set to production.'
)
return
}

if (!(CLOUDFLARE_TOKEN && CLOUDFLARE_ZONE_ID)) {
console.error(
'Skipping CloudFlare cache purge because CLOUDFLARE_TOKEN and/or CLOUDFLARE_ZONE_ID are not set.'
)
return
}

async function main() {
const res = await fetch(
`https://api.cloudflare.com/client/v4/zones/${CLOUDFLARE_ZONE_ID}/purge_cache`,
{
Expand All @@ -34,26 +48,21 @@ async function main() {
}
)

const body = await res.text()

if (!res.ok) {
throw new Error('Error response received from CloudFlare: ' + body)
}

console.log('Cleared cache successfully')
}
const body = await res.json()

if (CONTEXT === 'production') {
if (!(CLOUDFLARE_TOKEN && CLOUDFLARE_ZONE_ID)) {
console.error(
'scripts/clear-cloudflare-cache.js: ' +
'need CLOUDFLARE_TOKEN and CLOUDFLARE_ZONE_ID environment variables.'
if (!res.ok || !body.success) {
throw new Error(
'CloudFlare cache clear failed! ' +
JSON.stringify(
{
status: res.status,
errors: body.errors
},
undefined,
2
)
)
process.exit(1)
}

main().catch(e => {
console.error(e)
process.exit(1)
})
console.log('Cleared CloudFlare cache successfully')
}
8 changes: 7 additions & 1 deletion scripts/deploy-with-s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const path = require('path')
const PRODUCTION_PREFIX = 'dvc-org-prod'

const { DEPLOY_OPTIONS } = process.env
const clearCloudflareCache = require('./clear-cloudflare-cache')

// Generate deploy options from a comma separated string in the DEPLOY_OPTIONS
// env var. If DEPLOY_OPTIONS isn't set, use a default setting.
Expand All @@ -20,7 +21,8 @@ const deployOptions = DEPLOY_OPTIONS
download: true,
build: true,
upload: true,
clean: true
clean: true,
clearCloudflareCache: true
}

if (deployOptions.logSteps) {
Expand Down Expand Up @@ -129,6 +131,10 @@ async function main() {
console.log('Cleaning all local cache!')
await cleanAllLocal()
}

if (deployOptions.clearCloudflareCache) {
await clearCloudflareCache()
}
}

main().catch(e => {
Expand Down
43 changes: 31 additions & 12 deletions src/gatsby/models/github/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
gatsby-plugin-github-api. If no GITHUB_TOKEN is specified, this node will be
filled with default dummy data instead of throwing like using the plugin
alone does.
*/
*/

async function createStaticGithubDataNode(api, fieldData = {}) {
const {
Expand Down Expand Up @@ -36,17 +36,36 @@ async function createStaticGithubDataNode(api, fieldData = {}) {
}

module.exports = {
sourceNodes: createStaticGithubDataNode,
async onCreateNode(api) {
const {
node,
actions: { createParentChildLink }
} = api
if (node.internal.type !== 'GithubData') return
const child = await createStaticGithubDataNode(api, {
parent: node.id,
stars: node.rawResult.data.repository.stargazers.totalCount
async createSchemaCustomization({ actions: { createTypes }, schema }) {
createTypes(
schema.buildObjectType({
name: 'StaticGithubData',
fields: {
stars: 'String'
}
})
)
},
async createResolvers({ createResolvers }) {
createResolvers({
Query: {
staticGithubData: {
type: 'StaticGithubData',
async resolve(source, args, context) {
const nodes = await context.nodeModel.getAllNodes({
type: 'GithubData'
})
const node = nodes[0]
return node
? {
stars: node.rawResult.data.repository.stargazers.totalCount
}
: {
stars: 8888
}
}
}
}
})
await createParentChildLink({ child, parent: node })
}
}