From 2656182181eacfad3f1f2037cd7798b842668a49 Mon Sep 17 00:00:00 2001 From: Dan Livings Date: Thu, 19 Sep 2024 14:50:10 +0100 Subject: [PATCH 1/4] Add `Dockerfile` and `docker-compose.yml` files It's standard practice at dxw to make applications that need to be deployed somewhere into containers to avoid dependence on any one deployment platform and to avoid issues around replicability. --- Dockerfile | 24 ++++++++++++++++++++++++ docker-compose.yml | 5 +++++ 2 files changed, 29 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5813c99 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM node:22.8.0-slim + +WORKDIR /towtruck +VOLUME /data + +ARG APP_ID +ARG PRIVATE_KEY +ARG CLIENT_ID +ARG CLIENT_SECRET +ARG WEBHOOK_SECRET + +COPY . . + +RUN touch .env \ + && echo "APP_ID=$APP_ID" >> .env \ + && echo "PRIVATE_KEY=$PRIVATE_KEY" >> .env \ + && echo "CLIENT_ID=$CLIENT_ID" >> .env \ + && echo "CLIENT_SECRET=$CLIENT_SECRET" >> .env \ + && echo "WEBHOOK_SECRET=$WEBHOOK_SECRET" >> .env + +RUN npm install + +EXPOSE 3000 +CMD [ "sh", "-c", "npm run seed && exec npm run start" ] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2ca5091 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,5 @@ +services: + towtruck: + build: . + ports: + - "3000:3000" From f449617601392e64ff685ef7adc25338dd8f130a Mon Sep 17 00:00:00 2001 From: Dan Livings Date: Tue, 8 Oct 2024 13:08:32 +0100 Subject: [PATCH 2/4] Use Base64-encoded private key instead of path to .pem file This simplifies the deployment as this allows the private key to be passed in as an environment variable, rather than relying on a separate file to exist somewhere. --- .env.example | 2 +- README.md | 4 +++- octokitApp.js | 5 ++--- script/encode-key | 4 ++++ 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100755 script/encode-key diff --git a/.env.example b/.env.example index 8f9d0f5..1216987 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ APP_ID=123456 -PRIVATE_KEY_PATH=/path/to/app.private-key.pem +PRIVATE_KEY= # Use `script/encode-key ` to encode the private key CLIENT_ID=SomeClientId123 CLIENT_SECRET=secret WEBHOOK_SECRET=secret diff --git a/README.md b/README.md index 647db89..69b3f8a 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,9 @@ The environment variables are available here: https://github.com/organizations/d In order for Towtruck to communicate with the GitHub API, it needs several pieces of information, configured through environment variables: - `APP_ID`: The unique numeric ID assigned to the GitHub App. This can be found in the dxw-towtruck app settings. -- `PRIVATE_KEY_PATH`: The private key used to sign access token requests. Towtruck expects this to be an absolute path to a `.pem` file stored locally and generated by GitHub in the app settings. +- `PRIVATE_KEY`: The private key used to sign access token requests. + Towtruck expects this to be a `.pem` file generated by GitHub in the app settings and encoded using Base64. + This can be generated from the `.pem` file by running `script/encode-key ` in the terminal and copying the output. - `CLIENT_ID`: A unique alphanumeric ID assigned to the GitHub App. This can be found in the dxw-towtruck app settings - `CLIENT_SECRET`: A token used to authenticate API requests. These are generated by GitHub in the dxw-towtruck app settings. - `WEBHOOK_SECRET`: A user-defined secret used to authenticate GitHub to Towtruck for receiving webhooks. This must be exactly the same as it is entered in the app settings on GitHub. diff --git a/octokitApp.js b/octokitApp.js index 511f7d9..6b7c195 100644 --- a/octokitApp.js +++ b/octokitApp.js @@ -1,13 +1,12 @@ -import { readFileSync } from "fs"; import { App, createNodeMiddleware } from "@octokit/app"; const APP_ID = process.env.APP_ID; -const PRIVATE_KEY_PATH = process.env.PRIVATE_KEY_PATH; +const PRIVATE_KEY = process.env.PRIVATE_KEY; const CLIENT_ID = process.env.CLIENT_ID; const CLIENT_SECRET = process.env.CLIENT_SECRET; const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; -const privateKey = readFileSync(PRIVATE_KEY_PATH).toString(); +const privateKey = Buffer.from(PRIVATE_KEY, 'base64').toString('ascii'); const app = new App({ appId: APP_ID, diff --git a/script/encode-key b/script/encode-key new file mode 100755 index 0000000..2059577 --- /dev/null +++ b/script/encode-key @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cat $1 | openssl base64 | tr -d '\n' +echo From 8d283c48a458d290c32e90ad2b5f06a629167a13 Mon Sep 17 00:00:00 2001 From: Dan Livings Date: Tue, 8 Oct 2024 13:21:43 +0100 Subject: [PATCH 3/4] Add Heroku manifest --- heroku.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 heroku.yml diff --git a/heroku.yml b/heroku.yml new file mode 100644 index 0000000..8eec25b --- /dev/null +++ b/heroku.yml @@ -0,0 +1,3 @@ +build: + docker: + web: Dockerfile From c779301f2ff722c2a50dfa53e2c39df36e53679e Mon Sep 17 00:00:00 2001 From: Dan Livings Date: Tue, 8 Oct 2024 13:56:53 +0100 Subject: [PATCH 4/4] Allow for active port to be configured through `PORT` env var Heroku uses dynamic port assignment, so this allows Heroku to connect to the application using the port it's assigned. The default port of 3000 is still available for local development. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 2312a57..6f2aba0 100644 --- a/index.js +++ b/index.js @@ -36,7 +36,7 @@ const httpServer = createServer(async (request, response) => { return response.end(template); }); -const PORT = 3000; +const PORT = process.env.PORT || 3000; httpServer.listen(PORT, () => { console.info(`Server is running on port ${PORT}`); });