Last active
August 3, 2022 14:36
-
-
Save laneparton/7a29eae1810168dfd67aecc465f6d112 to your computer and use it in GitHub Desktop.
A webhook that builds Gatsby via an Express endpoint with a FIFO queue.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require("express"); | |
const util = require("util"); | |
const moment = require("moment"); // require | |
const exec = util.promisify(require("child_process").exec); | |
require("dotenv").config(); | |
// Overall, it isn't clear what the best method of building these webhooks is. | |
// Is Express the answer? Is an entirely different language more efficient than Node? | |
// I'm leaning towards Node primarily because Gatsby builds with Node (we already need the node image) | |
const app = express(); | |
let currentProcess = { | |
active: false, | |
dateTime: null, | |
}; | |
let currentQueue = []; | |
let buildId; | |
const port = process.env.PORT || 8000; | |
app.listen(port, () => { | |
console.log("[Gatsby Webhook] Listening on port:", port); | |
}); | |
app.get("/build_status", async (req, res) => { | |
if (currentProcess.active) { | |
res.send(`The site is building. It started at ${currentProcess.dateTime}`); | |
} else { | |
res.send("The site has built."); | |
} | |
}); | |
app.post("/build_site", async (req, res) => { | |
buildId = moment().unix(); | |
// -- Access Control -- | |
// We can append a secret auth token | |
// We can also whitelist IP addresses (such as, only run from OKD IPs) | |
// -- Headers -- | |
// We will change these to headers (like Gatsby Cloud) later... | |
// buildType = production || preview | |
// This can also be separated into its own webhook | |
const buildType = req.query.type || "production"; | |
// Maybe with this flag, we can delete the existing .cache folder and run a cold build | |
// If we delete .cache, but don't delete public - what happens? We could alternatively build in a new location and copy... | |
const clearCache = req.query.cache || true; | |
// -- First Pass -- | |
if (currentProcess.active === false) { | |
console.log("[Gatsby Webhook] Build Request Received: " + buildId); | |
res.send(`[Gatsby Webhook] Build Request Received\n`); | |
// Add them to the queue | |
currentQueue.push(buildId); | |
// Collect data about the current process | |
currentProcess = { | |
active: true, | |
dateTime: buildId, | |
}; | |
build(); | |
} else { | |
// -- Add to the Queue -- | |
if ((currentQueue.length = 2)) { | |
// replace the second one with the current (latest) one | |
currentQueue[1] = buildId; | |
} | |
console.log("[Gatsby Webhook] Current Queue:"); | |
console.info(currentQueue); | |
console.log("[Gatsby Webhook] A build is already in progress. This has been added to the queue."); | |
res.send(`[Gatsby Webhook] A build is already in progress. This has been added to the queue.\n`); | |
} | |
}); | |
async function buildGatsbyCommand() { | |
try { | |
const { stdout, stderr } = await exec( | |
"node_modules/.bin/gatsby build --verbose" | |
); | |
console.log(stdout); | |
console.log("stderr:", stderr); | |
} catch (e) { | |
console.error(e); // should contain code (exit code) and signal (that caused the termination). | |
} | |
} | |
function build() { | |
console.log("[Gatsby Webhook] Building: " + currentQueue[0]); | |
buildGatsbyCommand() | |
.then(() => { | |
console.log("[Gatsby Webhook] Build " + currentQueue[0] + " has built."); | |
currentProcess = { | |
active: false, | |
dateTime: null, | |
}; | |
currentQueue.shift(); | |
console.log("[Gatsby Webhook] Current Queue:"); | |
console.info(currentQueue); | |
}) | |
.then(() => { | |
// If there are more items in the queue, keep building them. | |
if (currentQueue.length > 0) { | |
currentProcess = { | |
active: true, | |
dateTime: currentQueue[0], | |
}; | |
build(); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Gatsby Webhook
This is very much a WIP. It currently supports the idea of a FIFO queue of a current build and the latest build.
This is specifically built for Gatsby + Drupal, but would work with any CMS that supports the idea of a POST webhook.