xref: /aosp_15_r20/developers/build/github.sh (revision d353a188ca6ec4b5eba25b5fbd7bcb8ce61322fb)
1*d353a188SXin Li#!/usr/bin/env bash
2*d353a188SXin Li
3*d353a188SXin Li##############################################################################
4*d353a188SXin Li##
5*d353a188SXin Li##  GitHub Upload+Update Script (V2, combined) for DevPlat Samples
6*d353a188SXin Li##
7*d353a188SXin Li##############################################################################
8*d353a188SXin Li
9*d353a188SXin Liupdate=true
10*d353a188SXin Liupload=true
11*d353a188SXin LideleteTemp=true
12*d353a188SXin LiuseAllSamples=true
13*d353a188SXin LiallSamples=()
14*d353a188SXin Litoken=
15*d353a188SXin Li
16*d353a188SXin Li## Generates a random 32 character alphaneumeric string to use as a post script
17*d353a188SXin Li##   for the temporary code folder (folder will be deleted at end)
18*d353a188SXin LifolderPS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
19*d353a188SXin Li
20*d353a188SXin Li#utility function to print to stderr
21*d353a188SXin Liechoerr() { echo "$@" 1>&2; }
22*d353a188SXin Li
23*d353a188SXin Lidisplay_usage() {
24*d353a188SXin Liecho -e "\e[90mUsage:
25*d353a188SXin Li
26*d353a188SXin Li      -t | --token [github_auth_token]
27*d353a188SXin Li         Input an auth token to access the googlesamples GitHub org
28*d353a188SXin Li         (if this is not present, you will be prompted for one later)
29*d353a188SXin Li
30*d353a188SXin Li      -s | --samples [sample1 sample2 sample3 ... sampleN]
31*d353a188SXin Li         If you don't want to check the entire samples folder,
32*d353a188SXin Li         you can specify which samples to use with this option.
33*d353a188SXin Li
34*d353a188SXin Li      --upload-only
35*d353a188SXin Li          Only uploads new samples - samples with existing
36*d353a188SXin Li          repos will be ignored
37*d353a188SXin Li
38*d353a188SXin Li      --update-only
39*d353a188SXin Li          Only updates samples with existing repos - new
40*d353a188SXin Li          samples will be ignored
41*d353a188SXin Li
42*d353a188SXin Li      --keep-temp-files
43*d353a188SXin Li          Will not delete the temporary directory used to pull/push
44*d353a188SXin Li          to Github. (normally deleted upon exit) Preserves logs.
45*d353a188SXin Li
46*d353a188SXin Li  This script can be run with no options - it will check the entire
47*d353a188SXin Li  ./prebuilts/gradle folder and prompt for an auth token when needed.\e[0m\n"
48*d353a188SXin Li}
49*d353a188SXin Li
50*d353a188SXin Li##############################################################################
51*d353a188SXin Li##  Make sure we delete the temporary folder (if it gets created) before exiting
52*d353a188SXin Lifinish() {
53*d353a188SXin Li  if $deleteTemp; then
54*d353a188SXin Li    if [ -d "../github-temp$folderPS" ]; then
55*d353a188SXin Li     cd ..
56*d353a188SXin Li     rm -rf ./github-temp$folderPS
57*d353a188SXin Li    elif [ -d "github-temp$folderPS" ]; then
58*d353a188SXin Li     rm -rf ./github-temp$folderPS
59*d353a188SXin Li    fi
60*d353a188SXin Li  fi
61*d353a188SXin Li}
62*d353a188SXin Li# this ensures finish() will always be called no matter how the script ends
63*d353a188SXin Litrap finish EXIT
64*d353a188SXin Li
65*d353a188SXin Li
66*d353a188SXin Li##############################################################################
67*d353a188SXin Li##  Process input parameters. (see above for usage)
68*d353a188SXin Li
69*d353a188SXin Li## How this works:
70*d353a188SXin Li##  $# is the number of parameters passed in
71*d353a188SXin Li##  $1 is the first parameter, $2 the second, and so on. (space delimited)
72*d353a188SXin Li##  shift basically left shifts the params array - $1 goes away, $2 becomes $1, etc
73*d353a188SXin Li##  Thus, this while loop iterates through all command line parameters
74*d353a188SXin Liwhile [[ $# > 0 ]]; do
75*d353a188SXin Licase "$1" in
76*d353a188SXin Li
77*d353a188SXin Li  -t|--token)
78*d353a188SXin Li    if [[ $2 != -* ]] && [[ $2 ]]; then
79*d353a188SXin Li      token="$2"; shift
80*d353a188SXin Li    else
81*d353a188SXin Li      echoerr -e "Option $1 requires an argument. Cancelling script.\nUse --help to display usage."
82*d353a188SXin Li      exit 1
83*d353a188SXin Li    fi;;
84*d353a188SXin Li
85*d353a188SXin Li  --update-only) upload=false;;
86*d353a188SXin Li
87*d353a188SXin Li  --upload-only) update=false;;
88*d353a188SXin Li
89*d353a188SXin Li  --keep-temp-files) deleteTemp=false;;
90*d353a188SXin Li
91*d353a188SXin Li  -s|--samples)
92*d353a188SXin Li    useAllSamples=false
93*d353a188SXin Li    while [[ $2 != -* ]] && [[ $2 ]]; do
94*d353a188SXin Li      #if true; then ##for testing
95*d353a188SXin Li      if [ -d "./prebuilts/gradle/$2" ]; then
96*d353a188SXin Li        allSamples+=("$2")
97*d353a188SXin Li        shift
98*d353a188SXin Li      else
99*d353a188SXin Li        echoerr -e "Sample \"$2\" does not exist in ./prebuilts/gradle. Cancelling script.\n"
100*d353a188SXin Li        exit 1
101*d353a188SXin Li      fi
102*d353a188SXin Li    done;;
103*d353a188SXin Li
104*d353a188SXin Li  -h|--help)
105*d353a188SXin Li      display_usage
106*d353a188SXin Li      exit 1;;
107*d353a188SXin Li
108*d353a188SXin Li  *)
109*d353a188SXin Li    echoerr -e "Unknown Option: $1\nUse --help to display usage."
110*d353a188SXin Li    exit 1;;
111*d353a188SXin Li
112*d353a188SXin Liesac
113*d353a188SXin Lishift
114*d353a188SXin Lidone #ends options while loop
115*d353a188SXin Li
116*d353a188SXin Liif ! $upload && ! $update; then
117*d353a188SXin Li  echoerr -e "Do not use both --update-only and --upload-only, no samples will be processed.
118*d353a188SXin Li  If you want to do both updates and uploads, no flags are needed.
119*d353a188SXin Li  Use --help to display usage."
120*d353a188SXin Li  exit 1
121*d353a188SXin Lifi
122*d353a188SXin Li
123*d353a188SXin Li##############################################################################
124*d353a188SXin Li##  Get all folders in prebuilts and stick 'em in an array
125*d353a188SXin Li
126*d353a188SXin Liif $useAllSamples; then
127*d353a188SXin Li  allSamples=($(ls ./prebuilts/gradle))
128*d353a188SXin Lifi
129*d353a188SXin Li
130*d353a188SXin Li# [@] returns all items in an array, ${#...} counts them
131*d353a188SXin LinumSamples=${#allSamples[@]}
132*d353a188SXin Liecho "Running script for $numSamples samples"
133*d353a188SXin Li
134*d353a188SXin Li##############################################################################
135*d353a188SXin Li##  Iterate through all the samples and see if there's
136*d353a188SXin Li##  a repo for them on GitHub already - save results so we only do it once
137*d353a188SXin Li
138*d353a188SXin LitoUpdate=()
139*d353a188SXin LitoUpload=()
140*d353a188SXin LiproblemSamples=()
141*d353a188SXin LicurSample=0
142*d353a188SXin Li
143*d353a188SXin Liecho -ne "Checking for existence of repos... ($curSample/$numSamples)\r"
144*d353a188SXin Lifor i in ${allSamples[@]};
145*d353a188SXin Lido
146*d353a188SXin Li #echo "$i"
147*d353a188SXin Li URL=https://github.com/googlesamples/android-$i
148*d353a188SXin Li result=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "$URL")
149*d353a188SXin Li #echo "$result $URL"
150*d353a188SXin Li if [ "$result" -eq "404" ]; then
151*d353a188SXin Li   toUpload+=("$i")
152*d353a188SXin Li elif [ "$result" -eq "200" ]; then
153*d353a188SXin Li   toUpdate+=("$i")
154*d353a188SXin Li else
155*d353a188SXin Li   problemSamples+=("$i")
156*d353a188SXin Li fi
157*d353a188SXin Li curSample=$(($curSample+1))
158*d353a188SXin Li echo -ne "Checking for existence of repos... ($curSample/$numSamples)\r"
159*d353a188SXin Lidone #close for loop for existence check
160*d353a188SXin Liecho ""
161*d353a188SXin Li
162*d353a188SXin Li
163*d353a188SXin Li##############################################################################
164*d353a188SXin Li##  For every sample that has a repo already, clone it and diff it against
165*d353a188SXin Li##  the sample code in our git to see if it needs updating.
166*d353a188SXin Li
167*d353a188SXin Liif $update; then
168*d353a188SXin Li
169*d353a188SXin LineedsUpdate=()
170*d353a188SXin LicurSample=0
171*d353a188SXin LinumUpdates=${#toUpdate[@]}
172*d353a188SXin Li
173*d353a188SXin Li##make temporary dir to pull code into - will be deleted upon exit.
174*d353a188SXin Limkdir github-temp$folderPS
175*d353a188SXin Licd github-temp$folderPS
176*d353a188SXin Li
177*d353a188SXin Liecho -ne "Checking for out-of-date repos... ($curSample/$numUpdates)\r"
178*d353a188SXin Lifor i in ${toUpdate[@]};
179*d353a188SXin Lido
180*d353a188SXin Li URL=https://github.com/googlesamples/android-$i
181*d353a188SXin Li git clone $URL.git &> /dev/null
182*d353a188SXin Li if [ -d "android-$i" ]; then
183*d353a188SXin Li   diffResult=$(diff -r --exclude '*.git' ../prebuilts/gradle/$i/ ./android-$i/)
184*d353a188SXin Li   #for testing (will show diff in every repo)
185*d353a188SXin Li   #diffResult=$(diff -r ../prebuilts/gradle/$i/ ./android-$i/)`
186*d353a188SXin Li   #echo $diffResult
187*d353a188SXin Li   if [ -n "$diffResult" ]; then
188*d353a188SXin Li     needsUpdate+=("$i")
189*d353a188SXin Li   fi
190*d353a188SXin Li else
191*d353a188SXin Li   echoerr "Something went wrong when cloning $i - result directory does not exist.
192*d353a188SXin Li   Leaving temp files in place for further examination."
193*d353a188SXin Li   deleteTemp=false;
194*d353a188SXin Li fi
195*d353a188SXin Li curSample=$(($curSample+1))
196*d353a188SXin Li echo -ne "Checking for out-of-date repos... ($curSample/$numUpdates)\r"
197*d353a188SXin Lidone #end of for loop when checking which repos actually need updating
198*d353a188SXin Liecho ""
199*d353a188SXin Lifi
200*d353a188SXin Li
201*d353a188SXin Liecho ""
202*d353a188SXin Li
203*d353a188SXin Li##############################################################################
204*d353a188SXin Li##  Display the detected changes to be made and get user confirmation
205*d353a188SXin Li
206*d353a188SXin Liif $upload; then
207*d353a188SXin Li  if [ ${#toUpload[@]} -ne 0 ]; then
208*d353a188SXin Li    echo -e "\n\e[1mNew samples that will be uploaded:\e[0m"
209*d353a188SXin Li    for i in ${toUpload[@]}; do
210*d353a188SXin Li     echo -e "\e[32m$i\e[0m"
211*d353a188SXin Li    done
212*d353a188SXin Li  else
213*d353a188SXin Li    upload=false
214*d353a188SXin Li    echo "Nothing new to upload."
215*d353a188SXin Li  fi
216*d353a188SXin Lielse
217*d353a188SXin Li  echo "No uploads - check skipped on user request"
218*d353a188SXin Lifi
219*d353a188SXin Li
220*d353a188SXin Liif $update; then
221*d353a188SXin Li  if [ ${#needsUpdate[@]} -ne 0 ]; then
222*d353a188SXin Li    echo -e "\n\e[1mSamples that will be updated:\e[0m"
223*d353a188SXin Li    for i in ${needsUpdate[@]}; do
224*d353a188SXin Li      echo -e "\e[34m$i\e[0m"
225*d353a188SXin Li    done
226*d353a188SXin Li  else
227*d353a188SXin Li    update=false
228*d353a188SXin Li    echo "Nothing to update."
229*d353a188SXin Li  fi
230*d353a188SXin Lielse
231*d353a188SXin Li  echo "No updates - check skipped on user request"
232*d353a188SXin Lifi
233*d353a188SXin Li
234*d353a188SXin Liif [ ${#problemSamples[@]} -ne 0 ]; then
235*d353a188SXin Li echoerr "
236*d353a188SXin LiThese repos returned something other than a 404 or 200 result code:"
237*d353a188SXin Li for i in ${problemSamples[@]};
238*d353a188SXin Li do
239*d353a188SXin Li  echoerr "$i"
240*d353a188SXin Li done
241*d353a188SXin Lifi
242*d353a188SXin Li
243*d353a188SXin Liif ! $upload && ! $update; then
244*d353a188SXin Li echo -e "\e[1mLooks like everything's up-to-date.\e[0m\n"
245*d353a188SXin Lielse
246*d353a188SXin Li
247*d353a188SXin Liread -p "
248*d353a188SXin LiDo you want to continue? [y/n]: " -n 1 -r
249*d353a188SXin Liecho
250*d353a188SXin Li# if they type anything but an upper or lower case y, don't proceed.
251*d353a188SXin Liif [[ $REPLY =~ ^[Yy]$ ]]
252*d353a188SXin Lithen
253*d353a188SXin Li   #echo "Commencing Github updates"
254*d353a188SXin Li
255*d353a188SXin Li##############################################################################
256*d353a188SXin Li##  If the user hasn't supplied a token via parameter, ask now
257*d353a188SXin Li
258*d353a188SXin Liif ! [ -n "$token" ]
259*d353a188SXin Lithen
260*d353a188SXin Li read -p "
261*d353a188SXin LiInput a valid googlesamples GitHub access token to continue: " -r
262*d353a188SXin Li token=$REPLY
263*d353a188SXin Lifi
264*d353a188SXin Li
265*d353a188SXin Li##############################################################################
266*d353a188SXin Li##  Test that token
267*d353a188SXin Li
268*d353a188SXin LitokenTest=$(curl -o /dev/null --silent \
269*d353a188SXin Li  -H "Authorization: token $token" \
270*d353a188SXin Li  --write-out '%{http_code}' "https://api.github.com/orgs/googlesamples/repos")
271*d353a188SXin Li
272*d353a188SXin Liif [ "$tokenTest" -eq "200" ]; then
273*d353a188SXin Li
274*d353a188SXin Li
275*d353a188SXin Li##############################################################################
276*d353a188SXin Li##  If there's something to update, do the updates
277*d353a188SXin Liif [ ${#needsUpdate[@]} -ne 0 ] && $update; then
278*d353a188SXin Li for i in ${needsUpdate[@]}; do
279*d353a188SXin Li   echo -e "\nUpdating $i"
280*d353a188SXin Li   if [ -d "android-$i" ]; then
281*d353a188SXin Li     rsync -az --delete --exclude '*.git' ../prebuilts/gradle/$i/ ./android-$i/
282*d353a188SXin Li
283*d353a188SXin Li     cd ./android-$i/
284*d353a188SXin Li
285*d353a188SXin Li     git config user.name "google-automerger"
286*d353a188SXin Li     git config user.email automerger@google.com
287*d353a188SXin Li
288*d353a188SXin Li     git add .
289*d353a188SXin Li     git status
290*d353a188SXin Li     git commit -m "Auto-update"
291*d353a188SXin Li
292*d353a188SXin Li     git remote set-url origin "https://[email protected]/googlesamples/android-$i.git"
293*d353a188SXin Li     git push origin master
294*d353a188SXin Li
295*d353a188SXin Li     #overwrite remote url to not contain auth token
296*d353a188SXin Li     git remote set-url origin "http://github.com/googlesamples/android-$i.git"
297*d353a188SXin Li
298*d353a188SXin Li     cd ..
299*d353a188SXin Li   else
300*d353a188SXin Li     echoerr "Something went wrong when cloning $i - result directory does not exist.
301*d353a188SXin LiLeaving temp files in place for further examination."
302*d353a188SXin Li   deleteTemp=false;
303*d353a188SXin Li  fi
304*d353a188SXin Li done
305*d353a188SXin Lifi
306*d353a188SXin Li
307*d353a188SXin Li#moves out of the temp folder, if we're in it.
308*d353a188SXin Liif [ -d "../github-temp$folderPS" ]; then
309*d353a188SXin Li   cd ..
310*d353a188SXin Lifi
311*d353a188SXin Li
312*d353a188SXin Li##############################################################################
313*d353a188SXin Li##  If there's something new to upload, do the uploads
314*d353a188SXin Liif [ ${#toUpload[@]} -ne 0 ] && $upload; then
315*d353a188SXin Li for i in ${toUpload[@]}; do
316*d353a188SXin Li   echo -e "\nUploading $i"
317*d353a188SXin Li
318*d353a188SXin Li   repoName="googlesamples/android-$i"
319*d353a188SXin Li
320*d353a188SXin Li   CREATE="curl -H 'Authorization: token '$TOKEN \
321*d353a188SXin Li     -d '{\"name\":\"android-'$i'\", \"team_id\":889859}' \
322*d353a188SXin Li     https://api.github.com/orgs/googlesamples/repos"
323*d353a188SXin Li   eval $CREATE
324*d353a188SXin Li
325*d353a188SXin Li   #add secondary team permissions (robots)
326*d353a188SXin Li   ADDTEAM="curl -X PUT \
327*d353a188SXin Li     -H 'Authorization: token '$TOKEN \
328*d353a188SXin Li     -H 'Content-Length: 0' \
329*d353a188SXin Li     https://api.github.com/teams/889856/repos/$repoName"
330*d353a188SXin Li
331*d353a188SXin Li   eval $ADDTEAM
332*d353a188SXin Li
333*d353a188SXin Li   URL="https://[email protected]/$repoName"
334*d353a188SXin Li
335*d353a188SXin Li   cd $i
336*d353a188SXin Li   git init
337*d353a188SXin Li    #overrides .gitconfig just for this project - does not alter your global settings.
338*d353a188SXin Li   git config user.name "google-automerger"
339*d353a188SXin Li   git config user.email automerger@google.com
340*d353a188SXin Li   git add .
341*d353a188SXin Li   git commit -m "Initial Commit"
342*d353a188SXin Li   git remote add origin $URL
343*d353a188SXin Li   git push origin master
344*d353a188SXin Li   cd ..
345*d353a188SXin Li
346*d353a188SXin Li
347*d353a188SXin Li done
348*d353a188SXin Lifi
349*d353a188SXin Li
350*d353a188SXin Lielse
351*d353a188SXin Li  echoerr "That token doesn't work. A test returned the code: $tokenTest"
352*d353a188SXin Lifi
353*d353a188SXin Li
354*d353a188SXin Lielse
355*d353a188SXin Li   echo "User cancelled Github update."
356*d353a188SXin Lifi
357*d353a188SXin Li
358*d353a188SXin Lifi #end of "is there something to do?" if statement