use aws package to upload to s3 #2074
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node | |
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions | |
name: Webapp CI | |
on: | |
push: | |
branches: [main] | |
paths-ignore: | |
- 'apps/**' | |
pull_request: | |
branches: ['**'] | |
paths-ignore: | |
- 'apps/**' | |
concurrency: | |
group: webapp-${{ github.event_name }}-${{ github.ref }} | |
env: | |
SELECTED_PERMISSION_API_TAG: latest | |
jobs: | |
build-app: | |
name: Build app | |
runs-on: ubuntu-latest | |
outputs: | |
head-commit-message: ${{ steps.get_head_commit_message.outputs.commit_message }} | |
steps: | |
- name: Print Triggering event context payload | |
env: | |
workflow_event_context: ${{ toJSON(github.event) }} | |
run: | | |
echo "$workflow_event_context" | |
echo "Workflow and code ref: ${{github.ref}}" | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Install dependencies | |
uses: ./.github/actions/install | |
- name: Build app | |
uses: ./.github/actions/build | |
# source https://github.com/orgs/community/discussions/28474 | |
- name: Print head git commit message | |
id: get_head_commit_message | |
run: echo "commit_message=$(git show -s --format=%s)" >> "$GITHUB_OUTPUT" | |
validate-code: | |
name: Validate code | |
runs-on: ubuntu-latest | |
needs: build-app | |
if: ${{ !contains(needs.build-app.outputs.head-commit-message, 'skip-tests') }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Restore dependencies from cache | |
uses: ./.github/actions/install | |
- name: Restore app from cache | |
uses: ./.github/actions/build | |
- run: npm run typecheck | |
- run: npm run verifydeps | |
- name: Run eslint on changed files | |
uses: tj-actions/eslint-changed-files@v25 | |
with: | |
escape_paths: 'false' | |
warn_ignored: 'true' | |
skip_annotations: 'true' # do not annotate code in the PR | |
extra_args: '--ignore-pattern apps,packages' | |
file_extensions: '**/*.{ts,tsx}' | |
test-matrix: | |
name: Tests | |
runs-on: ubuntu-latest | |
needs: build-app | |
if: ${{ !contains(needs.build-app.outputs.head-commit-message, 'skip-tests') }} | |
# Postgres setup copied from https://gist.github.com/2color/537f8ef13ecec80059abb007839a6878 | |
services: | |
postgres: | |
image: postgres | |
env: | |
POSTGRES_USER: postgres | |
POSTGRES_PASSWORD: postgres | |
options: >- | |
--health-cmd pg_isready | |
--health-interval 10s | |
--health-timeout 5s | |
--health-retries 5 | |
--hostname postgres | |
ports: | |
# Maps tcp port 5432 on service container to the host | |
- 5432:5432 | |
strategy: | |
max-parallel: 10 | |
fail-fast: false | |
matrix: | |
include: | |
- test_name: 'Tests for tests' | |
test_command: 'npm run test:ci -- --config="./testing/jest.config.ts"' | |
- test_name: 'Library tests #1' | |
test_command: 'npm run test:ci -- --config="./lib/jest.config.ts" --shard 1/3' | |
- test_name: 'Library tests #2' | |
test_command: 'npm run test:ci -- --config="./lib/jest.config.ts" --shard 2/3' | |
- test_name: 'Library tests #3' | |
test_command: 'npm run test:ci -- --config="./lib/jest.config.ts" --shard 3/3' | |
- test_name: 'Server integration tests #1' | |
test_command: 'npm run start:test:ci & npm run test:server:ci -- --shard 1/2' | |
- test_name: 'Server integration tests #2' | |
test_command: 'npm run start:test:ci & npm run test:server:ci -- --shard 2/2' | |
- test_name: 'Browser tests' | |
test_command: 'npm run test:browser' | |
- test_name: 'Serverless tests' | |
test_command: | | |
npm run serverless:start & | |
sleep_loop_ct=0 | |
until curl --output /dev/null --silent --head http://localhost:3020 || [[ $sleep_loop_ct > 30 ]]; do | |
echo "serverless server not up in loop $sleep_loop_ct ... sleeping" | |
sleep_loop_ct=$((sleep_loop_ct + 1)) | |
sleep 10 | |
done | |
npm run test:serverless | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Restore dependencies from cache | |
uses: ./.github/actions/install | |
- name: Setup test database | |
run: npx dotenv -e .env.test.local -- npm run prisma:reset | |
- name: Configure AWS credentials | |
uses: aws-actions/configure-aws-credentials@v4 | |
with: | |
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-region: us-east-1 | |
mask-aws-account-id: 'no' | |
- name: Login to Amazon ECR | |
id: login-ecr | |
uses: aws-actions/amazon-ecr-login@v2 | |
with: | |
mask-password: true | |
- name: Run permissions api docker image | |
id: run_permissions_api | |
run: | | |
docker inspect postgres | |
docker network ls | |
cat /etc/hosts | |
echo "network ${{ job.services.postgres.network }}" | |
docker run -d --name permissions-api \ | |
-h permissions-api \ | |
-p "3001:3001" \ | |
-e HOST=0.0.0.0 \ | |
-e PORT=3001 \ | |
-v $PWD/nodes_modules/@charmverse/core:/apps/node_modules/@charmverse/core \ | |
--network "${{ job.services.postgres.network }}" \ | |
-e DATABASE_URL=postgres://postgres:postgres@postgres:5432/charmversetest \ | |
${{ steps.login-ecr.outputs.registry }}/charmverse-permissions-api:${{ env.SELECTED_PERMISSION_API_TAG }} \ | |
node --experimental-specifier-resolution=node ./dist/main.js | |
sleep_loop_ct=0 | |
until curl localhost:3001/api/health || [[ $sleep_loop_ct > 30 ]]; do | |
docker ps | |
docker logs permissions-api | |
docker inspect permissions-api | |
echo "permission api not up in loop $sleep_loop_ct ... sleeping" | |
sleep_loop_ct=$((sleep_loop_ct + 1)) | |
sleep 10 | |
done | |
- name: Restore app from cache | |
uses: ./.github/actions/build | |
- name: Run ${{matrix.test_name}} | |
env: | |
SERVERLESS_ACCESS_KEY: ${{ secrets.SERVERLESS_ACCESS_KEY }} | |
REACT_APP_APP_ENV: 'test' | |
run: ${{matrix.test_command}} | |
e2e-test-matrix: | |
name: Tests | |
runs-on: ubuntu-latest | |
needs: build-app | |
if: ${{ !contains(needs.build-app.outputs.head-commit-message, 'skip-tests') }} | |
# Postgres setup copied from https://gist.github.com/2color/537f8ef13ecec80059abb007839a6878 | |
services: | |
postgres: | |
image: postgres | |
env: | |
POSTGRES_USER: postgres | |
POSTGRES_PASSWORD: postgres | |
options: >- | |
--health-cmd pg_isready | |
--health-interval 10s | |
--health-timeout 5s | |
--health-retries 5 | |
--hostname postgres | |
ports: | |
# Maps tcp port 5432 on service container to the host | |
- 5432:5432 | |
strategy: | |
max-parallel: 10 | |
fail-fast: false | |
matrix: | |
include: | |
- test_name: 'Browser e2e test #1' | |
test_command: 'npm run test:e2e:ci -- --shard=1/3' | |
- test_name: 'Browser e2e test #2' | |
test_command: 'npm run test:e2e:ci -- --shard=2/3' | |
- test_name: 'Browser e2e test #3' | |
test_command: 'npm run test:e2e:ci -- --shard=3/3' | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Restore dependencies from cache | |
uses: ./.github/actions/install | |
- name: Setup test database | |
run: npx dotenv -e .env.test.local -- npm run prisma:reset | |
- name: Configure AWS credentials | |
uses: aws-actions/configure-aws-credentials@v4 | |
with: | |
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-region: us-east-1 | |
mask-aws-account-id: 'no' | |
- name: Login to Amazon ECR | |
id: login-ecr | |
uses: aws-actions/amazon-ecr-login@v2 | |
with: | |
mask-password: true | |
- name: Run permissions api docker image | |
id: run_permissions_api | |
run: | | |
docker inspect postgres | |
docker network ls | |
cat /etc/hosts | |
echo "network ${{ job.services.postgres.network }}" | |
docker run -d --name permissions-api \ | |
-h permissions-api \ | |
-p "3001:3001" \ | |
-e HOST=0.0.0.0 \ | |
-e PORT=3001 \ | |
-v $PWD/nodes_modules/@charmverse/core:/apps/node_modules/@charmverse/core \ | |
--network "${{ job.services.postgres.network }}" \ | |
-e DATABASE_URL=postgres://postgres:postgres@postgres:5432/charmversetest \ | |
${{ steps.login-ecr.outputs.registry }}/charmverse-permissions-api:${{ env.SELECTED_PERMISSION_API_TAG }} \ | |
node --experimental-specifier-resolution=node ./dist/main.js | |
sleep_loop_ct=0 | |
until curl localhost:3001/api/health || [[ $sleep_loop_ct > 30 ]]; do | |
docker ps | |
docker logs permissions-api | |
docker inspect permissions-api | |
echo "permission api not up in loop $sleep_loop_ct ... sleeping" | |
sleep_loop_ct=$((sleep_loop_ct + 1)) | |
sleep 1 | |
done | |
- name: Restore app from cache | |
uses: ./.github/actions/build | |
- name: Start services | |
run: | | |
npm run start:test:ci &> connect.log & | |
sleep_loop_ct=0 | |
until curl localhost:3335/api/health || [[ $sleep_loop_ct > 30 ]]; do | |
echo "webapp not up in loop $sleep_loop_ct ... sleeping" | |
sleep_loop_ct=$((sleep_loop_ct + 1)) | |
sleep 1 | |
done | |
# this doesnt seem to be any faster than pulling from Docker registry | |
# - name: Cache Playwright Docker image | |
# uses: ScribeMD/[email protected] | |
# with: | |
# # include the version we want to cache | |
# key: docker-${{ runner.os }}-v1.42.1-jammy | |
- name: Run ${{matrix.test_name}} | |
env: | |
REACT_APP_APP_ENV: 'test' | |
# we have to run docker command ourselves to set network=host so that playwright can access the server | |
run: | | |
[[ "${{ runner.debug }}" = "1" ]] && tail -f connect.log & | |
docker run --name mcrmicrosoftcomplaywrightv1343jammy_68c205 \ | |
--workdir /github/workspace --rm \ | |
-e "REACT_APP_APP_ENV" -e CI=true \ | |
-v "/var/run/docker.sock":"/var/run/docker.sock" \ | |
-v "/home/runner/work/_temp/_github_home":"/github/home" \ | |
-v "/home/runner/work/_temp/_github_workflow":"/github/workflow" \ | |
-v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" \ | |
-v "/home/runner/work/app.charmverse.io/app.charmverse.io":"/github/workspace" \ | |
--network "host" \ | |
--ipc=host \ | |
mcr.microsoft.com/playwright:v1.47.1-jammy \ | |
${{matrix.test_command}} | |
# uses: docker://mcr.microsoft.com/playwright:v1.34.3-jammy | |
# with: | |
# args: ${{matrix.test_command}} | |
deploy-docker: | |
name: Upload Docker image and assets | |
runs-on: ubuntu-latest | |
# run whether previous jobs were successful or skipped | |
if: github.ref == 'refs/heads/main' && !(failure() || cancelled()) | |
needs: build-app | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Inject slug/short variables | |
uses: rlespinasse/[email protected] | |
- name: Install dependencies | |
uses: ./.github/actions/install | |
- name: Calculate Build ID | |
id: get_build_id | |
run: | | |
build_id=${{ hashFiles('package-lock.json', 'pages/api/**/*.[jt]s', 'lib/**/*.[jt]s') }} | |
echo "build_id=$build_id" >> $GITHUB_OUTPUT | |
- name: Build app | |
uses: ./.github/actions/build | |
with: | |
REACT_APP_APP_ENV: 'production' | |
- name: Build and Push Docker image | |
id: docker_build_push | |
uses: ./.github/actions/build_docker_image | |
env: | |
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
AWS_REGION: us-east-1 | |
with: | |
ecr_registry: charmverse-web3-workspace | |
- name: Configure AWS credentials | |
uses: aws-actions/configure-aws-credentials@v4 | |
with: | |
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-region: us-east-1 | |
- name: Upload static assets to S3 | |
run: aws s3 sync .next/static/ s3://charm.cdn/webapp-assets/_next/static/ | |
- name: Upload JS source maps to Datadog | |
env: | |
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} | |
run: | | |
npm install -g @datadog/datadog-ci | |
datadog-ci sourcemaps upload .next/static \ | |
--service=webapp \ | |
--release-version=${{ steps.get_build_id.outputs.build_id }} \ | |
--minified-path-prefix=https://cdn.charmverse.io/_next/static | |
deploy-main: | |
name: Deploy to production | |
runs-on: ubuntu-latest | |
# run whether previous jobs were successful or skipped | |
if: github.ref == 'refs/heads/main' && !(failure() || cancelled()) | |
needs: [validate-code, test-matrix, e2e-test-matrix, deploy-docker] | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 2 | |
- name: Inject slug/short variables | |
uses: rlespinasse/[email protected] | |
with: | |
short-length: 7 | |
- name: Install dependencies | |
uses: ./.github/actions/install | |
- name: Calculate Build ID and add to env file | |
id: get_build_id | |
run: | | |
build_id=${{ hashFiles('package-lock.json', 'pages/api/**/*.[jt]s', 'lib/**/*.[jt]s') }} | |
echo "REACT_APP_BUILD_ID=$build_id" >> ./.ebstalk.apps.env/webapp.env | |
- name: Set the docker compose env variables | |
uses: mikefarah/yq@master | |
with: | |
cmd: | | |
yq -I 4 -i ' | |
with(.option_settings."aws:elasticbeanstalk:application:environment"; | |
.NODE_ENV = "production" | | |
.IMGTAG = "${{ github.run_id }}-${{ env.GITHUB_SHA_SHORT }}") | |
' .ebextensions/webapp/00_env_vars.config | |
yq -I 4 -i ' | |
with(.option_settings."aws:elasticbeanstalk:application:environment"; | |
.IMGTAG = "${{ github.run_id }}-${{ env.GITHUB_SHA_SHORT }}") | |
' .ebextensions/websockets/00_env_vars.config | |
- name: Package webapp | |
run: | | |
mv .ebextensions .ebextensions_tmp | |
mv .ebextensions_tmp/webapp .ebextensions | |
cat files_to_zip.txt | zip --symlinks -r@ deploy.zip | |
- name: Deploy webapp to Beanstalk | |
id: webapp_deploy | |
uses: einaregilsson/beanstalk-deploy@v21 | |
with: | |
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
application_name: web3-workspace | |
environment_name: prd-charmverse-webapp | |
version_label: ${{ github.sha }} | |
region: us-east-1 | |
deployment_package: deploy.zip | |
use_existing_version_if_available: true # allows triggering re-deploys with same version | |
wait_for_deployment: false # set to false to save sweet Github minutes | |
- name: Deploy websockets to Beanstalk | |
if: steps.pkg_websocket.outputs.deploy_websocket == 'true' | |
uses: einaregilsson/beanstalk-deploy@v21 | |
with: | |
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
application_name: prd-charmverse-websockets | |
environment_name: prd-charmverse-websockets | |
version_label: ${{ github.sha }} | |
region: us-east-1 | |
deployment_package: deploy_websockets.zip | |
use_existing_version_if_available: true # allows triggering re-deploys with same version | |
wait_for_deployment: false # set to false to save sweet Github | |
discord-alert: | |
name: Notify Discord of failure | |
runs-on: ubuntu-latest | |
if: github.ref == 'refs/heads/main' && failure() | |
# pass in all steps so we can check if any failed | |
needs: [build-app, validate-code, test-matrix, e2e-test-matrix, deploy-docker, deploy-main] | |
steps: | |
- name: If any of prev jobs failed notify discord | |
if: contains(needs.*.result, 'failure') | |
uses: sarisia/actions-status-discord@v1 | |
with: | |
webhook: ${{ secrets.DISCORD_WARNINGS_WEBHOOK }} | |
status: 'failure' | |
content: 'Hey <@&1027309276454207519>' | |
title: 'Webapp deploy workflow failed' | |
description: | | |
Failed workflow URL: https://github.com/charmverse/app.charmverse.io/actions/runs/${{ github.run_id }} | |
color: '16515843' | |
url: 'https://github.com/charmverse/app.charmverse.io/actions/runs/${{ github.run_id }}' | |
username: GitHub Actions | |
avatar_url: 'https://github.githubassets.com/images/modules/logos_page/Octocat.png' |