github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/util/deploy-production.sh (about) 1 #!/bin/bash 2 3 # Helper script for deploying to production. 4 # Needs the following packages to be installed: google-cloud-cli, gh, jq 5 6 #set -x #echo on for debugging purposes 7 set -e 8 9 usage() { 10 USAGE="Usage: deploy-production.sh [-f] [-b] 11 -b : skip GitHub issue creation 12 -f : Always deploy (even if checks have failed)" 13 echo "${USAGE}" 14 } 15 16 # Deletes the service passed as a parameter. 17 delete_oldest_version() { 18 OLDEST_REV=$(gcloud app --project=wptdashboard versions list --sort-by=last_deployed_time --filter="service=$1" --limit=1 --format=json | jq -r '.[] | .id') 19 echo "Deleting $1 service version $OLDEST_REV" 20 if confirm "Delete $1 service version $OLDEST_REV?"; then 21 gcloud app versions delete --service=$SERVICE $OLDEST_REV 22 else 23 echo "Skipping $1 service version $OLDEST_REV" 24 fi 25 } 26 27 while getopts ':bfh' flag; do 28 case "${flag}" in 29 b) SKIP_ISSUE_CREATION='true' ;; 30 f) FORCE_DEPLOY='true' ;; 31 h|*) usage && exit 0;; 32 esac 33 done 34 35 GH_OWNER="web-platform-tests" 36 GH_REPO="wpt.fyi" 37 PROD_LABEL="prod" 38 RELEASE_LABEL="release" 39 UTIL_DIR=$(dirname $0) 40 source "${UTIL_DIR}/logging.sh" 41 source "${UTIL_DIR}/commands.sh" 42 43 if [[ ${SKIP_ISSUE_CREATION} != "true" ]]; 44 then 45 # Find changes to deploy. 46 LAST_DEPLOYED_SHA=$(gcloud app --project=wptdashboard versions list --hide-no-traffic --filter='service=default' --format=yaml | grep id | head -1 | cut -d' ' -f2 | sed 's/rev-//') 47 CHANGELIST=$(git log $LAST_DEPLOYED_SHA..HEAD --oneline) 48 if [[ "${CHANGELIST}" == "" ]]; 49 then 50 echo "No new changes to deploy." 51 exit 0 52 fi 53 CHANGE_COUNT=$(echo "$CHANGELIST"|wc -l) 54 echo -e "There are $CHANGE_COUNT changes to deploy:\n$CHANGELIST" 55 56 # Verfiy that all commit checks passed. 57 FAILED_CHECKS=$(gh api /repos/"$GH_OWNER"/"$GH_REPO"/commits/HEAD/check-runs | jq -r '.check_runs | map(select(.conclusion == "failure"))') 58 FAILURES=$(echo "$FAILED_CHECKS" | jq -r 'length') 59 if [[ "${FAILURES}" != "0" ]]; 60 then 61 echo -e "\n$FAILURES checks failed for the latest commit:" 62 echo "$FAILED_CHECKS" | jq -r '.[] | .name + ": " + .html_url' 63 if [[ "${FORCE_DEPLOY}" != "true" ]]; 64 then 65 echo -e "\nVisit the link(s) above and if failed checks should not block deployment, run the script again with -f" 66 exit 1 67 fi 68 fi 69 70 # File a deployment bug. 71 NEW_SHA=$(git rev-parse --short HEAD) 72 LAST_DEPLOYMENT_ISSUE=$(gh issue list --state closed --label "$PROD_LABEL" --label "$RELEASE_LABEL" --limit 1 --json number --jq '.[] | .number') 73 BUG_TITLE="Deploy $NEW_SHA to production" 74 BUG_BODY=$(cat << EOF 75 Previous deployment was #$LAST_DEPLOYMENT_ISSUE ($LAST_DEPLOYED_SHA) 76 77 Changelist $LAST_DEPLOYED_SHA...$NEW_SHA 78 79 Changes: 80 $CHANGELIST 81 82 This push is happening as part of the regular weekly push. 83 84 Pushing all three services - webapp, processor, and searchcache. 85 EOF 86 ) 87 88 gh issue create --title "$BUG_TITLE" --body "$BUG_BODY" --label "$PROD_LABEL" --label "$RELEASE_LABEL" 89 if [[ $? != 0 ]]; 90 then 91 echo "GitHub issue creation failed" 92 exit 2 93 fi 94 fi 95 96 # Confirm there are 3 versions for each service and delete the oldest version. 97 SERVICES="default processor searchcache" 98 for SERVICE in $SERVICES 99 do 100 VERSIONS=$(gcloud app --project=wptdashboard versions list --filter="service=$SERVICE" --format=list | wc -l) 101 if [[ "${VERSIONS}" -eq "3" ]]; 102 then 103 echo "Found 3 versions for service $SERVICE, will delete the oldest" 104 delete_oldest_version $SERVICE 105 elif [[ "${VERSIONS}" -lt "3" ]]; 106 then 107 echo -e "\n$VERSIONS versions found for service $SERVICE" 108 else 109 echo -e "\n$VERSIONS versions found for service $SERVICE!" 110 exit 3 111 fi 112 done 113 114 # Start a docker instance. 115 ${UTIL_DIR}/docker-dev/run.sh -d 116 # Login to gcloud if not already logged in. 117 wptd_exec_it gcloud auth login 118 # Deploy the services. 119 wptd_exec_it make deploy_production PROJECT=wptdashboard APP_PATH=webapp/web 120 wptd_exec_it make deploy_production PROJECT=wptdashboard APP_PATH=results-processor 121 wptd_exec_it make deploy_production PROJECT=wptdashboard APP_PATH=api/query/cache/service 122 cd webapp/web 123 gcloud app deploy --project=wptdashboard index.yaml queue.yaml dispatch.yaml 124 cd ../.. 125 126 # Stop docker. 127 ${UTIL_DIR}/docker-dev/run.sh -s 128 129 # Confirm that everything works as expected and redirect traffic. 130 VERSION_URL=$(gcloud app --project=wptdashboard versions list --sort-by=~last_deployed_time --filter='service=default' --limit=1 --format=json | jq -r '.[] | .version.versionUrl') 131 LATEST_VERSION=$(gcloud app --project=wptdashboard versions list --sort-by=~last_deployed_time --filter='service=default' --limit=1 --format=json | jq -r '.[] | .id') 132 MESSAGE="Visit $VERSION_URL to confirm that everything works (page load, search, test expansion, show history). Redirect traffic now?" 133 if confirm "$MESSAGE"; then 134 for SERVICE in $SERVICES 135 do 136 gcloud app services set-traffic $SERVICE --splits $LATEST_VERSION=1 137 done 138 else 139 echo "Don't forget to migrate traffic to the new version." 140 fi 141 142 # Update and close deployment bug. 143 LAST_DEPLOYMENT_ISSUE=$(gh issue list --state open --label "$PROD_LABEL" --label "$RELEASE_LABEL" --limit 1 --json number --jq '.[] | .number') 144 gh issue close "$LAST_DEPLOYMENT_ISSUE" -c "Deployment is now complete."