From 7793c74d69d60be39074a2218bbe70daea57c48f Mon Sep 17 00:00:00 2001 From: McNaBry Date: Wed, 30 Oct 2024 00:34:19 +0800 Subject: [PATCH 1/8] Create github workflow to deploy frontend and backend to AWS --- .github/workflows/backend.yml | 81 ++++++++++++++++++++++++++++++++++ .github/workflows/frontend.yml | 45 +++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 .github/workflows/backend.yml create mode 100644 .github/workflows/frontend.yml diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml new file mode 100644 index 0000000000..79170c4c21 --- /dev/null +++ b/.github/workflows/backend.yml @@ -0,0 +1,81 @@ +name: Deploy Backend Services + +on: + push: + branches: [ 'main' ] + paths: [ 'services/match/**', 'services/question/**', 'services/user/**' ] + pull_request: + branches: [ 'main' ] + types: [ 'opened', 'reopened', 'synchronize'] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout + +env: + AWS_REGION: ap-southeast-1 + ECS_CLUSTER: backend-cluster + +jobs: + deploy: + name: Deploy Backend Service + runs-on: ubuntu-latest + environment: production + + strategy: + matrix: + service: [ 'match', 'question', 'user' ] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check for changes in ${{ matrix.service }} directory + uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + service: + - '.services/${{ matrix.service }}/**' + + - name: Exit if no changes found + if: steps.changes.output.service == 'false' + run: exit 0 + + - name: Configure AWS credentials + id: aws-configure + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_BACKEND_ROLE }} + role-session-name: GitHub_to_AWS_via_FederatedOIDC + aws-region: ${{ env.AWS_REGION }} + + - name: Login to AWS ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2.0.1 + + - name: Build and push ${{ matrix.service }} image to Amazon ECR + id: build-image + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: ${{ matrix.service }} + IMAGE_TAG: latest + run: | + echo "Building $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./services/${{ matrix.service }} + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + + - name: Update AWS Service (${{ matrix.service }}) # Trigger re-deployment with latest image + id: update-service + env: + ECS_SERVICE: ${{ matrix.service }}-service + run: | + echo "Updating $ECS_SERVICE for $ECS_CLUSTER" + aws ecs update-service \ + --cluster $ECS_CLUSTER \ + --service $ECS_SERVICE \ + --force-new-deployment \ + --region $AWS_REGION diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml new file mode 100644 index 0000000000..255e69ee7c --- /dev/null +++ b/.github/workflows/frontend.yml @@ -0,0 +1,45 @@ +name: Deploy Frontend + +on: + push: + branches: [ 'main' ] + paths: + # - 'frontend/**' # Only trigger if changes are made in the frontend directory + pull_request: + branches: [ 'main' ] + types: [ 'opened', 'reopened', 'synchronize'] + + workflow_dispatch: + +permissions: + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout + +env: + AWS_REGION: ap-southeast-1 + S3_BUCKET_NAME: app.peerprep.org + +jobs: + deploy: + name: Deploy Frontend + runs-on: ubuntu-latest + environment: production + + steps: + - uses: actions/checkout@v4 + + - name: Configure AWS credentials + id: aws-configure + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_FRONTEND_ROLE }} + role-session-name: GitHub_to_AWS_via_FederatedOIDC + aws-region: ${{ env.AWS_REGION }} + + - name: Build frontend distribution + working-directory: frontend + run: npm ci && npm run build + + - name: Sync distribution to S3 + run: | + aws s3 sync ./frontend/dist/frontend/browser/ s3://$S3_BUCKET_NAME --delete From 63bb304947d9319ceda3bdc3b0bcc1c053b2a72d Mon Sep 17 00:00:00 2001 From: McNaBry Date: Thu, 31 Oct 2024 10:02:36 +0800 Subject: [PATCH 2/8] Add conditional trigger for backend workflow * The build is triggered for a specific service only if its files have been changes --- .github/workflows/backend.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 79170c4c21..d09940a9ae 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -4,9 +4,6 @@ on: push: branches: [ 'main' ] paths: [ 'services/match/**', 'services/question/**', 'services/user/**' ] - pull_request: - branches: [ 'main' ] - types: [ 'opened', 'reopened', 'synchronize'] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -41,12 +38,9 @@ jobs: service: - '.services/${{ matrix.service }}/**' - - name: Exit if no changes found - if: steps.changes.output.service == 'false' - run: exit 0 - - name: Configure AWS credentials id: aws-configure + if: steps.changes.output.service == 'true' uses: aws-actions/configure-aws-credentials@v4.0.2 with: role-to-assume: ${{ secrets.AWS_BACKEND_ROLE }} @@ -55,10 +49,12 @@ jobs: - name: Login to AWS ECR id: login-ecr + if: steps.changes.output.service == 'true' uses: aws-actions/amazon-ecr-login@v2.0.1 - - name: Build and push ${{ matrix.service }} image to Amazon ECR + - name: Build and push ${{ matrix.service }} image to AWS ECR id: build-image + if: steps.changes.output.service == 'true' env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: ${{ matrix.service }} @@ -70,6 +66,7 @@ jobs: - name: Update AWS Service (${{ matrix.service }}) # Trigger re-deployment with latest image id: update-service + if: steps.changes.output.service == 'true' env: ECS_SERVICE: ${{ matrix.service }}-service run: | From 57e3e7466dc188d7a422a7f5c4cc56388916a245 Mon Sep 17 00:00:00 2001 From: McNaBry Date: Thu, 31 Oct 2024 13:51:30 +0800 Subject: [PATCH 3/8] Update frontend workflow * Remove trigger on pull request * Add conditional trigger based on frontend directory --- .github/workflows/frontend.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 255e69ee7c..2b5483ca99 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -4,10 +4,7 @@ on: push: branches: [ 'main' ] paths: - # - 'frontend/**' # Only trigger if changes are made in the frontend directory - pull_request: - branches: [ 'main' ] - types: [ 'opened', 'reopened', 'synchronize'] + - 'frontend/**' workflow_dispatch: From c0b9e6d9716210360e42e03c8fe41e792faac03d Mon Sep 17 00:00:00 2001 From: McNaBry Date: Thu, 31 Oct 2024 13:52:35 +0800 Subject: [PATCH 4/8] Add cloudfront cache invalidation to frontend workflow Co-authored-by: samuelim01 <61283948+samuelim01@users.noreply.github.com> --- .github/workflows/frontend.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 2b5483ca99..cba08c04bf 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -40,3 +40,7 @@ jobs: - name: Sync distribution to S3 run: | aws s3 sync ./frontend/dist/frontend/browser/ s3://$S3_BUCKET_NAME --delete + + - name: Invalidate Cloudfront Cache + run: | + aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_ID }} --paths "/*" From 862b5bd4949b0ce1bc38c2439aa7726653556b7e Mon Sep 17 00:00:00 2001 From: Samuel Lim Date: Sat, 2 Nov 2024 01:55:25 +0800 Subject: [PATCH 5/8] Include collab in backend workflow --- .github/workflows/backend.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index d09940a9ae..e296c5278b 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -3,7 +3,12 @@ name: Deploy Backend Services on: push: branches: [ 'main' ] - paths: [ 'services/match/**', 'services/question/**', 'services/user/**' ] + paths: [ + 'services/question/**', + 'services/user/**', + 'services/match/**', + 'services/collaboration/**', + ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -24,7 +29,7 @@ jobs: strategy: matrix: - service: [ 'match', 'question', 'user' ] + service: [ 'question', 'user', 'match', 'collaboration' ] steps: - name: Checkout From ef9d4480c393bbc33733cc1b3906612c5c4dffc1 Mon Sep 17 00:00:00 2001 From: McNaBry Date: Sun, 3 Nov 2024 23:47:44 +0800 Subject: [PATCH 6/8] Add workflow scripts that can only be triggered manually for frontend and backend --- .github/workflows/backend_force.yml | 65 ++++++++++++++++++++++++++++ .github/workflows/frontend force.yml | 44 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 .github/workflows/backend_force.yml create mode 100644 .github/workflows/frontend force.yml diff --git a/.github/workflows/backend_force.yml b/.github/workflows/backend_force.yml new file mode 100644 index 0000000000..c1b934530e --- /dev/null +++ b/.github/workflows/backend_force.yml @@ -0,0 +1,65 @@ +# Deploys all backend services regardless of file changes. +# Can only be triggered manually. + +name: Force Deploy All Backend Services + +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout + +env: + AWS_REGION: ap-southeast-1 + ECS_CLUSTER: backend-cluster + +jobs: + deploy: + name: Deploy Backend Service + runs-on: ubuntu-latest + environment: production + + strategy: + matrix: + service: [ 'question', 'user', 'match', 'collaboration' ] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Configure AWS credentials + id: aws-configure + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_BACKEND_ROLE }} + role-session-name: GitHub_to_AWS_via_FederatedOIDC + aws-region: ${{ env.AWS_REGION }} + + - name: Login to AWS ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2.0.1 + + - name: Build and push ${{ matrix.service }} image to AWS ECR + id: build-image + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: ${{ matrix.service }} + IMAGE_TAG: latest + run: | + echo "Building $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" + docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./services/${{ matrix.service }} + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + + - name: Update AWS Service (${{ matrix.service }}) # Trigger re-deployment with latest image + id: update-service + env: + ECS_SERVICE: ${{ matrix.service }}-service + run: | + echo "Updating $ECS_SERVICE for $ECS_CLUSTER" + aws ecs update-service \ + --cluster $ECS_CLUSTER \ + --service $ECS_SERVICE \ + --force-new-deployment \ + --region $AWS_REGION diff --git a/.github/workflows/frontend force.yml b/.github/workflows/frontend force.yml new file mode 100644 index 0000000000..d7bdf0b237 --- /dev/null +++ b/.github/workflows/frontend force.yml @@ -0,0 +1,44 @@ +# Deploys frontend regardless of file changes. +# Can only be triggered manually. + +name: Force Deploy Frontend + +on: + workflow_dispatch: + +permissions: + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout + +env: + AWS_REGION: ap-southeast-1 + S3_BUCKET_NAME: app.peerprep.org + +jobs: + deploy: + name: Deploy Frontend + runs-on: ubuntu-latest + environment: production + + steps: + - uses: actions/checkout@v4 + + - name: Configure AWS credentials + id: aws-configure + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_FRONTEND_ROLE }} + role-session-name: GitHub_to_AWS_via_FederatedOIDC + aws-region: ${{ env.AWS_REGION }} + + - name: Build frontend distribution + working-directory: frontend + run: npm ci && npm run build + + - name: Sync distribution to S3 + run: | + aws s3 sync ./frontend/dist/frontend/browser/ s3://$S3_BUCKET_NAME --delete + + - name: Invalidate Cloudfront Cache + run: | + aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_ID }} --paths "/*" From 25e98cf5fe721dbde93fb2eebcff6acb1b969a56 Mon Sep 17 00:00:00 2001 From: McNaBry Date: Mon, 4 Nov 2024 00:17:50 +0800 Subject: [PATCH 7/8] Rename frontend force workflow --- .github/workflows/frontend force.yml | 44 ---------------------------- 1 file changed, 44 deletions(-) delete mode 100644 .github/workflows/frontend force.yml diff --git a/.github/workflows/frontend force.yml b/.github/workflows/frontend force.yml deleted file mode 100644 index d7bdf0b237..0000000000 --- a/.github/workflows/frontend force.yml +++ /dev/null @@ -1,44 +0,0 @@ -# Deploys frontend regardless of file changes. -# Can only be triggered manually. - -name: Force Deploy Frontend - -on: - workflow_dispatch: - -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout - -env: - AWS_REGION: ap-southeast-1 - S3_BUCKET_NAME: app.peerprep.org - -jobs: - deploy: - name: Deploy Frontend - runs-on: ubuntu-latest - environment: production - - steps: - - uses: actions/checkout@v4 - - - name: Configure AWS credentials - id: aws-configure - uses: aws-actions/configure-aws-credentials@v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_FRONTEND_ROLE }} - role-session-name: GitHub_to_AWS_via_FederatedOIDC - aws-region: ${{ env.AWS_REGION }} - - - name: Build frontend distribution - working-directory: frontend - run: npm ci && npm run build - - - name: Sync distribution to S3 - run: | - aws s3 sync ./frontend/dist/frontend/browser/ s3://$S3_BUCKET_NAME --delete - - - name: Invalidate Cloudfront Cache - run: | - aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_ID }} --paths "/*" From 88af58216b45e28d149703588a4e50f4e122c4f7 Mon Sep 17 00:00:00 2001 From: McNaBry Date: Mon, 4 Nov 2024 00:26:57 +0800 Subject: [PATCH 8/8] Change frontend and backend workflows to trigger only on production branch --- .github/workflows/backend.yml | 21 +--------- .github/workflows/backend_force.yml | 65 ----------------------------- .github/workflows/frontend.yml | 4 +- 3 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/backend_force.yml diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index e296c5278b..703022bdea 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -2,15 +2,8 @@ name: Deploy Backend Services on: push: - branches: [ 'main' ] - paths: [ - 'services/question/**', - 'services/user/**', - 'services/match/**', - 'services/collaboration/**', - ] + branches: [ 'production' ] - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: permissions: @@ -35,17 +28,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Check for changes in ${{ matrix.service }} directory - uses: dorny/paths-filter@v3 - id: changes - with: - filters: | - service: - - '.services/${{ matrix.service }}/**' - - name: Configure AWS credentials id: aws-configure - if: steps.changes.output.service == 'true' uses: aws-actions/configure-aws-credentials@v4.0.2 with: role-to-assume: ${{ secrets.AWS_BACKEND_ROLE }} @@ -54,12 +38,10 @@ jobs: - name: Login to AWS ECR id: login-ecr - if: steps.changes.output.service == 'true' uses: aws-actions/amazon-ecr-login@v2.0.1 - name: Build and push ${{ matrix.service }} image to AWS ECR id: build-image - if: steps.changes.output.service == 'true' env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: ${{ matrix.service }} @@ -71,7 +53,6 @@ jobs: - name: Update AWS Service (${{ matrix.service }}) # Trigger re-deployment with latest image id: update-service - if: steps.changes.output.service == 'true' env: ECS_SERVICE: ${{ matrix.service }}-service run: | diff --git a/.github/workflows/backend_force.yml b/.github/workflows/backend_force.yml deleted file mode 100644 index c1b934530e..0000000000 --- a/.github/workflows/backend_force.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Deploys all backend services regardless of file changes. -# Can only be triggered manually. - -name: Force Deploy All Backend Services - -on: - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout - -env: - AWS_REGION: ap-southeast-1 - ECS_CLUSTER: backend-cluster - -jobs: - deploy: - name: Deploy Backend Service - runs-on: ubuntu-latest - environment: production - - strategy: - matrix: - service: [ 'question', 'user', 'match', 'collaboration' ] - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Configure AWS credentials - id: aws-configure - uses: aws-actions/configure-aws-credentials@v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_BACKEND_ROLE }} - role-session-name: GitHub_to_AWS_via_FederatedOIDC - aws-region: ${{ env.AWS_REGION }} - - - name: Login to AWS ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2.0.1 - - - name: Build and push ${{ matrix.service }} image to AWS ECR - id: build-image - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: ${{ matrix.service }} - IMAGE_TAG: latest - run: | - echo "Building $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./services/${{ matrix.service }} - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - - - name: Update AWS Service (${{ matrix.service }}) # Trigger re-deployment with latest image - id: update-service - env: - ECS_SERVICE: ${{ matrix.service }}-service - run: | - echo "Updating $ECS_SERVICE for $ECS_CLUSTER" - aws ecs update-service \ - --cluster $ECS_CLUSTER \ - --service $ECS_SERVICE \ - --force-new-deployment \ - --region $AWS_REGION diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index cba08c04bf..53adae7092 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -2,9 +2,7 @@ name: Deploy Frontend on: push: - branches: [ 'main' ] - paths: - - 'frontend/**' + branches: [ 'production' ] workflow_dispatch: