Add build script

hub
FriendlyNeighborhoodShane 4 years ago
parent 666c777d2f
commit 28aee475a7

@ -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

@ -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.

@ -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("")
}
}

@ -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 <<EOF | jq -Rsr "@json";
Automatic release triggered by $GITHUB_EVENT_NAME.
The masses deserve to be lazy!
Update diff from last CI build:
$( (cd "./MinMicroG-resdl" && git diff --raw "HEAD@{1}";) | "./diffmsg" | sed 's|^| |g'; )
Update diff from last official release:
$( (cd "./MinMicroG-resdl" && git diff --raw "HEAD^";) | "./diffmsg" | sed 's|^| |g'; )
EOF
)";
id="$(cat <<EOF | curl --data "@-" -H "$auth" -H "Content-Type: application/json" "$ghapi" | jq -r '.id';
{
"tag_name": "$tag",
"target_commitish": "$commit",
"name": "$name",
"body": $str,
"draft": true
}
EOF
)";
[ "$id" ] && [ "$id" != "null" ] || error "could not find release id";
# Upload time
echo " ";
echo "Uploading files...";
for file in "./MinMicroG/releases"/*; do
ghass="$ghupl/$id/assets?name=$(basename "$file")";
curl --data-binary @"$file" -H "$auth" -H "Content-Type: application/octet-stream" "$ghass" -o /dev/null;
done;
# Publish drafted release
cat <<EOF | curl --data "@-" -H "$auth" -H "Content-Type: application/json" "$ghapi/$id";
{"draft":false}
EOF

144
run

@ -0,0 +1,144 @@
#!/bin/sh
# Build and upload MinMicroG packages
error() {
echo " ";
echo "!!! FATAL: $1";
exit 1;
}
# Use sudo if available
exec_su() {
if false; then
return 1;
elif command -v "sudo" >/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";
Loading…
Cancel
Save