Skip to content

Commit

Permalink
Merge pull request #9 from familab/mjh/feature/publish-tweaks
Browse files Browse the repository at this point in the history
Improved Deployment
  • Loading branch information
BZWingZero authored Apr 20, 2024
2 parents b19aade + 81cd54c commit bad14c1
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 25 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
34 changes: 25 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
FROM node:18-alpine
FROM node:18-alpine as base
LABEL org.opencontainers.image.source = "https://github.com/familab/accessController"


FROM base as build_api
# Build API

RUN npm install --global pnpm

WORKDIR /home
WORKDIR /build
COPY package.json \
tsconfig.json \
pnpm-workspace.yaml \
./

COPY tsconfig.json ./
WORKDIR /build/api
COPY api/package.json \
api/tsconfig.json \
api/tsconfig.build.json \
api/
COPY api/src api/src
./
COPY api/src src/

RUN pnpm install
RUN pnpm run build
RUN pnpm \
--filter=@familab/access-controller.api \
--prod \
deploy deployment


FROM base

RUN cd api && \
pnpm install && \
pnpm run build
COPY --from=build_api /build/api/deployment ./

ENTRYPOINT node ./api/build/server.js
ENTRYPOINT node ./build/server.js
50 changes: 43 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
<style>
body {
color: #fda501;
background-color: #2b2b2b;
}
</style>

FamiLAB Access Controller
=========================

Expand All @@ -28,6 +21,8 @@ See [nfc/README.md](./nfc/README.md)

See [api/README.md](./api/README.md)

--------------------------------

## Development Setup

1. Install Node 18+
Expand All @@ -41,6 +36,47 @@ See [api/README.md](./api/README.md)
```
4. Follow Development Setup instructions for the sub-project you wish to work on.

--------------------------------

## Deployment Process

The Docker image is built via GitHub Actions whenever a new commit is merged into the `release/v4` branch. The image is
therefore tagged `ghcr.io/familab/accesscontroller:release-v4`.

The server application is composed of multiple docker containers defined by the `./access-controller.stack.yml` Docker
Stack. To deploy this file to the server, you must have a Docker Context set up locally, and then update the Stack using
the stack file.

### Setup Docker Context

On your local machine, create a new [Docker Context](https://docs.docker.com/engine/context/working-with-contexts/) for
the access controller server.

```bash
docker context create familab.accesscontroller --docker "host=ssh://[email protected]"
docker context use familab.accesscontroller
```

Once you run these commands all `docker *` commands you use will target the remote server.

You can always switch back to targeting your local machine by running:

```bash
docker context use default
```

### Update Stack

Once you have a Docker Context set up for the remote server, run the following command to push the Stack.

```bash
docker stack deploy -c "./access-controller.stack.yml" access-controller
```

Make sure to check the logs of the containers to ensure the deployment worked.

--------------------------------

## Project Status

Currently implementing Phase 0.
Expand Down
26 changes: 26 additions & 0 deletions access-controller.stack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Docker Swarm Stack
version: "3.9"

services:
auth_service:
image: ghcr.io/familab/accesscontroller:release-v4
build:
context: ./
ports:
- "8080:8080/tcp"
secrets:
- google_credentials_client_email
- google_credentials_private_key
environment:
SERVER_PORT: 8080
LOGGING.LEVEL: info
GOOGLE.SPREADSHEET_ID: 1Mq3VC8-aO_3UA5PiUksvpzVHU1C49I5I1nvsnFs80Zo
GOOGLE.SPREADSHEET_RANGE: Sheet1
GOOGLE.CREDENTIALS.CLIENT_EMAIL#file: /run/secrets/google_credentials_client_email
GOOGLE.CREDENTIALS.PRIVATE_KEY#file: /run/secrets/google_credentials_private_key

secrets:
google_credentials_client_email:
external: true
google_credentials_private_key:
external: true
3 changes: 3 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"name": "@familab/access-controller.api",
"description": "Modern API Rewrite of Familab's access control system.",
"type": "module",
"files": [
"build"
],
"scripts": {
"build": "tsc --project tsconfig.build.json",
"lint": "eslint --ext .ts src",
Expand Down
23 changes: 14 additions & 9 deletions api/src/env.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import process from "node:process";
import fs from "node:fs";

class Env {
public static string(variableName: string): string;
public static string(variableName: string, defaultValue: string): string;
public static string(variableName: string, canBeUndefined: true): string | undefined;
public static string(variableName: string, arg2: string | boolean = false): string | undefined {
const val = process.env[variableName];
public static string(variableName: string, arg2?: string): string | undefined {
let val = process.env[variableName];

// If no value is present for the env var, check if its saved as a file?
if (val == null) {
const filename = process.env[variableName + "#file"];
if (filename && fs.existsSync(filename)) {
val = fs.readFileSync(filename, { encoding: "utf-8" })
}
}

if (val != null) return val;
if (typeof arg2 === "string") return arg2;
if (arg2) return undefined;
throw new Error(`Missing environment variable '${variableName}'`);
}

public static number(variableName: string): number {
const val1 = process.env[variableName];
if (!val1) {
throw new Error(`Missing environment variable '${variableName}'`);
}
const val1 = Env.string(variableName);
const val2 = Number(val1);
if (isNaN(val2)) {
throw new Error(`Invalid environment variable '${variableName}=${val1}'`);
Expand All @@ -29,7 +34,7 @@ export const env = {
serverPort: Env.number("SERVER_PORT"),
logging: {
level: Env.string("LOGGING.LEVEL", "off"),
logfile: Env.string("LOGGING.LOGFILE", true),
logfile: Env.string("LOGGING.LOGFILE", "logfile.log"),
},
database: Env.string("DATABASE", ".temp.sqlite"),
google: {
Expand Down

0 comments on commit bad14c1

Please sign in to comment.