Skip to content

Commit

Permalink
Merge pull request #42 from dreampipcom/dev
Browse files Browse the repository at this point in the history
Deploy
  • Loading branch information
angeloreale authored Aug 24, 2024
2 parents 1979708 + 99ce16f commit ff08755
Show file tree
Hide file tree
Showing 20 changed files with 1,818 additions and 53 deletions.
3 changes: 3 additions & 0 deletions .env.local.public
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ NEXUS_MODE=
# base path: server-only
NEXUS_BASE_PATH=

# for docker images only
NEXUS_STANDALONE=

# keep alive secret for private endpoints healthcheck
NEXUS_KEEPALIVE=

Expand Down
108 changes: 108 additions & 0 deletions .github/workflows/deploy_gcp_prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: hypnos::deploy_prod

on:
push:
branches:
- main

# on:
# pull_request:
# branches:
# - dev

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
REGION: europe-west2
GAR_LOCATION: europe-west2-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/chain-service/

jobs:
build-and-push-image:
name: hypnos::build_and_push::docker_image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- name: hypnos::deploy_prod::docker::Checkout repository
uses: actions/checkout@v4

- name: hypnos::deploy_prod::docker::Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: hypnos::deploy_prod::docker::Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: hypnos::deploy_prod::docker::Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
API_URL=${{ secrets.API_URL_PROD }}
APPLE_CLIENT_ID=${{ secrets.APPLE_CLIENT_ID_PROD }}
APPLE_CLIENT_SECRET=${{ secrets.APPLE_CLIENT_SECRET_PROD }}
AUTH_SECRET=${{ secrets.AUTH_SECRET_PROD }}
AUTH_TRUST_HOST=${{ secrets.AUTH_TRUST_HOST_PROD }}
AUTH_URL=${{ secrets.AUTH_URL_PROD }}
EMAIL_FROM=${{ secrets.EMAIL_FROM_PROD }}
EMAIL_SERVER=${{ secrets.EMAIL_SERVER_PROD }}
FACEBOOK_CLIENT_ID=${{ secrets.FACEBOOK_CLIENT_ID_PROD }}
FACEBOOK_CLIENT_SECRET=${{ secrets.FACEBOOK_CLIENT_SECRET_PROD }}
GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID_PROD }}
GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET_PROD }}
INSTAGRAM_CLIENT_ID=${{ secrets.INSTAGRAM_CLIENT_ID_PROD }}
INSTAGRAM_CLIENT_SECRET=${{ secrets.INSTAGRAM_CLIENT_SECRET_PROD }}
KV_REST_API_READ_ONLY_TOKEN=${{ secrets.KV_REST_API_READ_ONLY_TOKEN_PROD }}
KV_REST_API_TOKEN=${{ secrets.KV_REST_API_TOKEN_PROD }}
KV_REST_API_URL=${{ secrets.KV_REST_API_URL_PROD }}
KV_URL=${{ secrets.KV_URL_PROD }}
MAIN_URL=${{ secrets.MAIN_URL_PROD }}
MONGODB_DATABASE=${{ secrets.MONGODB_DATABASE_PROD }}
MONGODB_DEFAULT_ORG=${{ secrets.MONGODB_DEFAULT_ORG_PROD }}
MONGODB_ORGS_DATABASE=${{ secrets.MONGODB_ORGS_DATABASE_PROD }}
MONGODB_PRIVATE_URI=${{ secrets.MONGODB_PRIVATE_URI_PROD }}
MONGODB_PUBLIC_URI=${{ secrets.MONGODB_PUBLIC_URI_PROD }}
MONGODB_USERS_DATABASE=${{ secrets.MONGODB_USERS_DATABASE_PROD }}
NEXUS_KEEPALIVE=${{ secrets.NEXUS_KEEPALIVE_PROD }}
NEXUS_MODE=${{ secrets.NEXUS_MODE_PROD }}
NEXUS_STANDALONE=true
PRISMA_PRIVATE_URI=${{ secrets.MONGODB_PRIVATE_URI_PROD }}
PRISMA_PUBLIC_URI=${{ secrets.MONGODB_PUBLIC_URI_PROD }}
- name: hypnos::deploy_prod::docker::Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

deploy-to-gcp-vm:
needs: build-and-push-image
name: hypnos::deploy_prod::push_to_gcp::vm
runs-on: ubuntu-latest

