From 28aee475a7e129b3c377c7eb9a0ea9685e620c17 Mon Sep 17 00:00:00 2001 From: FriendlyNeighborhoodShane Date: Tue, 8 Sep 2020 22:10:21 +0530 Subject: [PATCH] Add build script --- .github/workflows/cron.yml | 16 ++++ README.md | 42 +++++++++ diffmsg | 174 +++++++++++++++++++++++++++++++++++++ release | 83 ++++++++++++++++++ run | 144 ++++++++++++++++++++++++++++++ 5 files changed, 459 insertions(+) create mode 100644 .github/workflows/cron.yml create mode 100755 diffmsg create mode 100755 release create mode 100755 run diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml new file mode 100644 index 0000000..652df4c --- /dev/null +++ b/.github/workflows/cron.yml @@ -0,0 +1,16 @@ +# Simple, no-dependency config to execute a file + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + run: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ github.token }} + steps: + - run: | + git clone --single-branch "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" . + ./run diff --git a/README.md b/README.md index fcfdc75..e3644ea 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,45 @@ # MinMicroG Auto Builder Free computing power to the masses, and laziness to me! + +This repo (ab)uses Github's CI mechanism to automatically create MinMicroG +builds whenever something is updated. This offloads the work of manually +checking for updates regularly, as well as making builds for every small +update for people that live on the bleeding edge. + +## !!! + +These are NOT official releases. For official releases see +[here](https://github.com/FriendlyNeighborhoodShane/MinMicroG_releases) + +## !!! + +This is NOT the way to self-build MinMicroG (although it can be a shortcut +to do that). For self-building see +[here](https://github.com/FriendlyNeighborhoodShane/MinMicroG) + +## !!! + +These zips are NOT created by me; I give no guarantees about their legitimacy +or functionality. The script does do signature verification with the last +official release's certificates, however, to the best of its ability. + +## What is this? + +Every midnight (UTC), Github server VMs will run the `run` shell script. +It will see if something has changed since the last time a CI build or +official release was made, and if it has, it will create a release with +all variants. The release will be tagged on the commit of the binary +assets it was made from. + +The release note will be a human-readable list of changes generated by the +`diffmsg` awk script, by feeding on `git diff --raw` outputs with both the +last CI build and the last official release. The update and build log +outputs will be attached as release assets, along with a diff file that +contains the `git diff --stat --patch` outputs. + +The +[`refs/volatile/current`](https://github.com/FriendlyNeighborhoodShane/MinMicroG-abuse-CI/tree/refs%2fvolatile%2fcurrent) +branch of this repo holds the entire resdl binary history of official +MinMicroG releases. But the last commit always holds the binaries from the +last CI build. diff --git a/diffmsg b/diffmsg new file mode 100755 index 0000000..df54617 --- /dev/null +++ b/diffmsg @@ -0,0 +1,174 @@ +#!/bin/awk -f +# create release message for MMG-CI releases +# feeds on git diff --raw + +BEGIN { + + # map uncommon apk names to conventional names for translation + delete appmap + appmap["GoogleBackupTransport"] = "Google sync adapters" + appmap["GoogleCalendarSyncAdapter"] = "Google sync adapters" + appmap["GoogleContactsSyncAdapter"] = "Google sync adapters" + appmap["MicroGGMSCore"] = "MicroG" + appmap["MicroGGSFProxy"] = "GSF proxy" + appmap["MicroGUNLP"] = "UNLP" + appmap["Phonesky"] = "Playstore" + + # init stateful vars + # arrays and index counters + appc = 0 + binc = 0 + cerc = 0 + delete appv + delete binv + delete cerv + +} + +# git diff --raw format +# (p = number of parents of commit) +# (SP = space char) +# { ":" }*p { mode SP }*(p+1) { hash SP }*(p+1) status SP { filepath SP }*? +# 0..p modes and hashes are of parents, (p+1)ths are of the child +# IDK anything about filepaths +# +# example: +# :000000 100644 0000000 3abb859 A README.md +# ::100644 100644 100644 08576ac 08576ac c4585d8 MM system/bin/npem + +# skip non-diff lines +# they don't start with colons +!/^:[:]*/ { next } + +# process each line and take out useful fields +# set variables: file, action +{ + + # match the pattern and get number of colons + # number of colons = number of parents of commit + match($0, "^:[:]*") + parents = RLENGTH + offset = (parents + 1) * 2 + + # get change status and build array of filepaths + change = $(offset + 1) + filec = 0 + delete filev + for (i = offset + 2; i <= NF; i++) { + filev[filec] = $i + filec += 1 + } + + # I have no idea what to with merges + # only supports non-merge commits for now + if (parents != 1) next + if (change ~ "C" || change ~ "R") + # for copies and renames, first filepath is src, second is dst + file = filev[1] + else + # for everything else there is only one filepath + file = filev[0] + + # find action by matching status code + if (change ~ "A" || change ~ "C" || change ~ "R") + action = "added" + else if (change ~ "M") + action = "updated" + else if (change ~ "D") + action = "deleted" + else + # unknown status, skip + next + +} + +# match file with various paths +# add their string and action to relevant arrays +# array[i, 0] = string +# array[i, 1] = action + +# string literals used as regex patterns are parsed twice by awk +# all escapes need to be doubled for simpler implementations + +file ~ "^system/(priv-)?app/[^/]*/(-[^/]*-/)?[^/]*\\.apk$" { + split(file, arr, "/") + str = arr[3] + if (str in appmap) + str = appmap[str] + for (i = 0; i < appc; i++) + if (appv[i, 0] == str) next + appv[appc, 0] = str + appv[appc, 1] = action + appc += 1 + next +} +file ~ "^system/(x)?bin/(-[^/]*-/)?[^/]*$" { + n = split(file, arr, "/") + str = "`" arr[n] "`" + for (i = 0; i < binc; i++) + if (binv[i, 0] == str) next + binv[binc, 0] = str + binv[binc, 1] = action + binc += 1 + next +} +file ~ "^system/framework/(-[^/]*-/)?com\\.google\\.android\\.maps\\.jar$" { + str = "MicroG maps API v1" + for (i = 0; i < binc; i++) + if (binv[i, 0] == str) next + binv[binc, 0] = str + binv[binc, 1] = "updated" + binc += 1 + next +} +file ~ "^util/certs/repo/[^/]*\\.cer$" { + split(file, arr, "/") + repo = substr(arr[4], 1, length(arr[4]) - length(".cer")) + str = "cert for repo" " " repo + for (i = 0; i < cerc; i++) + if (cerv[i, 0] == str) next + cerv[cerc, 0] = str + cerv[cerc, 1] = "changed" + cerc += 1 + next +} +file ~ "^util/certs/system/(priv-)?app/[^/]*/(-[^/]*-/)?[^/]*\\.cer$" { + split(file, arr, "/") + str = "cert for app" " " arr[5] + for (i = 0; i < cerc; i++) + if (cerv[i, 0] == str) next + cerv[cerc, 0] = str + cerv[cerc, 1] = "changed" + cerc += 1 + next +} + +END { + + # printf fmt string + fmt = " - %s %s\n" + + # loop through all non-empty lists and print elements + if (appc) { + print("- Apps changed:") + for (i = 0; i < appc; i++) { + printf(fmt, appv[i, 1], appv[i, 0]) + } + print("") + } + if (binc) { + print("- Binaries changed:") + for (i = 0; i < binc; i++) { + printf(fmt, binv[i, 1], binv[i, 0]) + } + print("") + } + if (cerc) { + print("- Certs changed:") + for (i = 0; i < cerc; i++) { + printf(fmt, cerv[i, 1], cerv[i, 0]) + } + print("") + } + +} diff --git a/release b/release new file mode 100755 index 0000000..02c4de2 --- /dev/null +++ b/release @@ -0,0 +1,83 @@ +#!/bin/sh +# Upload MinMicroG packages to releases + +error() { + echo " "; + echo "!!! FATAL: $1"; + exit 1; +} + +# Exit if not running on Github CI +[ "$GITHUB_TOKEN" ] || exit 0; + +tag="$1"; +name="$2"; +date="$3"; + +# Release variables +auth="Authorization: token $GITHUB_TOKEN"; +ghapi="https://api.github.com/repos/$GITHUB_REPOSITORY/releases"; +ghupl="https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases"; +id="$(curl -fs -H "$auth" "$ghapi/tags/$tag" | jq -r '.id')"; + +# Big if true +if [ "$id" != "null" ] && [ "$id" != "" ]; then + echo " "; + echo "Daily release $tag exists !!!"; + exit 0; +elif (cd "./MinMicroG-resdl" && [ "$(git diff --staged -- system)" ]); then + echo " "; + echo "Committing updates to resdl tracker..."; + ( + cd "./MinMicroG-resdl" || error "could not cd"; + git -c user.name="github-actions" -c user.email="actions@github.com" commit --amend -m "Current bins"; + git push -f "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY" "+HEAD:refs/volatile/current"; + ) +elif [ "$GITHUB_EVENT_NAME" != "workflow_dispatch" ]; then + echo " "; + echo "Nothing to update !!!"; + exit 0; +fi; + +# Release time +echo " "; +echo "Creating release at $tag..."; +commit="$(git -C "./MinMicroG-resdl" rev-parse "HEAD")"; +[ "$commit" ] || error "could not get resdl commit"; +str="$(cat </dev/null; then + sudo "$@"; + else + "$@"; + fi; +} + +# Translate command names to package names +getpkg() { + case "$1" in + *) + echo "$1" + ;; + esac; +} + +# Find package manager +if false; then + :; +elif command -v "apt-get" >/dev/null; then + echo 'debconf debconf/frontend select Noninteractive' | exec_su debconf-set-selections; + exec_su apt-get update -yy >/dev/null; + exec_su apt-get upgrade -yy >/dev/null; + pmcmd() { + pkg="$(getpkg "$1")"; + exec_su apt-get install -yy "$pkg" >/dev/null; + } +else + echo " "; + echo "!!! ERROR: Could not figure out package manager"; + pmcmd() { + return 1; + } +fi; + +# Dependency check +for bin in curl git jq unzip zip; do + command -v "$bin" >/dev/null || pmcmd "$bin"; + command -v "$bin" >/dev/null || error "could not install dependency: $bin"; +done; +for bin in aapt java; do + command -v "$bin" >/dev/null || pmcmd "$bin"; + command -v "$bin" >/dev/null || { + echo " "; + echo "!!! ERROR: Could not install optional dependency: $bin !!!"; + } +done; + +# Workaround for stupid outdated debian packages +command -v "java" >/dev/null && { + d="$(mktemp -d)"; + curl -fL "https://dl.google.com/android/repository/build-tools_r33.0.1-linux.zip" -o "$d/build-tools.zip"; + unzip -p "$d/build-tools.zip" "android-13/lib/apksigner.jar" > "$d/apksigner.jar"; + printf '#!/bin/sh\njava -jar "%s" "$@";\n' "$d/apksigner.jar" > "$d/apksigner"; + chmod +x "$d/apksigner"; + export PATH="$d:$PATH"; +} + +# Variables +tag="$(date -u +"%Y.%m.%d")"; +name="$(date -u +"%d %b %Y")"; +date="$(date -u +"%Y%m%d%H%M%S")"; + +# Clone time +echo " "; +echo "Cloning MinMicroG..."; +git clone "https://github.com/FriendlyNeighborhoodShane/MinMicroG"; +git clone "https://github.com/FriendlyNeighborhoodShane/MinMicroG-abuse-CI" "MinMicroG-resdl"; +( + cd "./MinMicroG-resdl" || error "could not cd"; + git fetch origin "refs/volatile/current:current"; + git checkout "current"; + git reset; +) + +# Intro +mkdir "./MinMicroG/releases"; +echo " "; +{ + echo " --- MinMicroG autobuild logs --- "; + echo " "; + echo "Date: $name $date"; + echo "System: $(uname -a)"; +} | tee "./MinMicroG/releases/build-$date.log"; + +# Setup stuff +echo " "; +echo "Setting up build..."; +ln -frs "./MinMicroG-resdl/system" "./MinMicroG-resdl/util" "./MinMicroG/resdl/"; +cert="$(curl -fs "https://api.github.com/repos/FriendlyNeighborhoodShane/MinMicroG_releases/releases" | jq -r ".[].assets[].browser_download_url" | grep "certs.tar.gz$" | head -n1)"; +[ "$cert" ] && { + { + echo " "; + echo "Cert archive found at $cert" + } | tee -a "./MinMicroG/releases/build-$date.log"; + ( + cd "./MinMicroG-resdl/util/certs" || error "could not cd"; + rm -rf ./*; + curl -fL "$cert" | tar xz; + ) +} + +# Build time +echo " "; +echo "Updating and building MinMicroG..."; +( + echo " "; + cd "./MinMicroG" || error "could not cd"; + ./bump.sh "UPDATELY" "999999" "$name"; + ./update.sh; + ./build.sh all; +) 2>&1 | tee -a "./MinMicroG/releases/build-$date.log"; + +# Create diff +echo " "; +echo "Generating update diff..."; +echo " "; +( + cd "./MinMicroG-resdl" || error "could not cd"; + git add -A; + echo "Update diff from last CI build:"; + echo " "; + git diff -C -C --stat --patch --staged; + echo " "; + echo "Update diff from last official build:"; + echo " "; + git diff -C -C --stat --patch --staged "HEAD^"; +) | tee "./MinMicroG/releases/diff-$date.txt"; + +# Run release script +[ -f ./release ] && ./release "$tag" "$name" "$date";