diff --git a/.dockerignore b/.dockerignore index d852c45..2a9859f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,11 +1,11 @@ .angular/ +.github/ .idea/ .dist/ .e2e/ non-vcs/ .git/ node_modules/ -server/node_modules/ server/target/ server/ts-gen/ -docker-compose*.yml +non-vcs/docker/docker-compose*.yml diff --git a/.github/workflows/build-push-and-deploy-ngx-ramblers-docker-image.yml b/.github/workflows/build-push-and-deploy-ngx-ramblers-docker-image.yml new file mode 100644 index 0000000..455dcf6 --- /dev/null +++ b/.github/workflows/build-push-and-deploy-ngx-ramblers-docker-image.yml @@ -0,0 +1,43 @@ +name: Build and Deploy NGX-Ramblers Docker Image + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Log in to Docker Hub + run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + - name: Build the Docker image + run: | + docker build . --file Dockerfile --tag ngx-ramblers:latest + - name: Tag the Docker image + run: docker tag ngx-ramblers:latest ${{ secrets.DOCKER_USERNAME }}/ngx-ramblers:latest + - name: Push the Docker image to Docker Hub + run: docker push ${{ secrets.DOCKER_USERNAME }}/ngx-ramblers:latest + - name: Deploy the Docker image + run: | + docker run -d -p 5000:5000 --name ngx-ramblers ${{ secrets.DOCKER_USERNAME }}/ngx-ramblers:latest \ + -e AUTH_SECRET=${{ secrets.AUTH_SECRET }} \ + -e AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ + -e AWS_BUCKET=${{ secrets.AWS_BUCKET }} \ + -e AWS_REGION=${{ secrets.AWS_REGION }} \ + -e AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ + -e CHROMEDRIVER_PATH=${{ secrets.CHROMEDRIVER_PATH }} \ + -e CHROMEDRIVER_VERSION=${{ secrets.CHROMEDRIVER_VERSION }} \ + -e CHROME_VERSION=${{ secrets.CHROME_VERSION }} \ + -e DEBUG=${{ secrets.DEBUG }} \ + -e DEBUG_COLORS=${{ secrets.DEBUG_COLORS }} \ + -e GOOGLE_CHROME_BIN=${{ secrets.GOOGLE_CHROME_BIN }} \ + -e GOOGLE_MAPS_APIKEY=${{ secrets.GOOGLE_MAPS_APIKEY }} \ + -e MEETUP_ACCESS_TOKEN=${{ secrets.MEETUP_ACCESS_TOKEN }} \ + -e MONGODB_URI=${{ secrets.MONGODB_URI }} \ + -e NODE_ENV=${{ secrets.NODE_ENV }} \ + -e NODE_OPTIONS=${{ secrets.NODE_OPTIONS }} \ + -e WALKS_NPM_COMMAND=${{ secrets.WALKS_NPM_COMMAND }} diff --git a/Dockerfile b/Dockerfile index 459d079..312bdf2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use the official Node.js image as the base image -FROM node:20.16.0 +FROM node:20.11.0 # Set the working directory inside the container WORKDIR /usr/src/app @@ -37,5 +37,6 @@ RUN npm install # Expose the port the application will run on EXPOSE 5000 +WORKDIR /usr/src/app # Define the command to run the server application CMD ["npm", "run", "server", "--prefix", "server"] diff --git a/README.md b/README.md index 5aff6eb..b34ca9c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ # Welcome to NGX-Ramblers! +[![NGX-Ramblers Docker Image](https://github.com/nbarrett/ngx-ramblers/actions/workflows/build-push-and-deploy-ngx-ramblers-docker-image.yml/badge.svg)](https://github.com/nbarrett/ngx-ramblers/actions/workflows/build-push-and-deploy-ngx-ramblers-docker-image.yml) [![Heroku](https://img.shields.io/badge/heroku-%23430098.svg?style=&logo=heroku&logoColor=white)](https://github.com/nbarrett/ngx-ramblers/deployments/ngx-ramblers-staging) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![GitHub issues](https://img.shields.io/github/issues/nbarrett/ngx-ramblers)](https://github.com/nbarrett/ngx-ramblers/issues) diff --git a/server/lib/env-config/env-config.ts b/server/lib/env-config/env-config.ts index 53d5da6..2ac8fd8 100644 --- a/server/lib/env-config/env-config.ts +++ b/server/lib/env-config/env-config.ts @@ -1,11 +1,12 @@ -const APP_PREFIX: string = "NGX_RAMBLERS_"; +const ENV_PREFIX: string = "SITE_"; function validatedEnvironmentVariable(variableName: string, prefixed?: boolean): string { - const resolvedName = prefixed ? APP_PREFIX + variableName : variableName; - const variableValue = process.env[resolvedName]; + const resolvedName = prefixed ? ENV_PREFIX + variableName : variableName; + const variableValue = process.env[resolvedName] || process.env[variableName]; if (!variableValue) { throw new Error("Environment variable '" + resolvedName + "' must be set"); } else { + console.info(`Environment variable '${resolvedName}' is set to '${variableValue}'`); return variableValue; } } diff --git a/server/lib/instagram/instagram-controllers.ts b/server/lib/instagram/instagram-controllers.ts index 14883aa..27305c2 100644 --- a/server/lib/instagram/instagram-controllers.ts +++ b/server/lib/instagram/instagram-controllers.ts @@ -5,7 +5,7 @@ import { Instagram, SystemConfig } from "../../../projects/ngx-ramblers/src/app/ import { systemConfig } from "../config/system-config"; const debug = debugLib(envConfig.logNamespace("instagram")); -debug.enabled = true; +debug.enabled = false; export async function configuredInstagram(): Promise { const config: SystemConfig = await systemConfig(); diff --git a/server/lib/instagram/recent-media.ts b/server/lib/instagram/recent-media.ts index 8a5fa30..f296b91 100644 --- a/server/lib/instagram/recent-media.ts +++ b/server/lib/instagram/recent-media.ts @@ -7,7 +7,7 @@ import { Instagram } from "../../../projects/ngx-ramblers/src/app/models/system. import { configuredInstagram } from "./instagram-controllers"; const debug = debugLib(envConfig.logNamespace("instagram:recent-media")); -debug.enabled = true; +debug.enabled = false; const refreshOnEachCall = true; async function recentMediaRequest(req: Request, res: Response) { diff --git a/server/lib/instagram/refresh-access-token.ts b/server/lib/instagram/refresh-access-token.ts index 0d38af1..077eea7 100644 --- a/server/lib/instagram/refresh-access-token.ts +++ b/server/lib/instagram/refresh-access-token.ts @@ -6,7 +6,7 @@ import { Instagram } from "../../../projects/ngx-ramblers/src/app/models/system. import { configuredInstagram } from "./instagram-controllers"; const debug = debugLib(envConfig.logNamespace("instagram:refresh-token")); -debug.enabled = true; +debug.enabled = false; export async function refreshAccessToken(req: Request, res: Response) { const instagram: Instagram = await configuredInstagram(); diff --git a/server/lib/mongo/mongoose-client.ts b/server/lib/mongo/mongoose-client.ts index 6d702de..a295a41 100644 --- a/server/lib/mongo/mongoose-client.ts +++ b/server/lib/mongo/mongoose-client.ts @@ -3,6 +3,8 @@ import debug from "debug"; import mongoose from "mongoose"; import transforms = require("./controllers/transforms"); +const debugLog = debug(envConfig.logNamespace("local-database")); +debugLog.enabled = false; let connected = false; function createDebugFor(model: any): debug.Debugger { @@ -45,15 +47,17 @@ export function create(model: mongoose.Model, data: T) { } export function connect(debug: debug.Debugger) { - return mongoose.connect(envConfig.mongo.uri, { + const mongoUri = envConfig.mongo.uri.replace(/^"|"$/g, ""); ; + debugLog("MongoDB URI:", mongoUri); + return mongoose.connect(mongoUri, { useUnifiedTopology: true, useNewUrlParser: true, }).then(response => { - debug("Connected to database:", envConfig.mongo.uri, "configured models:", response.models); + debug("Connected to database:", mongoUri, "configured models:", response.models); connected = true; return true; }).catch(error => { - debug("Connection failed:", envConfig.mongo.uri, "error:", error); + debug("Connection failed:", mongoUri, "error:", error); throw error; }); } diff --git a/server/lib/server.ts b/server/lib/server.ts index 1ce5892..963d10e 100644 --- a/server/lib/server.ts +++ b/server/lib/server.ts @@ -44,7 +44,7 @@ import memberResource = require("./mongo/routes/member-resource"); install(); const debugLog = debug(envConfig.logNamespace("server")); -debugLog.enabled = false; +debugLog.enabled = true; const folderNavigationsUp = process.env.NODE_ENV === "production" ? "../../" : ""; const distFolder = path.resolve(__dirname, folderNavigationsUp, "../../dist/ngx-ramblers"); const currentDir = path.resolve(__dirname);