From 5c3e5e8d94060ee8dc1d6f6ace4a1efabb7c84c3 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 14:09:47 +0100 Subject: [PATCH 01/13] Use node 20.8.1 in Docker build --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e55824e7..3b14c7ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18-alpine AS base +FROM node:20.8.1-alpine AS base # Install dependencies only when needed FROM base AS deps From de49fe457b44ab26cc0544f87352916d0c7fbf11 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 14:19:42 +0100 Subject: [PATCH 02/13] Create a .env.local to allow build to run --- .github/workflows/build-docker-image.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index dca98fda..4f8cb1e8 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -11,6 +11,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Set a .env.local + run: | + touch .env.local + echo "AUTH0_SECRET=placholder" >> .env.local + echo "AUTH0_BASE_URL=http://placholder_host:3000" >> .env.local + echo "AUTH0_ISSUER_BASE_URL=https://placeholder_domain.com" >> .env.local + echo "AUTH0_CLIENT_ID=placeholder_client_id" >> .env.local + echo "AUTH0_CLIENT_SECRET=placeholder_client_secret" >> .env.local + echo "AUTH0_AUDIENCE=placeholder_audience" >> .env.local + echo "AUTH0_SCOPE=openid profile" >> .env.local + - name: Build the app and Docker image run: | docker build -t shapedocs . From 1abaaad3b79dba146581b051dba3bb582c703aea Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 14:30:52 +0100 Subject: [PATCH 03/13] Add example env --- .env.example | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..b5608260 --- /dev/null +++ b/.env.example @@ -0,0 +1,19 @@ +NEXT_PUBLIC_SHAPE_DOCS_TITLE='Shape Docs' +SHAPE_DOCS_BASE_URL='https://docs.shapetools.io' +AUTH0_SECRET='use [openssl rand -hex 32] to generate a 32 bytes value' +AUTH0_BASE_URL='http://dev.local:3000' +AUTH0_ISSUER_BASE_URL='https://shape-docs-dev.eu.auth0.com' +AUTH0_CLIENT_ID='Your client ID' +AUTH0_CLIENT_SECRET='Your client secret' +AUTH0_MANAGEMENT_DOMAIN='shape-docs-dev.eu.auth0.com' +AUTH0_MANAGEMENT_CLIENT_ID='Your client ID' +AUTH0_MANAGEMENT_CLIENT_SECRET='Your client secret' +GITHUB_CLIENT_ID='GitHub App client ID' +GITHUB_CLIENT_SECRET='GitHub App client secret' +GITHUB_APP_ID='the GitHub App id' +GITHUB_PRIVATE_KEY_BASE_64='base 64 encoded version of the private key' +GITHUB_WEBHOOK_SECRET='preshared secret also put in app conf in GitHub' +GITHUB_WEBHOK_REPOSITORY_ALLOWLIST='' +GITHUB_WEBHOK_REPOSITORY_DISALLOWLIST='' +GITHUB_ORGANIZATION_NAME='shapehq' +REDIS_URL='' \ No newline at end of file From 31ccb22fafcb09ff00cf0421f77747cee2340d3d Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 14:31:28 +0100 Subject: [PATCH 04/13] Copy example to local env --- .github/workflows/build-docker-image.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 4f8cb1e8..c88a29b9 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -11,16 +11,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set a .env.local + - name: Create .env.local run: | - touch .env.local - echo "AUTH0_SECRET=placholder" >> .env.local - echo "AUTH0_BASE_URL=http://placholder_host:3000" >> .env.local - echo "AUTH0_ISSUER_BASE_URL=https://placeholder_domain.com" >> .env.local - echo "AUTH0_CLIENT_ID=placeholder_client_id" >> .env.local - echo "AUTH0_CLIENT_SECRET=placeholder_client_secret" >> .env.local - echo "AUTH0_AUDIENCE=placeholder_audience" >> .env.local - echo "AUTH0_SCOPE=openid profile" >> .env.local + cp .env.example .env.local - name: Build the app and Docker image run: | From bf8f8d111fa350db4d7cdc81444d14f783de52cd Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 15:21:29 +0100 Subject: [PATCH 05/13] Adjust .env.example to be valid for Docker build --- .env.example | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index b5608260..4ffeb0b1 100644 --- a/.env.example +++ b/.env.example @@ -1,19 +1,19 @@ -NEXT_PUBLIC_SHAPE_DOCS_TITLE='Shape Docs' -SHAPE_DOCS_BASE_URL='https://docs.shapetools.io' -AUTH0_SECRET='use [openssl rand -hex 32] to generate a 32 bytes value' AUTH0_BASE_URL='http://dev.local:3000' -AUTH0_ISSUER_BASE_URL='https://shape-docs-dev.eu.auth0.com' AUTH0_CLIENT_ID='Your client ID' AUTH0_CLIENT_SECRET='Your client secret' -AUTH0_MANAGEMENT_DOMAIN='shape-docs-dev.eu.auth0.com' +AUTH0_ISSUER_BASE_URL='https://shape-docs-dev.eu.auth0.com' AUTH0_MANAGEMENT_CLIENT_ID='Your client ID' AUTH0_MANAGEMENT_CLIENT_SECRET='Your client secret' +AUTH0_MANAGEMENT_DOMAIN='shape-docs-dev.eu.auth0.com' +AUTH0_SECRET='use [openssl rand -hex 32] to generate a 32 bytes value' +GITHUB_APP_ID=123456 GITHUB_CLIENT_ID='GitHub App client ID' GITHUB_CLIENT_SECRET='GitHub App client secret' -GITHUB_APP_ID='the GitHub App id' +GITHUB_ORGANIZATION_NAME='shapehq' GITHUB_PRIVATE_KEY_BASE_64='base 64 encoded version of the private key' -GITHUB_WEBHOOK_SECRET='preshared secret also put in app conf in GitHub' GITHUB_WEBHOK_REPOSITORY_ALLOWLIST='' GITHUB_WEBHOK_REPOSITORY_DISALLOWLIST='' -GITHUB_ORGANIZATION_NAME='shapehq' -REDIS_URL='' \ No newline at end of file +GITHUB_WEBHOOK_SECRET='preshared secret also put in app conf in GitHub' +NEXT_PUBLIC_SHAPE_DOCS_TITLE='Shape Docs' +REDIS_URL='' +SHAPE_DOCS_BASE_URL='https://docs.shapetools.io' \ No newline at end of file From 29938b2ec24afff27ccab6fa0b81e8bec3f224c3 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 15:21:43 +0100 Subject: [PATCH 06/13] Enable standalone output to be used with Docker image --- next.config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/next.config.js b/next.config.js index 5373e6a7..761f61ab 100644 --- a/next.config.js +++ b/next.config.js @@ -4,7 +4,9 @@ const nextConfig = { // Allows production builds to successfully complete even if it has linting errors. // This is only OK because we do linting as part of our CI setup. ignoreDuringBuilds: true, - } + }, + // Output standalone to be used for Docker builds. + output: 'standalone', } module.exports = nextConfig From 0e5ed25dd0412e6da4b811c45df5a8ebc1312cab Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 16:14:04 +0100 Subject: [PATCH 07/13] Authenticate with AWS and push --- .github/workflows/build-docker-image.yml | 62 +++++++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index c88a29b9..80119694 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -3,6 +3,15 @@ name: "Build Docker image" on: workflow_dispatch: {} +env: + AWS_REGION: eu-central-1 + ECR_REPOSITORY: shapedocs + ECS_SERVICE: StagingApp-AppService7F8F0CA1-jCcia0OvXEXa + ECS_CLUSTER: StagingApp-EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3-L9xrshUBnmqe + ECS_TASK_DEFINITION_NAME: StagingAppAppServiceTaskDef1613562E + CONTAINER_NAME: web + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_SHAPE_DOCS }} + jobs: build: name: Build @@ -11,10 +20,59 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Install 1Password CLI + uses: 1password/install-cli-action@v1 + + - name: Install AWS credentials from 1Password + run: | + AWS_ACCESS_KEY_ID=$(op read "op://Shape Docs GitHub Actions/AWS GitHub Actions User/access_key_id") + AWS_SECRET_ACCESS_KEY=$(op read "op://Shape Docs GitHub Actions/AWS GitHub Actions User/secret_access_key") + echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" >> $GITHUB_ENV + echo "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" >> $GITHUB_ENV + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4.0.1 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2.0.1 + + - name: Fetch task definition + run: | + aws ecs describe-task-definition --task-definition ${{ env.ECS_TASK_DEFINITION_NAME }} --region ${{ env.AWS_REGION }} > task-definition.json + - name: Create .env.local run: | cp .env.example .env.local - - name: Build the app and Docker image + - name: Build, tag, and push image to Amazon ECR + id: build-image + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ github.sha }} run: | - docker build -t shapedocs . + # Build a docker image and push it to ECR so that it can + # be deployed to ECS + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Fill in the new image ID in the Amazon ECS task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@v1.2.0 + with: + task-definition: task-definition.json + container-name: ${{ env.CONTAINER_NAME }} + image: ${{ steps.build-image.outputs.image }} + + - name: Deploy Amazon ECS task definition + uses: aws-actions/amazon-ecs-deploy-task-definition@v1.4.11 + with: + task-definition: ${{ steps.task-def.outputs.task-definition }} + service: ${{ env.ECS_SERVICE }} + cluster: ${{ env.ECS_CLUSTER }} + wait-for-service-stability: true From 979e587fc8825cc190d4763e8ed3de5b531295bd Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 16:26:50 +0100 Subject: [PATCH 08/13] Print task def --- .github/workflows/build-docker-image.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 80119694..52f2e6cc 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -44,6 +44,7 @@ jobs: - name: Fetch task definition run: | aws ecs describe-task-definition --task-definition ${{ env.ECS_TASK_DEFINITION_NAME }} --region ${{ env.AWS_REGION }} > task-definition.json + jq . task-definition.json - name: Create .env.local run: | From f661fe9878e4f5b38fa2ff5a3556ed3531b5cbd0 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 16:34:18 +0100 Subject: [PATCH 09/13] Store only task def itself in file --- .github/workflows/build-docker-image.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 52f2e6cc..d1ad96c1 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -42,8 +42,9 @@ jobs: uses: aws-actions/amazon-ecr-login@v2.0.1 - name: Fetch task definition + id: fetch-task-definition run: | - aws ecs describe-task-definition --task-definition ${{ env.ECS_TASK_DEFINITION_NAME }} --region ${{ env.AWS_REGION }} > task-definition.json + aws ecs describe-task-definition --task-definition ${{ env.ECS_TASK_DEFINITION_NAME }} --region ${{ env.AWS_REGION }} | jq .taskDefinition > task-definition.json jq . task-definition.json - name: Create .env.local From b2a3ce304f84ced97335d9559b25b089cd9fcf82 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 16:39:38 +0100 Subject: [PATCH 10/13] Make the docker container listen on port 80 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3b14c7ea..23d6c1fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,9 +56,9 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs -EXPOSE 3000 +EXPOSE 80 -ENV PORT 3000 +ENV PORT 80 # set hostname to localhost ENV HOSTNAME "0.0.0.0" From f7179efe9e104296e06e79c56110066beaa6e4a4 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 17:36:26 +0100 Subject: [PATCH 11/13] Add /api/health endpoint to be used by AWS LB --- src/app/api/health/route.ts | 5 +++++ src/middleware.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/app/api/health/route.ts diff --git a/src/app/api/health/route.ts b/src/app/api/health/route.ts new file mode 100644 index 00000000..fead38a1 --- /dev/null +++ b/src/app/api/health/route.ts @@ -0,0 +1,5 @@ +import { NextResponse } from "next/server" + +export const GET = async (): Promise => { + return NextResponse.json({ status: "Healthy" }) +} diff --git a/src/middleware.ts b/src/middleware.ts index ab6c8d87..1bd4ede1 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,7 +1,7 @@ import { withMiddlewareAuthRequired } from "@auth0/nextjs-auth0/edge" export const config = { - matcher: "/((?!api/hooks|api/auth/logout|api/auth/forceLogout|_next/static|_next/image|images|favicon.ico).*)" + matcher: "/((?!api/hooks|api/auth/logout|api/auth/forceLogout|api/health|_next/static|_next/image|images|favicon.ico).*)" } export default withMiddlewareAuthRequired() From ae5d9f37fd1731f1adf690f897353274891599fe Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Fri, 26 Jan 2024 17:50:27 +0100 Subject: [PATCH 12/13] Revert "Make the docker container listen on port 80" This reverts commit 602dcc08a2ab1e796e95dc61819a1a24e667195c. --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 23d6c1fb..3b14c7ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,9 +56,9 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs -EXPOSE 80 +EXPOSE 3000 -ENV PORT 80 +ENV PORT 3000 # set hostname to localhost ENV HOSTNAME "0.0.0.0" From dd36d708ea3684c40a9b8ac29634d7c470a875f8 Mon Sep 17 00:00:00 2001 From: Ulrik Andersen Date: Wed, 1 May 2024 19:10:13 +0200 Subject: [PATCH 13/13] Deploy specifically to staging --- .../{build-docker-image.yml => build-and-deploy-staging.yml} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename .github/workflows/{build-docker-image.yml => build-and-deploy-staging.yml} (93%) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-and-deploy-staging.yml similarity index 93% rename from .github/workflows/build-docker-image.yml rename to .github/workflows/build-and-deploy-staging.yml index d1ad96c1..8b46715d 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-and-deploy-staging.yml @@ -1,4 +1,4 @@ -name: "Build Docker image" +name: "[Staging] Build and Deploy" on: workflow_dispatch: {} @@ -60,7 +60,9 @@ jobs: # Build a docker image and push it to ECR so that it can # be deployed to ECS docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . + docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - name: Fill in the new image ID in the Amazon ECS task definition