M docs/hosting-design.md => docs/hosting-design.md +0 -1
@@ 4,4 4,3 @@ For the near term storing webpages on the disk of the machine that is
serving them is a fine approach. Long term we'll want to move towards
storing things inside of s3 buckets but the host machine has a 40gb
SSD which should last for a while.
-
M serve/app.js => serve/app.js +49 -3
@@ 1,6 1,7 @@
const express = require('express')
const jwt = require('jsonwebtoken')
const { execFile } = require('child_process')
+const axios = require('axios')
require('dotenv').config()
@@ 11,6 12,18 @@ const jobStatusMap = new Map()
app.use(express.json())
+// Sends a message to the zekebots discord channel. Doesn't wait for
+// the message to send and logs an error / success message as needed.
+const sendDiscordAlert = message => {
+ axios.post(process.env.WEBHOOOK_URL, {
+ content: message
+ }).then(function (response) {
+ console.log(`=> discord: (${message})`)
+ }).catch(function (error) {
+ console.log(`=/> discord. error: (${error})`)
+ });
+}
+
// Posting to deploy starts a build and returns a unique ID for that
// build. The status of the build can then be queried by making a get
// request to deploy with that ID as a URL param.
@@ 67,6 80,8 @@ app.post('/deploy', function(req, res) {
jobStatusMap.get(childProcessID).serverError = err.message
})
+ sendDiscordAlert(`deploying (${name}) for (${user})`)
+
res.status(200).json({
jobID: childProcessID
})
@@ 123,11 138,42 @@ app.post('/delete', function(req, res) {
})
}
- // TODO(zeke) - run undeploy script
+ const child = execFile('./undeploy.sh', [name])
+ const childProcessID = jobStatusMap.size.toString()
+ jobStatusMap.set(childProcessID, {
+ stdout: '',
+ stderr: '',
+ exitCode: undefined,
+ serverError: ''
+ })
+
+ child.stdout.on('data', data => {
+ jobStatusMap.get(childProcessID).stdout += data
+ })
+
+ child.stderr.on('data', data => {
+ jobStatusMap.get(childProcessID).stderr += data
+ })
+
+ child.on('exit', code => {
+ jobStatusMap.get(childProcessID).exitCode = code
+ })
+
+ child.on('error', err => {
+ // This firing indicates that:
+ //
+ // 1. The process could not be spawned, or
+ // 2. The process could not be killed, or
+ // 3. Sending a message to the child process failed.
+ //
+ // source: https://nodejs.org/api/child_process.html#child_process_event_error
+ jobStatusMap.get(childProcessID).serverError = err.message
+ })
+
+ sendDiscordAlert(`undeploying (${name}) for (${user})`)
res.status(200).json({
- name: name,
- user: user,
+ jobID: childProcessID
})
})
M serve/package-lock.json => serve/package-lock.json +41 -0
@@ 8,6 8,7 @@
"name": "serve",
"version": "0.0.1",
"dependencies": {
+ "axios": "^0.21.4",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1"
@@ 30,6 31,14 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
+ "node_modules/axios": {
+ "version": "0.21.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+ "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+ "dependencies": {
+ "follow-redirects": "^1.14.0"
+ }
+ },
"node_modules/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@@ 215,6 224,25 @@
"node": ">= 0.8"
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.14.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
+ "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ 613,6 641,14 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
+ "axios": {
+ "version": "0.21.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+ "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+ "requires": {
+ "follow-redirects": "^1.14.0"
+ }
+ },
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@@ 765,6 801,11 @@
"unpipe": "~1.0.0"
}
},
+ "follow-redirects": {
+ "version": "1.14.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
+ "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
+ },
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
M serve/package.json => serve/package.json +1 -0
@@ 8,6 8,7 @@
},
"author": "Zeke Medley",
"dependencies": {
+ "axios": "^0.21.4",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1"