steps:
- name: hypnos::deploy_prod::push_to_gcp::vm::install ssh keys
run: |
install -m 600 -D /dev/null ~/.ssh/id_rsa
echo "${{ secrets.SSH_PRIVATE_KEY_PROD }}" > ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SSH_HOST_PROD }} > ~/.ssh/known_hosts
- name: hypnos::deploy_prod::push_to_gcp::vm::connect and pull
run: ssh ${{ secrets.SSH_USER_PROD }}@${{ secrets.SSH_HOST_PROD }} "docker login ghcr.io -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASSWORD }} && docker pull ${{ secrets.IMAGE_TAG_PROD }} && docker stop hypnos && docker rm hypnos && docker run -d --name hypnos --restart unless-stopped -p ${{ secrets.IMAGE_PORT_PROD }}:3001 ${{ secrets.IMAGE_TAG_PROD }} && exit"
- name: cleanup
run: rm -rf ~/.ssh
5 changes: 2 additions & 3 deletions .github/workflows/pr_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ jobs:
- name: hypnos::checks::build::Build
run: npm run build
env:
MONGODB_URI: ${{ secrets.MONGODB_URI }}
EMAIL_SERVER: ${{ secrets.EMAIL_SERVER }}
EMAIL_FROM: ${{ secrets.EMAIL_FROM }}
EMAIL_SERVER: ${{ secrets.EMAIL_SERVER_PROD }}
EMAIL_FROM: ${{ secrets.EMAIL_FROM_PROD }}

run-lint:
name: hypnos::checks::lint
Expand Down
239 changes: 239 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
FROM node:20-alpine AS base

# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat

WORKDIR /app
ARG NEXUS_STANDALONE
ENV NEXUS_STANDALONE=$NEXUS_STANDALONE

