💚 fixing webpack config for building app with good env and improve docker build

This commit is contained in:
ChatonDeAru 2024-03-26 03:36:04 +01:00
parent 9d019c085d
commit e18e3415a1
No known key found for this signature in database
GPG Key ID: 3CADF765A409F755
8 changed files with 40 additions and 97 deletions

View File

@ -1,11 +1,20 @@
name: Build & Deploy to Scaleway
name: Build for production
on:
workflow_dispatch:
envType:
description: "Environment to deploy to"
required: true
default: "prod"
type: choice
options:
- prod
- staging
jobs:
build:
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.envType }}
steps:
- uses: actions/checkout@v4
- name: Login to Scaleway Container Registry
@ -15,6 +24,6 @@ jobs:
password: ${{ secrets.SCALEWAY_API_KEY }}
registry: ${{ secrets.CONTAINER_REGISTRY_ENDPOINT }}
- name: Build the Docker image
run: docker build . -t ${{ secrets.CONTAINER_REGISTRY_ENDPOINT }}/fo-prod
run: docker build . -t ${{ secrets.CONTAINER_REGISTRY_ENDPOINT }}/fo-${{ github.event.inputs.envType }}
- name: Push the Docker Image
run: docker push ${{ secrets.CONTAINER_REGISTRY_ENDPOINT }}/fo-prod
run: docker push ${{ secrets.CONTAINER_REGISTRY_ENDPOINT }}/fo-${{ github.event.inputs.envType }}

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ public/*
# Access
access/*
!access/.gitkeep
# Misc
.DS_Store

View File

@ -1,29 +1,33 @@
# App build
FROM node:20-alpine as build-stage
ARG user=node
ARG project_dir=/opt/node_app
ARG PORT=3000
ARG API_URL="http://localhost:3000"
ENV PORT $PORT
ENV NODE_OPTIONS="--max_old_space_size=4096"
EXPOSE $PORT
ENV PORT=$PORT
ENV API_URL=$API_URL
## Enable corepack for proper version of YARN
RUN corepack enable
RUN mkdir $project_dir && chown $user:$user $project_dir
USER $user
WORKDIR $project_dir
WORKDIR /app
## Copy file for YARN then install all deps
COPY --chown=$user .yarnrc.yml yarn.lock package.json ./
COPY .yarnrc.yml yarn.lock package.json ./
RUN yarn install --frozen-lockfile
COPY --chown=$user . ./
## Build the app
COPY . ./
RUN yarn run build
CMD ["yarn", "start"]
## Run stage
FROM node:20-alpine
COPY --from=build-stage /app/public ./public
COPY --from=build-stage /app/node_modules ./node_modules
COPY --from=build-stage /app/access ./access
EXPOSE $PORT
CMD ["node", "./public/server"]

0
access/.gitkeep Normal file
View File

View File

@ -24,7 +24,7 @@ module.exports = {
__LOCAL__: false,
__REGISTER_DISCORD_COMMANDS__: false,
__TEST__: true,
API_URL: "http://localhost:3000",
API_URL: "http://localhost:3333",
},
maxConcurrency: 50,
maxWorkers: 1,

View File

@ -1,14 +0,0 @@
/* Copyright Coplay. All Rights Reserved. Use of this source code is governed by an MIT-style license that can be found in the LICENSE file at https://coplay.org/colicense */
import { NextFunction, Request, Response, Router } from "express"
import * as path from "path"
const certbotRouter: Router = Router()
certbotRouter.use((request: Request, response: Response, _next: NextFunction) => {
const filename = request.originalUrl.replace(/.*\//, "")
const resolvedPath: string = path.resolve(`../certbot/.well-known/acme-challenge/${filename}`)
response.setHeader("Content-Type", "text/html")
return response.sendFile(resolvedPath)
})
export default certbotRouter

View File

@ -8,14 +8,10 @@ import hpp from "hpp"
import favicon from "serve-favicon"
import chalk from "chalk"
import * as http from "http"
import * as https from "https"
import * as fs from "fs"
import _ from "lodash"
import devServer from "./devServer"
import ssr from "./ssr"
import certbotRouter from "../routes/certbot"
import { hasSecret, secure } from "./secure"
import { announcementListGet } from "./gsheets/announcements"
import { detailedBoxListGet } from "./gsheets/boxes"
@ -54,7 +50,7 @@ import { notificationsSubscribe, notificationMain } from "./notifications"
import { /* discordRegisterCommands, */ discordBot, hasDiscordAccess } from "./discordBot"
import checkAccess from "./checkAccess"
import { hasGSheetsAccess } from "./gsheets/accessors"
import { addStatus, showStatusAt } from "./status"
import { addStatus } from "./status"
import {
miscDiscordInvitation,
miscFestivalDateListGet,
@ -81,10 +77,6 @@ app.use(helmet({ contentSecurityPolicy: false }))
app.use(hpp())
// Compress all requests
app.use(compression())
// Https with certbot and Let's Encrypt
if (!__DEV__) {
app.use("/.well-known/acme-challenge", certbotRouter)
}
// Use for http request debug (show errors only)
app.use(logger("dev", { skip: (_req, res) => res.statusCode < 400 }))
@ -164,70 +156,21 @@ app.post("/notifications/subscribe", notificationsSubscribe)
app.get("*", ssr)
/**
* Create HTTP and HTTPS server.
* Create server.
*/
const servers = [{ protocol: "http", server: http.createServer(app) }]
interface Cert {
key: string
cert: string
}
const certPaths: Cert[] = [
{
// Prod
key: "/root/certbot/config/live/fo.parisestludique.fr/privkey.pem",
cert: "/root/certbot/config/live/fo.parisestludique.fr/fullchain.pem",
},
{
// Local
key: "../certbot/key.pem",
cert: "../certbot/cert.pem",
},
]
const validCertPath: Cert | undefined = certPaths.find((certPath: Cert) =>
_.every(certPath, (pemPath: string) => fs.existsSync(pemPath))
)
if (validCertPath) {
const httpsOptions = _.mapValues(validCertPath, (pemPath: string) => fs.readFileSync(pemPath))
servers.push({ protocol: "https", server: https.createServer(httpsOptions, app) })
showStatusAt(6)
} else {
showStatusAt(5)
}
/**
* Listen on provided port, on all network interfaces.
*/
servers.forEach(({ protocol, server }) => {
const port = Number(process.env.PORT) || 3000
server.listen(protocol === "http" ? port : port + 2)
server.on("error", onError)
server.on("listening", () => onListening(server))
})
/**
* Event listener for HTTP server 'error' event.
*/
function onError(error: any) {
const server = http.createServer(app)
server.listen(process.env.PORT || 3000)
server.on("error", (error: any) => {
if (error) {
addStatus("Server listening:", chalk.red(`==> 😭 OMG!!! ${error}`))
}
}
/**
* Event listener for HTTP server 'listening' event.
*/
function onListening(server: any) {
})
server.on("listening", () => {
const addr = server.address()
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr?.port}`
addStatus("Server listening:", chalk.green(`${bind}`))
}
})
if (hasGSheetsAccess()) {
addStatus("Database:", chalk.green(`✅ online from Google Sheet`))

View File

@ -52,7 +52,7 @@ const getPlugins = (isWeb: boolean) => {
__DEV__: isDev,
__LOCAL__: isLocal,
__REGISTER_DISCORD_COMMANDS__: isRegisterDiscordCommands,
API_URL: process.env.API_URL || "'http://localhost:3000'",
API_URL: `"${process.env.API_URL}"` || "'http://localhost:3000'",
}),
]