Skip to content
This repository has been archived by the owner on Jul 15, 2024. It is now read-only.

feat: monorepo setup #337

Merged
merged 1 commit into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 83 additions & 14 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,87 @@
name: Build & Push to container registry
name: Build & Push Docker Image to container image registry

on:
release:
types: [created]
push:
branches:
- "**"
pull_request:
branches:
- "**"
paths:
- "Dockerfile"
workflow_call:
inputs:
ADD_FLAVOR:
description: "Whether to add flavor (only -dev atm) to the image tag"
type: boolean
required: false
default: true
NO_CACHE:
description: "Whether to use build cache"
type: boolean
required: false
default: false
SCOPE:
description: "Scope of the image (e.g. 'bot')"
type: string
required: true

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
docker:
uses: nezuchan/workflows/.github/workflows/docker-build.yml@main
secrets: inherit
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
scope: ${{ fromJson(inputs.SCOPE) }}
steps:
- name: Check Out Repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 2

#- name: Set up QEMU (We don't need QEMU, because we don't build images for platforms other than linux/amd64, which is our current native arch in our infra
# uses: docker/[email protected]

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0

- name: Login to GitHub Container Registry
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
if: ${{ github.event_name != 'pull_request' }}
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract tag name
id: tags
if: ${{ github.event_name == 'release' }}
run: echo ::set-output name=name::${GITHUB_REF##*/}

- name: Extract flavor
id: flavor
if: ${{ inputs.ADD_FLAVOR == true }}
run: if [ "${{ github.event_name }}" = "release" ]; then echo ::set-output name=name::; else echo ::set-output name=name::-dev; fi

- name: Generate Docker image metadata
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
id: img_meta
with:
flavor: |
latest=auto
suffix=${{ steps.flavor.outputs.name }}
images: ghcr.io/nezuchan/${{ matrix.scope }}
tags: |
${{ steps.tags.outputs.name }}
latest

- name: Build and push
id: docker_build
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: ./
tags: ${{ steps.img_meta.outputs.tags }}
labels: ${{ steps.img_meta.outputs.labels }}
push: ${{ github.event_name != 'pull_request' }}
build-args: |
"SCOPE=@nezuchan/${{ matrix.scope }}"
cache-from: type=gha,mode=max
cache-to: type=gha,mode=max
no-cache: ${{ inputs.NO_CACHE == true }}
12 changes: 12 additions & 0 deletions .github/workflows/services-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Release services

on:
release:
types: [created]

jobs:
docker:
uses: ./.github/workflows/docker.yml
with:
scope: '["kanao-gateway"]'
secrets: inherit
45 changes: 45 additions & 0 deletions .github/workflows/services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2023 Hazmi35 (https://github.com/Hazmi35)
name: Services Nightly Builds

on:
push:
branches:
- main
paths:
- "Dockerfile"
- "services/**"
pull_request:
branches:
- main
paths:
- "Dockerfile"

jobs:
build:
runs-on: ubuntu-latest
outputs:
folders: ${{ steps.json.outputs.folders }}
steps:
- name: Check Out Repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 2
- name: List changed folders
id: changed
run: |
echo ::set-output name=folders::$(git diff --name-only HEAD~1 HEAD | grep -E 'services/.*' | cut -d'/' -f2 | sort | uniq | tr '\n' ',' | sed 's/,$//')
- name: List all folders if no changes
if: steps.changed.outputs.folders == ''
id: all
run: |
echo ::set-output name=folders::$(ls services | tr '\n' ',' | sed 's/,$//')
- name: Turn output into JSON array
id: json
run: |
echo ::set-output name=folders::[$(echo ${{ steps.changed.outputs.folders || steps.all.outputs.folders }} | sed 's/,/","/g;s/^/"/;s/$/"/')]
docker:
needs: build
uses: ./.github/workflows/docker.yml
with:
scope: ${{ needs.build.outputs.folders }}
secrets: inherit
Empty file added .turbo/cookies/0.cookie
Empty file.
Empty file added .turbo/cookies/1.cookie
Empty file.
55 changes: 39 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,52 @@
FROM ghcr.io/hazmi35/node:20-dev-alpine as build-stage
# Copyright 2023 Hazmi35 (https://github.com/Hazmi35)
FROM ghcr.io/hazmi35/node:20-dev-alpine as dev

LABEL name "NezukoChan Gateway (Docker Build)"
LABEL maintainer "KagChi"
# Prepare with corepack (experimental feature)
RUN corepack enable

RUN corepack enable && corepack prepare pnpm@latest
# Prepare
FROM dev as prepare

COPY package*.json .
COPY pnpm-lock.yaml .

RUN pnpm install --frozen-lockfile
ARG SCOPE
WORKDIR /prepare

# Scoped install for monorepo
RUN npm install --global turbo
COPY . .
RUN turbo prune --scope=${SCOPE} --docker
RUN cp -r tsconfig* /prepare/out/json

# Build the project
FROM dev AS builder

WORKDIR /builder

# Set NPM_CONFIG_USERCONFIG build args
ARG SCOPE

# First install the dependencies (as they change less often)
COPY --from=prepare /prepare/out/json/ .
COPY --from=prepare /prepare/out/pnpm-lock.yaml ./pnpm-lock.yaml

# Install dependencies
RUN pnpm install --frozen-lockfile

# Build the project
COPY --from=prepare /prepare/out/full/ .
RUN pnpm run build

RUN pnpm prune --production
# Deploy the service
RUN pnpm deploy -P --filter=${SCOPE} /out

# Get ready for production
FROM ghcr.io/hazmi35/node:20-alpine

LABEL name "NezukoChan Gateway Production"
LABEL maintainer "KagChi"
LABEL name "${SCOPE}"

COPY --from=build-stage /tmp/build/package.json .
COPY --from=build-stage /tmp/build/pnpm-lock.yaml .
COPY --from=build-stage /tmp/build/node_modules ./node_modules
COPY --from=build-stage /tmp/build/dist ./dist
# Copy needed files
COPY --from=builder /out/package.json .
COPY --from=builder /out/node_modules ./node_modules
COPY --from=builder /out/dist ./dist

CMD ["node", "dist/index.js"]
# Start the app with node
CMD ["npm", "start"]
29 changes: 0 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,4 @@

</div>

# Requirements
- NodeJS 16+

# Features
- Zero downtime deployments, You will almost never need to restart the gateway service, allowing absolute 100% uptime for your bot. Even when a restart is required, kanao will resume the sessions, so you will not lose a single event.
- Big Bot Sharding support
- Docker replica

# Docker Replica

To deploy replica the container must connected to docker sock in order know which replica in they are
```yaml
version: '3.8'

services:
kanao:
deploy:
resources:
limits:
memory: "256M"
replicas: ${GATEWAY_REPLICA_COUNT:-3}
restart: always
image: 'ghcr.io/nezuchan/kanao:latest'
env_file:
- .env
volumes:
- /var/run/docker.sock:/var/run/docker.sock
```

Being used in production by NezukoChan, Musical Tune, and more.
64 changes: 12 additions & 52 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,61 +1,21 @@
{
"name": "@nezuchan/kanao",
"version": "4.0.0",
"description": "A standalone service for connecting to the Discord gateway.",
"name": "kanao",
"version": "1.0.0",
"description": "A standalone service for connecting to the Discord gateway",
"type": "module",
"scripts": {
"build": "turbo run build",
"lint": "turbo run lint",
"lint:fix": "turbo run lint:fix"
},
"keywords": [],
"author": "",
"license": "GPL-3.0",
"author": "KagChi",
"type": "module",
"main": "dist",
"scripts": {
"build": "rimraf dist && swc ./src -d dist --config-file .swcrc --strip-leading-paths",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"start": "node -r dotenv/config dist/index.js",
"start:dev": "npm run build && node -r dotenv/config dist/index.js"
},
"dependencies": {
"@discordjs/collection": "^2.0.0",
"@discordjs/rest": "^2.2.0",
"@discordjs/ws": "^1.0.2",
"@nezuchan/constants": "^0.8.0",
"@nezuchan/utilities": "^0.6.2",
"@sapphire/pieces": "^4.2.2",
"@sapphire/result": "^2.6.6",
"@sapphire/time-utilities": "^1.7.12",
"@sapphire/utilities": "^3.15.3",
"@skyra/start-banner": "^2.0.1",
"amqp-connection-manager": "^4.1.14",
"amqplib": "^0.10.3",
"bufferutil": "^4.0.8",
"discord-api-types": "^0.37.69",
"dockerode": "^4.0.2",
"dotenv": "^16.4.3",
"drizzle-orm": "^0.29.3",
"gradient-string": "^2.0.2",
"pino": "^8.18.0",
"pino-pretty": "^10.3.1",
"postgres": "^3.4.3",
"prometheus-middleware": "^1.3.3",
"tslib": "^2.6.2",
"utf-8-validate": "^6.0.3"
},
"devDependencies": {
"@hazmi35/eslint-config": "^13.3.1",
"@swc/cli": "^0.3.9",
"@swc/core": "^1.4.0",
"@types/amqplib": "^0.10.4",
"@types/dockerode": "^3.3.23",
"@types/gradient-string": "^1.1.5",
"@types/node": "^20.11.17",
"@vladfrangu/async_event_emitter": "^2.2.4",
"drizzle-kit": "^0.20.14",
"eslint": "^8.56.0",
"rimraf": "^5.0.5",
"turbo": "^1.12.3",
"typescript": "^5.3.3"
},
"optionalDependencies": {
"ioredis": "^5.3.2",
"pino-loki": "^2.2.1",
"zlib-sync": "^0.1.9"
}
}
Loading
Loading