diff --git a/.github/mergify.yml b/.github/mergify.yml index abb7e6dda8..513294bcdb 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -11,7 +11,7 @@ pull_request_rules: - check-success~=CodeQL # CodeQL code scanning results - check-success~=GitGuardian - check-success~=Semantic Pull Request - - check-success~=Travis CI - Branch + - check-success~=build_deploy_application - check-success~=coverage/coveralls - check-success~=license/snyk - check-success~=security/snyk @@ -32,7 +32,7 @@ pull_request_rules: - check-success~=CodeQL # CodeQL code scanning results - check-success~=GitGuardian - check-success~=Semantic Pull Request - - check-success~=Travis CI - Branch + - check-success~=build_deploy_application - check-success~=coverage/coveralls - check-success~=license/snyk - check-success~=security/snyk diff --git a/.github/workflows/deploy-eb.yml b/.github/workflows/deploy-eb.yml new file mode 100644 index 0000000000..d27e932649 --- /dev/null +++ b/.github/workflows/deploy-eb.yml @@ -0,0 +1,88 @@ +name: Deploy to AWS Elastic Beanstalk +on: + push: + branches: # There should be 4 environments in github actions secrets: release, staging, staging-alt, uat. This is different from the DEPLOY_ENV secret which corresponds to elastic beanstalk environment name + - release + - staging + - staging-alt + - uat + +jobs: + set_environment: + outputs: + current_env: ${{ steps.set-environment.outputs.current_env }} + runs-on: ubuntu-latest + steps: + - id: set-environment + run: echo "::set-output name=current_env::${{github.ref_name}}" + + build_deploy_application: + needs: set_environment + environment: + name: ${{ needs.set_environment.outputs.current_env }} + env: + IMAGE_TAG: github-actions-${{ github.sha }}-${{ github.run_id }}-${{github.run_attempt}} + BRANCH: ${{ needs.set_environment.outputs.current_env }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'npm' + - name: Build + env: + NODE_OPTIONS: '--max-old-space-size=4096' + run: | + npm ci + set -e + npm_config_mode=yes npx lockfile-lint --type npm --path package.json --validate-https --allowed-hosts npm + npm run lint-ci + npm run build + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_DEFAULT_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build, tag, and push image to Amazon ECR + env: + ECR_REPOSITORY: ${{ secrets.ECR_REPO }} + run: | + docker build -f Dockerfile.production -t $ECR_REPOSITORY:$IMAGE_TAG . + docker tag $ECR_REPOSITORY:$IMAGE_TAG $ECR_REPOSITORY:$BRANCH + docker push -a $ECR_REPOSITORY + sed -i -e "s/@TAG/$IMAGE_TAG/g" Dockerrun.aws.json + zip -r "$IMAGE_TAG.zip" .ebextensions Dockerrun.aws.json + + - name: Copy to S3 + env: + BUCKET_NAME: ${{ secrets.BUCKET_NAME }} + run: | + aws s3 cp $IMAGE_TAG.zip s3://$BUCKET_NAME/$IMAGE_TAG.zip + + - name: Create application version + env: + BUCKET_NAME: ${{ secrets.BUCKET_NAME }} + APP_NAME: ${{ secrets.APP_NAME }} + run: | + aws elasticbeanstalk create-application-version --application-name $APP_NAME \ + --version-label $IMAGE_TAG \ + --source-bundle S3Bucket=$BUCKET_NAME,S3Key=$IMAGE_TAG.zip \ + --description "${{ github.event.head_commit.message }}" + + - name: Update EB environment + id: update-eb-1 + env: + APP_NAME: ${{ secrets.APP_NAME }} + DEPLOY_ENV: ${{ secrets.DEPLOY_ENV }} + run: | + aws elasticbeanstalk update-environment --application-name $APP_NAME \ + --environment-name $DEPLOY_ENV \ + --version-label $IMAGE_TAG diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c9579ca61b..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,123 +0,0 @@ -os: linux -dist: xenial - -services: - - xvfb - -language: node_js -node_js: '14' -install: true # skip installation, perform in build stage. - -notifications: - email: - recipients: - # Please change to your own email recipient if you are forking this - # repository. - - formsg@data.gov.sg - on_success: always - on_failure: always - -jobs: - include: - - stage: Build application - install: npm ci - cache: - - npm - - pip - before_script: - - export NODE_OPTIONS=--max-old-space-size=4096 - script: - - set -e - - npm_config_mode=yes npx lockfile-lint --type npm --path package.json --validate-https --allowed-hosts npm - - npm run lint-ci - - npm run build - workspaces: - create: - name: build - paths: . - - stage: Deploy - services: - - docker - workspaces: - use: build - script: skip - before_deploy: - # Workaround to run before_deploy only once - - > - if ! [ "$TAG" ]; then - pip install --user awscli - # Put AWS in path - export PATH=$PATH:$HOME/.local/bin - # Login to AWS ECR, credentials defined in $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY - $(aws ecr get-login --no-include-email --region ap-southeast-1) - export TAG=travis-$TRAVIS_COMMIT-$TRAVIS_BUILD_NUMBER - docker build -f Dockerfile.production -t $REPO:$TAG . - docker tag $REPO:$TAG $REPO:$TRAVIS_BRANCH - docker push $REPO - # Add TAG to Dockerrun - sed -i -e "s/@TAG/$TAG/g" Dockerrun.aws.json - zip -r "$TAG.zip" .ebextensions Dockerrun.aws.json - fi - - export ELASTIC_BEANSTALK_LABEL="$TAG-$(env TZ=Asia/Singapore date "+%Y%m%d%H%M%S")" - deploy: - - provider: elasticbeanstalk - skip_cleanup: true - access_key_id: $AWS_ACCESS_KEY_ID - secret_access_key: $AWS_SECRET_ACCESS_KEY - region: $AWS_REGION - app: $STAGING_APP_NAME - env: $UAT_DEPLOY_ENV - bucket: $STAGING_BUCKET_NAME - zip_file: '$TAG.zip' - on: - branch: $UAT_BRANCH - - - provider: elasticbeanstalk - skip_cleanup: true - access_key_id: $AWS_ACCESS_KEY_ID - secret_access_key: $AWS_SECRET_ACCESS_KEY - region: $AWS_REGION - app: $STAGING_APP_NAME - env: $STAGING_DEPLOY_ENV - bucket: $STAGING_BUCKET_NAME - zip_file: '$TAG.zip' - on: - branch: $STAGING_BRANCH - - - provider: elasticbeanstalk - skip_cleanup: true - access_key_id: $AWS_ACCESS_KEY_ID - secret_access_key: $AWS_SECRET_ACCESS_KEY - region: $AWS_REGION - app: $STAGING_APP_NAME - env: $STAGING_ALT_DEPLOY_ENV - bucket: $STAGING_BUCKET_NAME - zip_file: '$TAG.zip' - on: - branch: $STAGING_ALT_BRANCH - - - provider: elasticbeanstalk - skip_cleanup: true - access_key_id: $AWS_ACCESS_KEY_ID - secret_access_key: $AWS_SECRET_ACCESS_KEY - region: $AWS_REGION - app: $PROD_APP_NAME - env: $PROD_DEPLOY_ENV - bucket: $PROD_BUCKET_NAME - zip_file: '$TAG.zip' - on: - branch: $PROD_BRANCH - - after_deploy: - - > - if [[ "$SENTRY_PROJECT" && "$SENTRY_AUTH_TOKEN" && "$SENTRY_ORG" && "$SENTRY_URL" ]]; then - curl -sL https://sentry.io/get-cli/ | bash - sentry-cli releases --org $SENTRY_ORG --project $SENTRY_PROJECT new "$TAG" - sentry-cli releases files "$TAG" upload-sourcemaps ./ --rewrite --ignore-file .sentryignore - sentry-cli releases finalize "$TAG" - fi - -stages: - - Build application - - Tests - - Deploy diff --git a/README.md b/README.md index b277650829..bd5efb8e73 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # FormSG -[![Build Status](https://travis-ci.com/opengovsg/formsg.svg?branch=release)](https://travis-ci.com/opengovsg/formsg) +[![Build Status](https://github.com/opengovsg/FormSG/actions/workflows/deploy-eb.yml)](https://github.com/opengovsg/FormSG/actions/workflows/deploy-eb.yml) [![Coverage Status](https://coveralls.io/repos/github/opengovsg/FormSG/badge.svg?branch=develop)](https://coveralls.io/github/opengovsg/FormSG?branch=develop) ## Table of Contents diff --git a/docs/DEPLOYMENT_SETUP.md b/docs/DEPLOYMENT_SETUP.md index d9bee23381..71088f256c 100644 --- a/docs/DEPLOYMENT_SETUP.md +++ b/docs/DEPLOYMENT_SETUP.md @@ -23,7 +23,7 @@ Infrastructure DevOps -- TravisCI for running tests and builds +- Github Actions for running tests and builds - AWS Elastic Container Registry to host built Docker images Network @@ -76,32 +76,22 @@ Secondly, edit the form document belonging to that specific form adminstrator by If no `msgSrvcName` is found in the form document, SMSes associated with that form will be sent out using and charged to the default Twilio API credentials. -### Travis CI/CD environment variables +### Github Actions Secrets -For more information about the various environment variables, please refer to -[Travis documentation](https://docs.travis-ci.com/user/deployment/elasticbeanstalk/). - -The following env variables are set in Travis: -| Variable | Description| +The following repository secrets are set in Github Actions: +| Secret | Description| |:---------|------------| -|`REPO`|The repository of the AWS Elastic Container Registry| -|`STAGING_BRANCH`|Name of staging branch, usually `master`.| -|`STAGING_ALT_BRANCH`|Name of staging-alt (if any) branch, usually `release`. An alternate staging branch is used to host diverging feature sets, useful for A/B testing.| -|`PROD_BRANCH`|Name of production branch, usually `release`.| |`AWS_ACCESS_KEY_ID`|AWS IAM access key ID used to deploy.| |`AWS_SECRET_ACCESS_KEY`|AWS IAM access secret used to deploy.| -|`AWS_REGION`|AWS region to use.| -|`PROD_APP_NAME`|The names of the deployed docker application for the production application on AWS as determined by `PROD_BRANCH`.| -|`STAGING_APP_NAME`|The names of the deployed docker application for the staging application on AWS as determined by `STAGING_BRANCH`.| -|`PROD_BUCKET_NAME`|Bucket name to upload the code of the production app to. Elastic Beanstalk will create and deploy an application version from the source bundle in this Amazon S3 bucket.| -|`STAGING_BUCKET_NAME`|Bucket name to upload the code of the staging app to. Elastic Beanstalk will create and deploy an application version from the source bundle in this Amazon S3 bucket.| -|`PROD_DEPLOY_ENV`|The name of the Elastic Beanstalk environment the production application will be deployed to.| -|`STAGING_DEPLOY_ENV`|The name of the Elastic Beanstalk environment the staging application will be deployed to.| -|`STAGING_ALT_DEPLOY_ENV`|The name of the Elastic Beanstalk environment the staging-alt application will be deployed to.| -|`SENTRY_ORG`|Organisation that source-maps should be linked to on sentry dashboard.| -|`SENTRY_AUTH_TOKEN`|Authentication token used by sentry cli to authenticate with sentry service.| -|`SENTRY_PROJECT`|Project that source-maps should be linked to on sentry dashboard.| -|`SENTRY_URL`|Sentry service that source-maps should be pushed to.| +|`AWS_DEFAULT_REGION`|AWS region to use.| +|`ECR_REPO`|ECR Repository which stores the docker images.| +|`BUCKET_NAME`| S3 Bucket used to store zipped `Dockerrun.aws.json`.| + +There are also environment secrets for each environment (`staging`, `staging-alt`, `release`, `uat`): +| Secret | Description| +|:---------|------------| +|`APP_NAME`|Application name for the environment.| +|`DEPLOY_ENV`|Deployment environment on elastic beanstalk.| ## Environment Variables