| 1 | #!/usr/bin/env bash
 | 
| 2 | #
 | 
| 3 | # Fast forward a green branch to master.
 | 
| 4 | #
 | 
| 5 | # Usage:
 | 
| 6 | #   soil/maybe-merge.sh <function name>
 | 
| 7 | 
 | 
| 8 | set -o nounset
 | 
| 9 | set -o pipefail
 | 
| 10 | set -o errexit
 | 
| 11 | 
 | 
| 12 | source soil/common.sh
 | 
| 13 | 
 | 
| 14 | fast-forward()  {
 | 
| 15 |   # Generate a token in "Settings" -> Developer Settings
 | 
| 16 |   # https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
 | 
| 17 |   # Should be a secret in Github Actions
 | 
| 18 |   local github_token=$1
 | 
| 19 | 
 | 
| 20 |   local commit_hash=${2:-}
 | 
| 21 |   local to_branch=${3:-'master'}
 | 
| 22 | 
 | 
| 23 |   # local testing
 | 
| 24 |   if test -z "$github_token"; then
 | 
| 25 |     # set by YAML
 | 
| 26 |     github_token=${SOIL_GITHUB_API_TOKEN:-}
 | 
| 27 | 
 | 
| 28 |     # Local testing
 | 
| 29 |     if test -z "$github_token"; then
 | 
| 30 |       github_token=$(cat token.txt)
 | 
| 31 |     fi
 | 
| 32 |   fi
 | 
| 33 |   if test -z "$commit_hash"; then 
 | 
| 34 |     # $GITHUB_SHA is the commit, set by Github Actions
 | 
| 35 |     commit_hash=${GITHUB_SHA:-}
 | 
| 36 | 
 | 
| 37 |     # Local testing
 | 
| 38 |     if test -z "$commit_hash"; then 
 | 
| 39 |       commit_hash='ae02c9d6e8ba8e19399de556292a1d93faa220d3'
 | 
| 40 |     fi
 | 
| 41 |   fi
 | 
| 42 | 
 | 
| 43 |   # Adapted from
 | 
| 44 |   # https://stackoverflow.com/questions/55800253/how-can-i-do-a-fast-forward-merge-using-the-github-api
 | 
| 45 |   #
 | 
| 46 |   # https://docs.github.com/en/rest/git/refs#update-a-reference
 | 
| 47 | 
 | 
| 48 |   local response=_tmp/soil/gh-fast-forward.json
 | 
| 49 | 
 | 
| 50 |   echo
 | 
| 51 |   echo "Trying to fast-forward branch $to_branch to commit $commit_hash"
 | 
| 52 |   echo
 | 
| 53 | 
 | 
| 54 |   curl \
 | 
| 55 |     -o $response \
 | 
| 56 |     -X PATCH \
 | 
| 57 |     -H "Content-Type: application/json" \
 | 
| 58 |     -H "Accept: application/vnd.github.v3+json" \
 | 
| 59 |     -H "Authorization: token ${github_token}" \
 | 
| 60 |     https://api.github.com/repos/oilshell/oil/git/refs/heads/$to_branch \
 | 
| 61 |     -d '{"sha": "'$commit_hash'", "force": false }'
 | 
| 62 |     
 | 
| 63 |   local error
 | 
| 64 |   error=$(cat $response | jq '.message')
 | 
| 65 | 
 | 
| 66 |   local ret
 | 
| 67 |   if test "$error" = 'null'; then
 | 
| 68 |     echo "Success:"
 | 
| 69 |     ret=0
 | 
| 70 |   else
 | 
| 71 |     echo 'ERROR fast forwarding:'
 | 
| 72 |     ret=1
 | 
| 73 |   fi
 | 
| 74 | 
 | 
| 75 |   cat $response
 | 
| 76 |   return $ret
 | 
| 77 | }
 | 
| 78 | 
 | 
| 79 | test-fast-forward()  {
 | 
| 80 |   fast-forward '' '' dev-andy-3
 | 
| 81 | }
 | 
| 82 | 
 | 
| 83 | all-status-zero() {
 | 
| 84 |   ### Do all files contain status 0?
 | 
| 85 | 
 | 
| 86 |   for path in "$@"; do
 | 
| 87 |     # There may be a newline on the end, which 'read' stops at.
 | 
| 88 |     read -r status unused_job_id < $path
 | 
| 89 | 
 | 
| 90 |     if test "$status" != '0'; then
 | 
| 91 |       echo "$path = $status"
 | 
| 92 |       return 1
 | 
| 93 |     fi
 | 
| 94 |   done
 | 
| 95 | 
 | 
| 96 |   return 0
 | 
| 97 | }
 | 
| 98 | 
 | 
| 99 | soil-run() {
 | 
| 100 |   local github_token=${1:-}  # SOIL_GITHUB_API_TOKEN
 | 
| 101 |   local run_id=${2:-}  # $GITHUB_RUN_ID
 | 
| 102 |   local commit_hash=${3:-}  # GITHUB_SHA
 | 
| 103 |   local to_branch=${4:-}  # defaults to master
 | 
| 104 | 
 | 
| 105 |   if test -z "$run_id"; then
 | 
| 106 |     # GITHUB_RUN_ID is set by Github Actions
 | 
| 107 |     run_id=${GITHUB_RUN_ID:-}
 | 
| 108 | 
 | 
| 109 |     # local testing
 | 
| 110 |     if test -z "$run_id"; then
 | 
| 111 |       run_id='2526880241'
 | 
| 112 |     fi
 | 
| 113 |   fi
 | 
| 114 | 
 | 
| 115 |   local branch=$(git rev-parse --abbrev-ref HEAD)
 | 
| 116 |   echo "Should we auto-merge branch $branch to master?"
 | 
| 117 | 
 | 
| 118 |   if test "$branch" != 'soil-staging'; then
 | 
| 119 |     echo 'No, only soil-staging is merged to master'
 | 
| 120 |     return
 | 
| 121 |   fi
 | 
| 122 | 
 | 
| 123 |   local dir=_tmp/status-api
 | 
| 124 |   rm -f -v $dir/*
 | 
| 125 |   mkdir -p $dir
 | 
| 126 | 
 | 
| 127 |   # These tiny files are written by each Soil task
 | 
| 128 |   local url_base="http://$SOIL_HOST/status-api/github/$run_id"
 | 
| 129 | 
 | 
| 130 |   #local jobs='dummy pea other-tests'  # minimal set of jobs to wait for
 | 
| 131 |   local jobs=$(soil/worker.sh list-jobs)
 | 
| 132 | 
 | 
| 133 |   local -a args=()
 | 
| 134 |   for job in $jobs; do  # relies on word splitting
 | 
| 135 | 
 | 
| 136 |     # output each URL in a different file
 | 
| 137 |     args=( "${args[@]}" -o $dir/$job $url_base/$job )
 | 
| 138 |   done
 | 
| 139 | 
 | 
| 140 |   curl -v ${args[@]}
 | 
| 141 | 
 | 
| 142 |   if all-status-zero $dir/*; then
 | 
| 143 |     fast-forward "$github_token" "$commit_hash" "$to_branch"
 | 
| 144 |   fi
 | 
| 145 | }
 | 
| 146 | 
 | 
| 147 | test-soil-run() {
 | 
| 148 |   # test with non-master branch
 | 
| 149 |   # other params have testing defaults
 | 
| 150 |   soil-run '' '' '' '' dev-andy-3
 | 
| 151 | }
 | 
| 152 | 
 | 
| 153 | "$@"
 |