diff --git a/.github/workflows/gcp_deploy.yaml b/.github/workflows/gcp_deploy.yaml index c7a8c051b..11ad1507b 100644 --- a/.github/workflows/gcp_deploy.yaml +++ b/.github/workflows/gcp_deploy.yaml @@ -1,4 +1,4 @@ -name: Deploy to GCS +name: Deploy to GCS Stage on: push: @@ -6,25 +6,54 @@ on: - gcs-pipeline jobs: + test-website: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node js + uses: actions/setup-node@v3 + with: + node-version: "18" + - name: Install dependencies + run: yarn install --immutable + - name: Test current build + run: yarn run test-ci + continue-on-error: true + deploy-stage: runs-on: ubuntu-latest + needs: test-website + if: ${{ success() }} environment: stage steps: - name: Checkout code uses: actions/checkout@v3 + - name: Setup Node js + uses: actions/setup-node@v3 - name: Set up Google Cloud SDK uses: google-github-actions/auth@v2 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - - name: set up gcloud + - name: Set up gcloud uses: google-github-actions/setup-gcloud@v2 - - name: stage build with unpublsiehd contents + - name: Build the website run: | yarn install yarn build:production + - name: Build version.json file + run: | + if [ -e version.json ]; then + echo "version.json exists, skipping build" + else + echo "version.json does not exist, running build-version-json.sh" + bash ./.utils/build-version-json.sh + fi + - name: Deploying unpublsiehd content to stage. run: | - sh ./bin/gcs-deploy.sh ${{vars.EXTENSIONWORKSHOP_BUCKET_STAGE}} + sh ./.utils/gcs-deploy.sh ${{ vars.EXTENSIONWORKSHOP_BUCKET_STAGE }} diff --git a/.github/workflows/gcp_deploy_prod.yaml b/.github/workflows/gcp_deploy_prod.yaml index 2d10da604..c06efcd0d 100644 --- a/.github/workflows/gcp_deploy_prod.yaml +++ b/.github/workflows/gcp_deploy_prod.yaml @@ -1,4 +1,4 @@ -name: Deploy to GCS +name: Deploy to GCS Prod on: push: @@ -7,25 +7,55 @@ on: workflow_dispatch: jobs: + test-website: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node js + uses: actions/setup-node@v3 + with: + node-version: "18" + - name: Install dependencies + run: yarn install --immutable + - name: Test current build + run: yarn run test-ci + continue-on-error: true + deploy-prod: runs-on: ubuntu-latest - environment: Prod + needs: test-website + if: ${{ success() }} + + environment: prod steps: - name: Checkout code uses: actions/checkout@v3 + - name: Setup Node js + uses: actions/setup-node@v3 - name: Set up Google Cloud SDK uses: google-github-actions/auth@v2 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - - name: set up gcloud + - name: Set up gcloud uses: google-github-actions/setup-gcloud@v2 - - name: stage build with unpublsiehd contents + - name: Build the website run: | yarn install yarn build:production + - name: Build version.json file + run: | + if [ -e version.json ]; then + echo "version.json exists, skipping build" + else + echo "version.json does not exist, running build-version-json.sh" + bash ./.utils/build-version-json.sh + fi + - name: Deploying unpublsiehd content to stage. run: | - sh ./bin/gcs-deploy.sh ${{vars.EXTENSIONWORKSHOP_BUCKET_PROD}} + sh ./.utils/gcs-deploy.sh ${{ vars.EXTENSIONWORKSHOP_BUCKET_PROD }} diff --git a/.utils/gcs-deploy.sh b/.utils/gcs-deploy.sh new file mode 100644 index 000000000..7201734c4 --- /dev/null +++ b/.utils/gcs-deploy.sh @@ -0,0 +1,99 @@ +#!/bin/bash + + set -ex + EXTENSION_WORKSHOP_BUCKET_GCS=$1 + + echo $EXTENSION_WORKSHOP_BUCKET_GCS + + + # For short-lived assets; in seconds + TEN_MINS="600" + + # For long-lived assets; in seconds + ONE_YEAR="31536000" + + CSPSTATIC="x-goog-meta-content-security-policy: default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors: 'none'; object-src 'none'" + CSP="x-goog-meta-content-security-policy: default-src 'none'; img-src 'self' data:; form-action 'self' https://www.mozilla.org/en-US/newsletter/; media-src 'self' blob:; script-src 'self' https://www.youtube.com/iframe_api https://www.youtube.com/s/player/ 'sha256-vqFvYKh0rwFP9fSa0PuzUff2ElHQ+rkjGfycqUNqufQ=' https://www.googletagmanager.com/gtag/js ; font-src 'self'; frame-ancestors 'none'; frame-src https://www.youtube.com/embed/ https://calendar.google.com/calendar/appointments/; base-uri 'none'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://blog.mozilla.org/addons/feed/ https://www.mozilla.org/en-US/newsletter/ https://*.google-analytics.com;" + ACAO="x-goog-meta-access-control-allow-origin: *" + + if [ -z "$EXTENSION_WORKSHOP_BUCKET_GCS" ]; then + echo "The GCS bucket is not set. Failing." + exit 1 + fi + + if [ -e version.json ]; then + mv version.json dist/__version__ + # __version__ JSON; short cache + gsutil \ + -h "cache-control: max-age=${TEN_MINS}" \ + -h "content-type: application/json" \ + -h "$CSPSTATIC" \ + -h "$ACAO" \ + rsync \ + -J \ + -a public-read \ + dist/_version_ "gs://${EXTENSION_WORKSHOP_BUCKET_GCS}/__version__" + + fi + + + deploy_code() { + + # The basic strategy is to sync all the files that need special attention + # first, and then sync everything else which will get defaults + # + # Note that we use single quotes below for the regex pattern so that we don't + # have to deal with history expansion in shell. + + # HTML; short cache + gsutil \ + -h "cache-control: max-age=${TEN_MINS}" \ + -h "content-type: text/html" \ + -h "$CSP" \ + -h "$ACAO" \ + rsync \ + -R \ + -J \ + -a public-read \ + -x '.*(? version.json - -cat version.json diff --git a/bin/gcs-deploy.sh b/bin/gcs-deploy.sh deleted file mode 100644 index f744176f0..000000000 --- a/bin/gcs-deploy.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/bash - -set -ex - EXTENSION_WORKSHOP_BUCKET_GCS=$1 - - echo $EXTENSION_WORKSHOP_BUCKET_GCS - - CODE_DIR="dist" - # For short-lived assets; in seconds - TEN_MINS="600" - - # For long-lived assets; in seconds - ONE_YEAR="31536000" - - CSPSTATIC="x-goog-meta-content-security-policy: default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors: 'none'; object-src 'none'" - CSP="x-goog-meta-content-security-policy: default-src 'none'; img-src 'self' data:; form-action 'self' https://www.mozilla.org/en-US/newsletter/; media-src 'self' blob:; script-src 'self' https://www.youtube.com/iframe_api https://www.youtube.com/s/player/ 'sha256-vqFvYKh0rwFP9fSa0PuzUff2ElHQ+rkjGfycqUNqufQ=' https://www.googletagmanager.com/gtag/js ; font-src 'self'; frame-ancestors 'none'; frame-src https://www.youtube.com/embed/ https://calendar.google.com/calendar/appointments/; base-uri 'none'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://blog.mozilla.org/addons/feed/ https://www.mozilla.org/en-US/newsletter/ https://*.google-analytics.com;" - ACAO="x-goog-meta-access-control-allow-origin: *" - - if [ -z "$EXTENSION_WORKSHOP_BUCKET_GCS" ]; then - echo "The GCS bucket is not set. Failing." - exit 1 - fi - -[ -e version.json ] || $(dirname $0)/build-version-json.sh - - if [ -e version.json ]; then - mv version.json dist/__version__ - # __version__ JSON; short cache - gcloud storage cp dist/__version__ gs://${EXTENSION_WORKSHOP_BUCKET_GCS}/__version__ - - fi - - -deploy_code() { - - # The basic strategy is to sync all the files that need special attention - # first, and then sync everything else which will get defaults - # - # Note that we use single quotes below for the regex pattern so that we don't - # have to deal with history expansion in shell. - - # HTML; short cache - gsutil \ - -h "cache-control: max-age=${TEN_MINS}" \ - -h "content-type: text/html" \ - -h "$CSP" \ - -h "$ACAO" \ - rsync \ - -R \ - -J \ - -a public-read \ - -x '.*(?