# Install dependencies based on the preferred package manager
RUN mkdir -p ./prisma
COPY prisma/schema-* ./prisma
RUN mkdir -p ./patches
COPY patches/* ./patches
COPY postInstall.js ./
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi

# Rebuild the source code only when needed
FROM base AS builder

WORKDIR /app
ARG NEXUS_STANDALONE
ENV NEXUS_STANDALONE=$NEXUS_STANDALONE

COPY --from=deps /app/node_modules ./node_modules
COPY . .
COPY --from=deps /app/package.json /app/yarn.lock* /app/package-lock.json* /app/pnpm-lock.yaml* ./
COPY --from=deps /app/prisma/schema-* ./prisma
RUN npm run schema:generate:all:standalone

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1


# ARGS VARS
ARG GITHUB_ID
ARG GITHUB_SECRET
ARG GOOGLE_CLIENT_ID
ARG GOOGLE_CLIENT_SECRET
ARG INSTAGRAM_CLIENT_ID
ARG INSTAGRAM_CLIENT_SECRET
ARG FACEBOOK_CLIENT_ID
ARG FACEBOOK_CLIENT_SECRET
ARG APPLE_CLIENT_ID
ARG APPLE_CLIENT_SECRET
ARG EMAIL_FROM
ARG EMAIL_SERVER

ARG AUTH_TRUST_HOST
ARG AUTH_SECRET
ARG AUTH_URL
ARG MAIN_URL
ARG API_URL

ARG KV_REST_API_READ_ONLY_TOKEN
ARG KV_REST_API_TOKEN
ARG KV_REST_API_URL
ARG KV_URL

ARG MONGODB_DATABASE
ARG MONGODB_USERS_DATABASE
ARG MONGODB_ORGS_DATABASE
ARG MONGODB_DEFAULT_ORG

ARG PRISMA_PRIVATE_URI
ARG MONGODB_PRIVATE_URI
ARG PRISMA_PUBLIC_URI
ARG MONGODB_PUBLIC_URI

ARG NEXUS_MODE

# ENV FROM ARGS VARS
ENV GITHUB_ID=$GITHUB_ID
ENV GITHUB_SECRET=$GITHUB_SECRET
ENV GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID
ENV GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET
ENV INSTAGRAM_CLIENT_ID=$INSTAGRAM_CLIENT_ID
ENV INSTAGRAM_CLIENT_SECRET=$INSTAGRAM_CLIENT_SECRET
ENV FACEBOOK_CLIENT_ID=$FACEBOOK_CLIENT_ID
ENV FACEBOOK_CLIENT_SECRET=$FACEBOOK_CLIENT_SECRET
ENV APPLE_CLIENT_ID=$APPLE_CLIENT_ID
ENV APPLE_CLIENT_SECRET=$APPLE_CLIENT_SECRET

ENV EMAIL_FROM=$EMAIL_FROM
ENV EMAIL_SERVER=$EMAIL_SERVER

ENV AUTH_TRUST_HOST=$AUTH_TRUST_HOST
ENV AUTH_SECRET=$AUTH_SECRET
ENV AUTH_URL=$AUTH_URL
ENV MAIN_URL=$MAIN_URL
ENV API_URL=$API_URL


ENV KV_REST_API_READ_ONLY_TOKEN=$KV_REST_API_READ_ONLY_TOKEN
ENV KV_REST_API_TOKEN=$KV_REST_API_TOKEN
ENV KV_REST_API_URL=$KV_REST_API_URL
ENV KV_URL=$KV_URL

ENV MONGODB_DATABASE=$MONGODB_DATABASE
ENV MONGODB_USERS_DATABASE=$MONGODB_USERS_DATABASE
ENV MONGODB_ORGS_DATABASE=$MONGODB_ORGS_DATABASE
ENV MONGODB_DEFAULT_ORG=$MONGODB_DEFAULT_ORG

ENV PRISMA_PRIVATE_URI=$PRISMA_PRIVATE_URI
ENV MONGODB_PRIVATE_URI=$MONGODB_PRIVATE_URI
ENV PRISMA_PUBLIC_URI=$PRISMA_PUBLIC_URI
ENV MONGODB_PUBLIC_URI=$MONGODB_PUBLIC_URI

ENV NEXUS_MODE=$NEXUS_MODE

RUN \
if [ -f yarn.lock ]; then yarn run build:vm; \
elif [ -f package-lock.json ]; then npm run build:vm; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build:vm; \
else echo "Lockfile not found." && exit 1; \
fi

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ARG NEXUS_STANDALONE
ENV NEXUS_STANDALONE=$NEXUS_STANDALONE

ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1

# ARGS VARS
ARG GITHUB_ID
ARG GITHUB_SECRET
ARG GOOGLE_CLIENT_ID
ARG GOOGLE_CLIENT_SECRET
ARG INSTAGRAM_CLIENT_ID
ARG INSTAGRAM_CLIENT_SECRET
ARG FACEBOOK_CLIENT_ID
ARG FACEBOOK_CLIENT_SECRET
ARG APPLE_CLIENT_ID
ARG APPLE_CLIENT_SECRET
ARG EMAIL_FROM
ARG EMAIL_SERVER

ARG AUTH_TRUST_HOST
ARG AUTH_SECRET
ARG AUTH_URL
ARG MAIN_URL
ARG API_URL

ARG KV_REST_API_READ_ONLY_TOKEN
ARG KV_REST_API_TOKEN
ARG KV_REST_API_URL
ARG KV_URL

ARG MONGODB_DATABASE
ARG MONGODB_USERS_DATABASE
ARG MONGODB_ORGS_DATABASE
ARG MONGODB_DEFAULT_ORG

ARG PRISMA_PRIVATE_URI
ARG MONGODB_PRIVATE_URI
ARG PRISMA_PUBLIC_URI
ARG MONGODB_PUBLIC_URI

ARG NEXUS_MODE

# ENV FROM ARGS VARS
ENV GITHUB_ID=$GITHUB_ID
ENV GITHUB_SECRET=$GITHUB_SECRET
ENV GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID
ENV GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET
ENV INSTAGRAM_CLIENT_ID=$INSTAGRAM_CLIENT_ID
ENV INSTAGRAM_CLIENT_SECRET=$INSTAGRAM_CLIENT_SECRET
ENV FACEBOOK_CLIENT_ID=$FACEBOOK_CLIENT_ID
ENV FACEBOOK_CLIENT_SECRET=$FACEBOOK_CLIENT_SECRET
ENV APPLE_CLIENT_ID=$APPLE_CLIENT_ID
ENV APPLE_CLIENT_SECRET=$APPLE_CLIENT_SECRET

ENV EMAIL_FROM=$EMAIL_FROM
ENV EMAIL_SERVER=$EMAIL_SERVER

ENV AUTH_TRUST_HOST=$AUTH_TRUST_HOST
ENV AUTH_SECRET=$AUTH_SECRET
ENV AUTH_URL=$AUTH_URL
ENV MAIN_URL=$MAIN_URL
ENV API_URL=$API_URL


ENV KV_REST_API_READ_ONLY_TOKEN=$KV_REST_API_READ_ONLY_TOKEN
ENV KV_REST_API_TOKEN=$KV_REST_API_TOKEN
ENV KV_REST_API_URL=$KV_REST_API_URL
ENV KV_URL=$KV_URL

ENV MONGODB_DATABASE=$MONGODB_DATABASE
ENV MONGODB_USERS_DATABASE=$MONGODB_USERS_DATABASE
ENV MONGODB_ORGS_DATABASE=$MONGODB_ORGS_DATABASE
ENV MONGODB_DEFAULT_ORG=$MONGODB_DEFAULT_ORG

ENV PRISMA_PRIVATE_URI=$PRISMA_PRIVATE_URI
ENV MONGODB_PRIVATE_URI=$MONGODB_PRIVATE_URI
ENV PRISMA_PUBLIC_URI=$PRISMA_PUBLIC_URI
ENV MONGODB_PUBLIC_URI=$MONGODB_PUBLIC_URI

ENV NEXUS_MODE=$NEXUS_MODE

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
COPY --from=builder /app/pm2-vm.json ./

RUN npm i -g pm2

# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3001

ENV PORT=3001

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
CMD [ "npm", "run", "start:vm:pm2" ]
Loading

0 comments on commit ff08755

Please sign in to comment.