diff --git a/.docker/scripts.sh b/.docker/scripts.sh new file mode 100644 index 0000000..f7aaa8f --- /dev/null +++ b/.docker/scripts.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Applying Database Migrations" +/app/node_modules/.bin/prisma migrate deploy + +echo "Starting Application" +node /app/lib/servers/graphql-main.js \ No newline at end of file diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml new file mode 100644 index 0000000..cfa1cdf --- /dev/null +++ b/.github/workflows/build-image.yml @@ -0,0 +1,33 @@ +name: Build and Push Docker image + +on: + push: + branches: + - 'deployment-ci' + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v2 + with: + context: . + push: true + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index e62d445..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Build and Deploy to GKE - -on: - push: - branches: - - deployment-ci - -env: - PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }} - GKE_CLUSTER: ${{ secrets.GKE_CLUSTER_NAME }} - GKE_ZONE: ${{ secrets.GKE_CLUSTER_LOCATION }} - DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} - DEPLOYMENT_NAME: ranter-deploy-dev - IMAGE: ranter-dev-image - -jobs: - setup-build-publish-deploy: - name: Setup, Build, Publish, and Deploy - runs-on: ubuntu-latest - environment: production - - steps: - - name: Checkout - uses: actions/checkout@v2 - - # Setup gcloud CLI - - uses: google-github-actions/setup-gcloud@v0.2.1 - with: - service_account_key: ${{ secrets.GCP_SA_KEY }} - project_id: ${{ secrets.GCP_PROJECT_ID }} - - # helper for authentication - - run: |- - gcloud --quiet auth configure-docker - - # Get the GKE credentials so we can deploy to the cluster - - name: Get GKE credentials - run: |- - gcloud container clusters get-credentials $GKE_CLUSTER --zone $GKE_ZONE --project $PROJECT_ID - - # Build the Docker image - - name: Build - run: |- - docker build \ - --tag "$DOCKER_HUB_USERNAME/$IMAGE:latest" \ - --build-arg GITHUB_SHA="$GITHUB_SHA" \ - --build-arg GITHUB_REF="$GITHUB_REF" \ - . - - # Log in to Docker Hub - - name: Log in to Docker Hub - run: |- - echo "${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin - - # Push the Docker image - - name: Push - run: |- - docker push "$DOCKER_HUB_USERNAME/$IMAGE:latest" - - # Get the access token - - name: Get access token - id: get-access-token - run: |- - echo "::set-output name=access_token::$(gcloud auth print-access-token)" - - # Deploy the Docker image to the GKE cluster - - name: Deploy - run: |- - kubectl set image deployment/$DEPLOYMENT_NAME $DEPLOYMENT_NAME=$DOCKER_HUB_USERNAME/$IMAGE:latest --token "${{ steps.get-access-token.outputs.access_token }}" - kubectl rollout status deployment/$DEPLOYMENT_NAME --token "${{ steps.get-access-token.outputs.access_token }}" - kubectl get services -o wide --token "${{ steps.get-access-token.outputs.access_token }}" diff --git a/.github/workflows/spinup.yml b/.github/workflows/spinup.yml new file mode 100644 index 0000000..d505571 --- /dev/null +++ b/.github/workflows/spinup.yml @@ -0,0 +1,33 @@ +name: Spinup Server + +on: + push: + branches: ['deployment-ci'] + +jobs: + spinup-server: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' + + - name: Install direnv + run: sudo apt-get install direnv -y + + - name: Install dependencies + run: yarn install + + - name: Build the app + run: yarn build + + - name: Run Server & Get Healthz + run: | + . ./.envrc && yarn start & + sleep 5 + curl --fail http://localhost:4000/healthz diff --git a/Dockerfile b/Dockerfile index 42e6e3e..5beafa8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,23 @@ -FROM node:18 +FROM node:18 AS BUILD_IMAGE WORKDIR /app # Install dependencies -COPY *.json ./yarn.lock ./ +COPY . . RUN yarn install --frozen-lockfile -# Run Source Code -COPY . . \ No newline at end of file +# Build Source Code +COPY ./src ./src +RUN yarn build +RUN yarn install --frozen-lockfile --production + +FROM node:16 +COPY --from=BUILD_IMAGE /app/lib /app/lib +COPY --from=BUILD_IMAGE /app/node_modules /app/node_modules +COPY --from=BUILD_IMAGE /app/prisma /app/prisma +COPY --from=BUILD_IMAGE /app/.docker/scripts /app/.docker/scripts + +WORKDIR /app +COPY ./*.js ./package.json ./tsconfig.json ./yarn.lock ./default.yaml ./ + +CMD [".docker/scripts/start.sh"] \ No newline at end of file diff --git a/eslintonld.json b/eslintonld.json deleted file mode 100644 index 880110b..0000000 --- a/eslintonld.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "env": { - "node": true - }, - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "tsconfig.json", - "sourceType": "module" - }, - "plugins": ["eslint-plugin-import", "@typescript-eslint", "prettier"], - "extends": [ - "eslint:recommended", - "plugin:import/recommended", - "plugin:import/typescript", - "plugin:@typescript-eslint/recommended", - "prettier" - ], - "rules": { - "@typescript-eslint/no-extra-semi": "off", - - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/unified-signatures": "error", - - "import/no-deprecated": "error", - "import/no-extraneous-dependencies": "error", - "import/no-unassigned-import": "error", - "import/no-unresolved": "off", - "import/order": [ - "error", - { "newlines-between": "always-and-inside-groups" } - ], - - "prettier/prettier": [ - "error", - { - "semi": false, - "trailingComma": "none", - "quoteProps": "consistent", - "singleQuote": true, - "tabWidth": 4, - "useTabs": false, - "bracketSpacing": true, - "arrowParens": "always", - "proseWrap": "preserve", - "endOfLine": "lf" - } - ], - - "arrow-body-style": "off", - "prefer-arrow-callback": "off", - - "no-empty": ["error", { "allowEmptyCatch": true }], - "no-new-wrappers": "error", - "no-param-reassign": "error", - "no-return-await": "error", - "no-sequences": "error", - "no-throw-literal": "error", - "no-void": "error", - "@typescript-eslint/explicit-module-boundary-types": "off", - "no-async-promise-executor": "off" - }, - "settings": { - "import/resolver": { - "node": { - "paths": ["."] - } - } - } -}