From 8a41e710c4adcb5a7dc2842acb66eed0461e10a7 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 19 Jan 2026 12:22:19 +0100 Subject: [PATCH 01/64] chore: do not duplicate trap * inherited by sync trap * _cleanup_fail overwritten by each process --- scripts/ota.sh | 2 -- scripts/packaging.sh | 2 -- scripts/sign.sh | 2 -- scripts/upload.sh | 2 -- 4 files changed, 8 deletions(-) diff --git a/scripts/ota.sh b/scripts/ota.sh index cf79bd6..18b4a46 100644 --- a/scripts/ota.sh +++ b/scripts/ota.sh @@ -56,8 +56,6 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _ota_info if [[ -n "${OTA_REPO_URL}" ]]; then _push_ota_info diff --git a/scripts/packaging.sh b/scripts/packaging.sh index c99ddf7..a7cb12a 100644 --- a/scripts/packaging.sh +++ b/scripts/packaging.sh @@ -66,8 +66,6 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _packaging _extract_recovery _print_build_success diff --git a/scripts/sign.sh b/scripts/sign.sh index 2711a6b..6debaf3 100644 --- a/scripts/sign.sh +++ b/scripts/sign.sh @@ -88,8 +88,6 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _cleanup if [[ -n "${ROM_BUILD_FLAGS}" ]]; then IFS=',' read -r -a "ROM_BUILD_FLAGS" <<< "${ROM_BUILD_FLAGS}" diff --git a/scripts/upload.sh b/scripts/upload.sh index 1091038..a1e0a8b 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -79,8 +79,6 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _upload if [[ -n "${UPLOAD_TARGET}" ]]; then _print_upload_success From bce9a0bc914bb61f7a1fb01398b061f5b01288af Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 19 Jan 2026 13:00:31 +0100 Subject: [PATCH 02/64] chore: fail ota when pushing is not possible --- scripts/ota.sh | 4 +++- scripts/upload.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/ota.sh b/scripts/ota.sh index 18b4a46..fe79797 100644 --- a/scripts/ota.sh +++ b/scripts/ota.sh @@ -32,9 +32,11 @@ _push_ota_info() { target_ota_repo_url="${OTA_REPO_URL}" elif [[ -n "${GITHUB_TOKEN}" ]]; then target_ota_repo_url="${OTA_REPO_URL//git@github.com:/https://${GITHUB_TOKEN}@github.com/}" + else + _cleanup_fail fi - # Specify a fallback, so that roms, that purely rely on android numbers dont collide + # Specify a fallback, so that roms, that purely rely on android numbers do not collide if [[ -n "${ROM_OTA_BRANCH_FALLBACK}" ]]; then target_ota_branch="${ROM_OTA_BRANCH_FALLBACK}" else diff --git a/scripts/upload.sh b/scripts/upload.sh index a1e0a8b..cab2635 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -37,7 +37,7 @@ _upload_gh() { https://api.github.com/repos/"${release_repo}"/releases \ --data "{ \"tag_name\": \"${tag}\", \"body\": \"${desc}\" }" \ | tr --delete '\n' | json_arg_parser.py "upload_url" \ - | cut --delimiter='{' -f1) + | cut --delimiter='{' --fields=1) # Upload ROM DL_OTA_URL=$(curl_cmd \ From ad63ab77e84796c4b3acb44d46fc3aca9bf95d41 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 19 Jan 2026 13:21:52 +0100 Subject: [PATCH 03/64] chore: use host python for A16+ * works after https://github.com/LineageOS/android_build/commit/0157cd3ebb39b62d29c56c1b08121d89937235f7 --- scripts/compat.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/compat.sh b/scripts/compat.sh index e4ffab1..a85024b 100644 --- a/scripts/compat.sh +++ b/scripts/compat.sh @@ -55,7 +55,7 @@ _key_size_recovery() { if [[ "${ANDROID_VERSION}" -lt 10 ]]; then _init_py2 # A10-15 -else +elif [[ "${ANDROID_VERSION}" -lt 16 ]]; then _init_py3 fi From d326ab724c52083295f10ac226192e08cf3dc4a1 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 10:42:46 +0100 Subject: [PATCH 04/64] chore: drop redundant cd --- scripts/sign.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/sign.sh b/scripts/sign.sh index 6debaf3..ee5150d 100644 --- a/scripts/sign.sh +++ b/scripts/sign.sh @@ -5,7 +5,6 @@ source "${SCRIPT_DIR}"/print.sh # Drop old builds _cleanup() { - cd "${ROM_DIR}" || exit set +eu if ! m installclean -j"$(nproc)" 2>&1 | tee --append "${LOGS_DIR}"/"${BUILD_DATE}"/build.txt then From 5d1092dce1ce23c85188458f1a54ce6e132e5959 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 11:29:08 +0100 Subject: [PATCH 05/64] docs: describe ssh upload --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 29b6207..e4562f6 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,11 @@ LOCAL_MANIFEST=https://raw.githubusercontent.com/SirRGB/local_manifests/refs/hea - ```SF_USER```: Username of your account - ```SF_RELEASES_REPO```: Project name - Requires passwordless ssh keys added to your [SourceForge account](https://sourceforge.net/p/forge/documentation/SSH%20Keys) +- SSH Upload + - ```SSH_USER```: Username on the ssh server + - ```SSH_UPLOAD_URL```: ssh server domain or ip + - ```SSH_DOWNLOAD_URL```: Direct download url excluding filename to ssh server + - Requires passwordless ssh keys with respective public keys authorized on your ssh server - Telegram logging - ```[TELEGRAM_TOKEN](https://core.telegram.org/bots/features#botfather)``` - ```TELEGRAM_CHAT```: either as @xyz or the id From 29b72e553edda86cfb61bbf938a605c3086f4391 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 11:35:08 +0100 Subject: [PATCH 06/64] chore: describe repopick --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e4562f6..2e4ed08 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,10 @@ LOCAL_MANIFEST=https://raw.githubusercontent.com/SirRGB/local_manifests/refs/hea - OTA Updates - At least one file provider mentioned above - ```OTA_REPO_URL```: Any git hoster using ssh authentification i.e. GitHub, GitLab, CodeBerg,... +- Repopick + - ```REPOPICK_PICKS```: Fetch changes from respective Gerrit instance using short-form change-id + - ```REPOPICK_TOPICS```: Fetch changes from respective Gerrit instance using topics + - ```REPOPICK_PULLS```: Pull changes from respective Gerrit instance using short-form change-id These variables should be defined in config.env. From b544167854a9ae04103d799c7baaa2ff3254220e Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 11:46:57 +0100 Subject: [PATCH 07/64] chore: describe fallbacks --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2e4ed08..f0bfec9 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,12 @@ LOCAL_MANIFEST=https://raw.githubusercontent.com/SirRGB/local_manifests/refs/hea ### optional +- Fallbacks + - ```LUNCH_PREFIX_FALLBACK```: Prefix for lunching, i.e. lineage_ for LineageOS. Needed when neither ```LOCAL_MANIFEST``` or ```CLONE_REPOS``` are specified. + - ```ROM_PREFIX_FALLBACK```: Prefix for naming, i.e. lineage will result in a package name like lineage-extraversion(if set)-version-date-device-signed.zip. Needed when *_TARGET_PACKAGE is not defined in vendor/*/build/tasks/* or build/core/Makefile. + - ```ROM_VERSION_FALLBACK```: Version fallback for package name. Needed when rom does not specify PRODUCT_VERSION_MINOR/PRODUCT_VERSION_MAJOR in vendor/*/config/. + - ```ROM_OTA_BRANCH_FALLBACK```: Ota branch fallback. Needed when roms have conflicting branch names and ota updates are set up. + - ```RELEASETOOL_EXTRA_FLAGS```: Releasetool flags for setting up legacy quirks i.e. skip certain vintf checks. - GitHub Upload - ```[GITHUB_TOKEN](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)``` - ```OTA_REPO_URL```: for example git@github.com:user/ota_config, will also be used for uploading From c7703ed591beb6120c859ae9667dda2722b501c8 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 12:35:19 +0100 Subject: [PATCH 08/64] docs: correct md syntax highlighting --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f0bfec9..f477a81 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ LOCAL_MANIFEST=https://raw.githubusercontent.com/SirRGB/local_manifests/refs/hea - ```ROM_OTA_BRANCH_FALLBACK```: Ota branch fallback. Needed when roms have conflicting branch names and ota updates are set up. - ```RELEASETOOL_EXTRA_FLAGS```: Releasetool flags for setting up legacy quirks i.e. skip certain vintf checks. - GitHub Upload - - ```[GITHUB_TOKEN](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)``` + - ```[GITHUB_TOKEN]```: [Github Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) for upload (and/or push) authentification - ```OTA_REPO_URL```: for example git@github.com:user/ota_config, will also be used for uploading - Requires ```GITHUB_TOKEN``` or passwordless ssh keys [added to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) - SourceForge Upload @@ -133,7 +133,7 @@ LOCAL_MANIFEST=https://raw.githubusercontent.com/SirRGB/local_manifests/refs/hea - ```SSH_DOWNLOAD_URL```: Direct download url excluding filename to ssh server - Requires passwordless ssh keys with respective public keys authorized on your ssh server - Telegram logging - - ```[TELEGRAM_TOKEN](https://core.telegram.org/bots/features#botfather)``` + - ```TELEGRAM_TOKEN```: [Telegram Token](https://core.telegram.org/bots/features#botfather). Needed when telegram logging is set up. - ```TELEGRAM_CHAT```: either as @xyz or the id - ```TIME_ZONE```: either as in the format UTC+2 or CET - ```ROM_BUILD_FLAGS```: if you want to define values like ```WITH_GMS=true``` you can do this in here, even with multiple of them separated by comma for separate builds or space for the same build From 7479d3b54a34f1620c87cdf95fab3728a026f931 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 12:38:13 +0100 Subject: [PATCH 09/64] docs: update debug behavior --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f477a81..8dd6bae 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ docker compose up --force-recreate --build ## Debugging - Look up known issues in [TODO.md](TODO.md) -- If the error is undocumented you can uncomment [this](https://github.com/SirRGB/dockdroid/blob/da9593dca1ced7932f7f4295d20fab7077104b73/scripts/init.sh#L3) and send the part of the logs, where things go overboard via the [issues](https://github.com/SirRGB/dockdroid/issues) or debug it on your own and send a pull request. +- If the error is undocumented you can set DEBUG=true in the target.env and send the part of the logs, where things go overboard via the [issues](https://github.com/SirRGB/dockdroid/issues) or debug it on your own and send a pull request. ## Too much RAM From 42deea8e2c125d1ddafb4ed12b45f9fbc52297ab Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 13:50:17 +0100 Subject: [PATCH 10/64] build: allow to overwrite registry and user --- base/Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/base/Makefile b/base/Makefile index d19644e..5c160a5 100644 --- a/base/Makefile +++ b/base/Makefile @@ -1,13 +1,15 @@ all: build run tag ?= $$(date +%Y%m%d%H%M) +user ?= sirrgb +registry ?= docker.io build: - docker build . --tag docker.io/sirrgb/dockdroid-base:latest + docker build . --tag $(registry)/$(user)/dockdroid-base:latest run: - docker run --interactive --tty docker.io/sirrgb/dockdroid-base:latest + docker run --interactive --tty $(registry)/$(user)/dockdroid-base:latest publish: - docker tag docker.io/sirrgb/dockdroid-base:latest docker.io/sirrgb/dockdroid-base:$(tag) - docker image push docker.io/sirrgb/dockdroid-base:$(tag) - docker image push docker.io/sirrgb/dockdroid-base:latest + docker tag $(registry)/$(user)/dockdroid-base:latest $(registry)/$(user)/dockdroid-base:$(tag) + docker image push $(registry)/$(user)/dockdroid-base:$(tag) + docker image push $(registry)/$(user)/dockdroid-base:latest From aa6f0a3a2e11d56b81ca9a53b5f44ab3367545ec Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 14:00:01 +0100 Subject: [PATCH 11/64] docs: describe base image/makefile usage --- base/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 base/README.md diff --git a/base/README.md b/base/README.md new file mode 100644 index 0000000..94259e6 --- /dev/null +++ b/base/README.md @@ -0,0 +1,7 @@ +Build the base image +--- +You can simply build this base image by running `make build` +If you wish to configure the registry, user or tag you can do so by adding the parameters to the command like `make build user=exampleuser registry=example.com tag=exampletag` + +To use your newly made image you have to adapt the Dockerfile in the above directory and replace the ```FROM docker.io/sirrgb/dockdroid-base:latest``` statement with ```FROM example.com/exampleuser/dockdroid-base:exampletag``` +If you want to make your changes public you can run ```docker login example.com``` where example.com is your chosen registry and follow the given instructions. The same works for podman. ```make publish``` will push the image to that registry with your chosen tag and latest. From 285021dbd00325d1ccc0a955f295ad1ec2bcacb7 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 14:01:58 +0100 Subject: [PATCH 12/64] docs: add gsi to todo --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index 38f45dc..d367608 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +1,3 @@ ## ToDo - make vendor pulling work for multiple devices +- GSI/patch handling From 17b151d08c67173b7d2ed2d728b44d48f65c40aa Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 14:09:36 +0100 Subject: [PATCH 13/64] docs: explain why you might want to alter the base image --- base/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/README.md b/base/README.md index 94259e6..de43b92 100644 --- a/base/README.md +++ b/base/README.md @@ -1,5 +1,8 @@ Build the base image --- +To use this you need to have ```make``` installed on your system. Alternatively you can also reference the Makefile itself and run the commands manually. +You only want to alter the base image if you need to alter the dependencies, which you can also do in the Dockerfile in the root of this repo, but at the cost of build-time. + You can simply build this base image by running `make build` If you wish to configure the registry, user or tag you can do so by adding the parameters to the command like `make build user=exampleuser registry=example.com tag=exampletag` From 9044f979411c1de28b496a1d68f670e3555b3346 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 15:16:36 +0100 Subject: [PATCH 14/64] docs: recommend compiling podman-compose over pip installation --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8dd6bae..d267d85 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ This project targets Android 7 up to the most recent version. ## Prerequisites - [Podman](https://podman.io/docs/installation) - - [Podman compose](https://github.com/containers/podman-compose?tab=readme-ov-file#pip) + - [Podman compose](https://github.com/containers/podman-compose?tab=readme-ov-file#generate-binary-using-dockerpodman-locally) - or [Docker](https://docs.docker.com/engine/install) - [Docker Compose](https://docs.docker.com/compose/install) - - [Docker Rootless](https://docs.docker.com/engine/security/rootless/) + - [Docker Rootless](https://docs.docker.com/engine/security/rootless) - [SSH](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) - [GitConfig](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) - ZRam (highly recommended): [Debian](https://wiki.debian.org/ZRam), [Fedora](https://github.com/systemd/zram-generator), [Ubuntu, Arch and others](https://wiki.archlinux.org/title/Zram) @@ -55,7 +55,7 @@ sudo chown --recursive 52587:"${UID}" ~/docker_droid/src ~/docker_droid/dotfiles #### Other (If you know a smarter way to do this please tell me, -I know the available subuids can be found with `grep $USER < /etc/subuid | cut --delimiter=":" --fields=2` +I know the available subuids can be found with `grep ${USER} < /etc/subuid | cut --delimiter=':' --fields=2` I just do not know if the container uid is predictable, it seems to be 1000 for debian/ubuntu and 100 for fedora) @@ -79,7 +79,7 @@ sudo chown --recursive UID:"${UID}" ~/docker_droid/src ~/docker_droid/dotfiles ~ ``` And remove the incomplete sync ``` -sudo rm -rf ~/docker_droid/src/Los15/ +sudo rm --recursive --force ~/docker_droid/src/Los15/ ``` From 056d0c6e5230d603bf31864a12170a11637973ae Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 15:25:30 +0100 Subject: [PATCH 15/64] docs: use longform commands --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d267d85..5ce7f35 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,12 @@ which should be $subUID+$containerUID-1 according to the [docker forums](https:/ We need to manually create the required folders for the respective volumes ``` -mkdir -p ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys +mkdir --parents ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys ``` Copy the required dotfiles from the host machines ``` cp ~/.gitconfig ~/docker_droid/dotfiles/ -cp -r ~/.ssh ~/docker_droid/dotfiles/ +cp --recursive ~/.ssh ~/docker_droid/dotfiles/ ``` and clone this repo ``` @@ -70,7 +70,7 @@ docker compose up --force-recreate --build Wait until it starts syncing and stop using ctrl + c Find out the uid by running: ``` -ls -n ~/docker_droid/src/Los15/.repo +ls --numeric-uid-gid ~/docker_droid/src/Los15/.repo ``` Give ownership to the uid you found out: (replace the 1st UID) From d0daa9fbafbddb46d94d4e20174fe066c8210b8a Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 15:40:15 +0100 Subject: [PATCH 16/64] chore: use absolute path for python scripts --- Dockerfile | 2 +- scripts/compat.sh | 2 +- scripts/sync.sh | 4 ++-- scripts/upload.sh | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1343d8d..f8aad05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ USER root # Create dirs and copy scripts RUN mkdir --parents "${SCRIPT_DIR}" COPY scripts/ "${SCRIPT_DIR}"/ -COPY py-utils/ "${BIN_DIR}"/ +COPY py-utils/ "${SCRIPT_DIR}"/ # Set up user and work directories RUN chown --recursive "${userid}":"${groupid}" "${ROOT_DIR}" && chmod --recursive u+srw "${ROOT_DIR}" diff --git a/scripts/compat.sh b/scripts/compat.sh index a85024b..95f2044 100644 --- a/scripts/compat.sh +++ b/scripts/compat.sh @@ -25,7 +25,7 @@ _setup_jdk8() { --header 'Accept: application/vnd.github+json' \ --header 'X-GitHub-Api-Version: 2022-11-28' \ https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest \ - | tr --delete '\n' | json_arg_parser.py "tag_name") + | tr --delete '\n' | "${SCRIPT_DIR}"/json_arg_parser.py "tag_name") jdk_name=OpenJDK8U-jdk_x64_linux_hotspot_$(tr --delete '-' <<< "${jdk_tag//jdk/}").tar.gz mkdir --parents "${jdk_dir}" curl_cmd --remote-name https://github.com/adoptium/temurin8-binaries/releases/download/"${jdk_tag}"/"${jdk_name}" --output-dir "${jdk_dir}" diff --git a/scripts/sync.sh b/scripts/sync.sh index 0660be0..2f502a1 100644 --- a/scripts/sync.sh +++ b/scripts/sync.sh @@ -18,10 +18,10 @@ _sync() { find "${ROM_DIR}"/.repo/local_manifests/ -type f -exec rm {} \; if [[ -n "${LOCAL_MANIFEST}" ]]; then # Merge local manifests into one to avoid conflicts with duplicate dependencies - xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml + "${SCRIPT_DIR}"/xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml elif [[ -z "${CLONE_REPOS}" ]]; then # Generate vendor manifest, so that official lineage just builds - xml_roomservice.py "${DEVICE}" "${ROM_BRANCH}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml + "${SCRIPT_DIR}"/xml_roomservice.py "${DEVICE}" "${ROM_BRANCH}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml fi local threads threads=$(nproc) diff --git a/scripts/upload.sh b/scripts/upload.sh index cab2635..9ed6017 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -36,7 +36,7 @@ _upload_gh() { --header 'content-type: application/json' \ https://api.github.com/repos/"${release_repo}"/releases \ --data "{ \"tag_name\": \"${tag}\", \"body\": \"${desc}\" }" \ - | tr --delete '\n' | json_arg_parser.py "upload_url" \ + | tr --delete '\n' | "${SCRIPT_DIR}"/json_arg_parser.py "upload_url" \ | cut --delimiter='{' --fields=1) # Upload ROM @@ -47,7 +47,7 @@ _upload_gh() { --header "Content-Type: $(file -b --mime-type "${OUT}"/"${PACKAGE_NAME}")" \ --upload-file "${OUT}"/"${PACKAGE_NAME}" \ "${upload_url}"?name="${PACKAGE_NAME}" \ - | tr --delete '\n' | json_arg_parser.py "browser_download_url") + | tr --delete '\n' | "${SCRIPT_DIR}"/json_arg_parser.py "browser_download_url") # Upload Recovery curl_cmd \ From e8f9691ff1fea94db56bd3ccaa363c67ccca98cb Mon Sep 17 00:00:00 2001 From: sirrgb Date: Wed, 21 Jan 2026 16:43:22 +0100 Subject: [PATCH 17/64] chore: exact path/def --- scripts/lunch.sh | 2 +- scripts/sync.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/lunch.sh b/scripts/lunch.sh index b2d126b..ca40fed 100644 --- a/scripts/lunch.sh +++ b/scripts/lunch.sh @@ -9,7 +9,7 @@ _lunch() { # Append release codename, if exists (A14+) local release_codename - release_codename= + release_codename='' if [[ -d "${ANDROID_BUILD_TOP}"/build/release/aconfig/ ]]; then release_codename=-$(find "${ANDROID_BUILD_TOP}"/build/release/aconfig/* -maxdepth 0 -type d -name '[a-z][a-z][0-9][a-z]' -printf '%f\n' | tail --lines=1) fi diff --git a/scripts/sync.sh b/scripts/sync.sh index 2f502a1..a3edde5 100644 --- a/scripts/sync.sh +++ b/scripts/sync.sh @@ -71,7 +71,7 @@ _clone() { branch=$(rev <<< "${full_repo_name}" | cut --delimiter='/' --fields=-1 | rev) target_path=$(rev <<< "${full_repo_name}" | cut --delimiter='/' --fields=3 | rev | sed 's/android_//g; s/proprietary_//g; s|_|/|g') rm --recursive --force "${target_path}" || true - git clone "${repo_name}" --branch "${branch}" "${target_path}" + git clone "${repo_name}" --branch "${branch}" "${ANDROID_BUILD_TOP}"/"${target_path}" } # Wrapper to clone all repos defined in $CLONE_REPOS From 3dcf254ce37bf13d8ddc1ebe9f6e0046336c7823 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Wed, 21 Jan 2026 22:14:34 +0100 Subject: [PATCH 18/64] docs: document telegram logging quirk --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index d367608..13f29b8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,4 @@ ## ToDo - make vendor pulling work for multiple devices - GSI/patch handling +- fix telegram/curl failure on devices like "poplar_canada" From f78cb001cee6c10f9cca10a1812ad07d567e9d7a Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 22 Jan 2026 10:40:50 +0100 Subject: [PATCH 19/64] feat: add remove-project functionality --- TODO.md | 1 + py-utils/xml_manifest_gen.py | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 13f29b8..ae47694 100644 --- a/TODO.md +++ b/TODO.md @@ -2,3 +2,4 @@ - make vendor pulling work for multiple devices - GSI/patch handling - fix telegram/curl failure on devices like "poplar_canada" +- project linkfile handling diff --git a/py-utils/xml_manifest_gen.py b/py-utils/xml_manifest_gen.py index 5c0f96c..7003b70 100755 --- a/py-utils/xml_manifest_gen.py +++ b/py-utils/xml_manifest_gen.py @@ -6,11 +6,15 @@ from urllib.request import urlopen, Request -def is_in_manifest(manifest: xml, project_path: str = "", project_remote: str = "") -> bool: +def is_in_manifest(manifest: xml, project_path: str = "", project_remote: str = "", project_remove: str = "") -> bool: for manifest_project in manifest.findall("project"): if project_path == manifest_project.get("path"): return True + for manifest_project in manifest.findall("remove-project"): + if project_remove == manifest_project.get("name"): + return True + for manifest_project in manifest.findall("remote"): if project_remote == manifest_project.get("name"): return True @@ -40,6 +44,20 @@ def add_project_to_manifest(manifest: xml, project_name: str, project_path: str, manifest.append(element) return manifest +def add_project_remove_to_manifest(manifest: xml, project_remove_name: str) -> xml: + if is_in_manifest(manifest=manifest, project_remove=project_remove_name): + return manifest + + element = ElementTree.Element( + "remove-project", + attrib={ + "name": project_remove_name, + }, + ) + + manifest.append(element) + return manifest + def add_remote_to_manifest(manifest: xml, remote_name: str, remote_fetch: str, remote_revision: str = "") -> xml: if is_in_manifest(manifest=manifest, project_remote=remote_name): @@ -74,6 +92,12 @@ def generate_manifest(local_manifest: xml, remote_manifest: xml) -> xml: remote_revision=revision ) + for projects in remote_manifest.findall("remove-project"): + local_manifest = add_project_remove_to_manifest( + manifest=local_manifest, + project_remove_name=projects.get("name") + ) + for projects in remote_manifest.findall("project"): if projects.get("remote") == "": remote = "" From 7c95008441ef18db8f50e6804d15653c05e39604 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 22 Jan 2026 11:00:28 +0100 Subject: [PATCH 20/64] feat: return to curl for single local manifests --- scripts/sync.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/sync.sh b/scripts/sync.sh index a3edde5..b42a686 100644 --- a/scripts/sync.sh +++ b/scripts/sync.sh @@ -17,8 +17,12 @@ _sync() { # Remove local manifests find "${ROM_DIR}"/.repo/local_manifests/ -type f -exec rm {} \; if [[ -n "${LOCAL_MANIFEST}" ]]; then - # Merge local manifests into one to avoid conflicts with duplicate dependencies - "${SCRIPT_DIR}"/xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml + if grep -q ',' <<< "${LOCAL_MANIFEST}"; then + # Merge local manifests into one to avoid conflicts with duplicate dependencies + "${SCRIPT_DIR}"/xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml + else + curl_cmd "${LOCAL_MANIFEST}" --output "${ROM_DIR}"/.repo/local_manifests/manifest.xml + fi elif [[ -z "${CLONE_REPOS}" ]]; then # Generate vendor manifest, so that official lineage just builds "${SCRIPT_DIR}"/xml_roomservice.py "${DEVICE}" "${ROM_BRANCH}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml From 361ef6de7db9a402ff1c441c8704ef7db4f1f8a6 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Fri, 23 Jan 2026 10:53:16 +0100 Subject: [PATCH 21/64] fix: depend on target branch --- scripts/ota.sh | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/scripts/ota.sh b/scripts/ota.sh index fe79797..a60b3f6 100644 --- a/scripts/ota.sh +++ b/scripts/ota.sh @@ -21,7 +21,20 @@ _push_ota_info() { fi cd "${ROM_DIR}"_ota || exit git init - git pull "${OTA_REPO_URL}" "${ROM_BRANCH}" + + # Specify a fallback, so that roms, that purely rely on android numbers do not collide + if [[ -n "${ROM_OTA_BRANCH_FALLBACK}" ]]; then + target_ota_branch="${ROM_OTA_BRANCH_FALLBACK}" + else + target_ota_branch="${ROM_BRANCH}" + fi + + # Append extraversion to avoid collision of different flavours + if [[ -n "${ROM_EXTRAVERSION}" ]]; then + target_ota_branch="${target_ota_branch}"-"$(tr --delete '-' <<< "${ROM_EXTRAVERSION,,}")" + fi + + git pull "${OTA_REPO_URL}" "${target_ota_branch}" cp "${OUT}"/"${PACKAGE_NAME}".json "${ROM_DIR}"_ota/"${TARGET_DEVICE}".json git add "${ROM_DIR}"_ota/"${TARGET_DEVICE}".json @@ -36,18 +49,6 @@ _push_ota_info() { _cleanup_fail fi - # Specify a fallback, so that roms, that purely rely on android numbers do not collide - if [[ -n "${ROM_OTA_BRANCH_FALLBACK}" ]]; then - target_ota_branch="${ROM_OTA_BRANCH_FALLBACK}" - else - target_ota_branch="${ROM_BRANCH}" - fi - - # Append extraversion to avoid collision of different flavours - if [[ -n "${ROM_EXTRAVERSION}" ]]; then - target_ota_branch="${target_ota_branch}"-"$(tr --delete '-' <<< "${ROM_EXTRAVERSION,,}")" - fi - if [[ -n "${target_ota_repo_url}" ]]; then git push "${target_ota_repo_url}" HEAD:"${target_ota_branch}" fi From abb81f02a380808d2d68ab606df5c044892e04f6 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Fri, 23 Jan 2026 15:34:51 +0100 Subject: [PATCH 22/64] docs: add more todos --- TODO.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO.md b/TODO.md index ae47694..c07be94 100644 --- a/TODO.md +++ b/TODO.md @@ -3,3 +3,5 @@ - GSI/patch handling - fix telegram/curl failure on devices like "poplar_canada" - project linkfile handling +- progress message telegram +- incremental updates From e5b99ebaa6671c4c3b533f789759f7e810c3ab17 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sat, 24 Jan 2026 13:46:13 +0100 Subject: [PATCH 23/64] chore: bump gh actions to v6 --- .github/workflows/shellcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index b921833..d24a1ea 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -6,6 +6,6 @@ jobs: name: ShellCheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Run ShellCheck run: find ./scripts -type f -name "*.sh" -exec shellcheck --enable require-double-brackets,require-variable-braces,avoid-nullary-conditions {} + From 69d6ceb3aab3aa642ed17db5014f977d776901a7 Mon Sep 17 00:00:00 2001 From: sirrgb Date: Thu, 5 Feb 2026 10:03:31 +0100 Subject: [PATCH 24/64] docs: py conversion and ordering --- TODO.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO.md b/TODO.md index c07be94..013b30a 100644 --- a/TODO.md +++ b/TODO.md @@ -5,3 +5,8 @@ - project linkfile handling - progress message telegram - incremental updates +- drop use of git, https://stackoverflow.com/questions/69069145/using-curl-for-pushing-a-file-to-github-repository +- move to py (apart from env vars?, devices as objects?) + - linting, pre-commit +- rename files to indicate order +- only log errors (docker/podman logs work otherwise) From 56d33bfc75602880fb5e39ea4eef175cc193c5ca Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 16 Feb 2026 13:31:51 +0100 Subject: [PATCH 25/64] docs: drop git curl replacement * would break non-github ota usage --- TODO.md | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO.md b/TODO.md index 013b30a..09e8118 100644 --- a/TODO.md +++ b/TODO.md @@ -5,7 +5,6 @@ - project linkfile handling - progress message telegram - incremental updates -- drop use of git, https://stackoverflow.com/questions/69069145/using-curl-for-pushing-a-file-to-github-repository - move to py (apart from env vars?, devices as objects?) - linting, pre-commit - rename files to indicate order From d1484dc7314bddc333370ceae298b33d4e6a302d Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 16 Feb 2026 13:48:29 +0100 Subject: [PATCH 26/64] fix: partially move printing to python --- TODO.md | 1 - base/Dockerfile | 1 + py-utils/print.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/print.sh | 38 +++++--------------------------- 4 files changed, 63 insertions(+), 33 deletions(-) create mode 100755 py-utils/print.py diff --git a/TODO.md b/TODO.md index 09e8118..aea8b97 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,6 @@ ## ToDo - make vendor pulling work for multiple devices - GSI/patch handling -- fix telegram/curl failure on devices like "poplar_canada" - project linkfile handling - progress message telegram - incremental updates diff --git a/base/Dockerfile b/base/Dockerfile index 7dabe0b..1fb04a5 100644 --- a/base/Dockerfile +++ b/base/Dockerfile @@ -55,6 +55,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update -qq && DEBIAN_FRONTEND=noninte libreadline-dev \ # Automation file \ + python3-requests \ unzip RUN rm --recursive /var/lib/apt/lists /var/cache/apt/archives diff --git a/py-utils/print.py b/py-utils/print.py new file mode 100755 index 0000000..4d4b1f0 --- /dev/null +++ b/py-utils/print.py @@ -0,0 +1,56 @@ +#!/usr/bin/python3 +import os +import sys + +import requests + + +def send_telegram_message(msg: str): + telegram_token = os.getenv("TELEGRAM_TOKEN", False) + if not telegram_token: + return + + data = { + "chat_id": telegram_token, + "parse_mode": "Markdown", + "text": msg, + } + response = requests.post( + f"https://api.telegram.org/{os.environ["TELEGRAM_TOKEN"]}/sendMessage", + data=data, + ) + + +def send_telegram_end(): + telegram_token = os.getenv("TELEGRAM_TOKEN", False) + if not telegram_token: + return + + data = { + "chat_id": telegram_token, + "parse_mode": "HTML", + "sticker": "CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE", + } + response = requests.post( + f"https://api.telegram.org/{os.environ["TELEGRAM_TOKEN"]}/sendMessage", + data=data, + ) + + +# Skeleton for printing to stdout +def print_success(msg): + print("\033[32m{}\033[00m".format(msg)) + send_telegram_message(msg) + + +def print_error(msg): + print("\033[31m{}\033[00m".format(msg)) + send_telegram_message(msg) + send_telegram_end() + + +if __name__ == "__main__": + if len(sys.argv) > 2: + globals()[sys.argv[1]](sys.argv[2]) + else: + globals()[sys.argv[1]]() diff --git a/scripts/print.sh b/scripts/print.sh index 572ddc3..7028e18 100644 --- a/scripts/print.sh +++ b/scripts/print.sh @@ -1,40 +1,12 @@ #!/bin/bash -GREEN='\033[0;32m' -RED='\033[0;31m' -NC='\033[0m' - -# Skeleton for posting to telegram -_telegram() { - if [[ -n "${TELEGRAM_TOKEN}" ]]; then - curl_cmd \ - --request POST https://api.telegram.org/bot"${TELEGRAM_TOKEN}"/sendMessage \ - --data chat_id="${TELEGRAM_CHAT}" \ - --data parse_mode='Markdown' \ - --data text="${1}" - fi -} - -_telegram_separator() { - if [[ -n "${TELEGRAM_TOKEN}" ]]; then - curl_cmd \ - --request POST https://api.telegram.org/bot"${TELEGRAM_TOKEN}"/sendSticker \ - --data chat_id="${TELEGRAM_CHAT}" \ - --data parse_mode='HTML' \ - --data sticker='CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE' - fi -} - -# Skelleton for printing to stdout +# Skeleton for printing to stdout _print_success() { - echo -e "${GREEN}$*${NC}" - _telegram "$*" + "${SCRIPT_DIR}"/print.py print_success "$*" } _print_error() { - echo -e "${RED}$*${NC}" - _telegram "$*" - _telegram_separator + "${SCRIPT_DIR}"/print.py print_error "$*" } @@ -95,13 +67,15 @@ _print_upload_fail() { _print_error 'Upload failed' } + # Ota _print_ota_fail() { _print_error 'Ota info failed' } +# End _print_done() { _print_success 'Completed successfully' - _telegram_separator + "${SCRIPT_DIR}"/print.py send_telegram_end } From a61f8199a237aa18cbad81fe89e0c50c9eadd04b Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 16 Feb 2026 15:18:18 +0100 Subject: [PATCH 27/64] chore: set up pre-commit --- .pre-commit-config.yaml | 35 +++++++++++++++++++++++++++++++++++ TODO.md | 1 - compose.yml => compose.yaml | 0 py-utils/json_arg_parser.py | 2 +- py-utils/print.py | 12 ++++++------ py-utils/xml_manifest_gen.py | 30 +++++++++++++++++++++--------- py-utils/xml_roomservice.py | 4 ++-- 7 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 .pre-commit-config.yaml rename compose.yml => compose.yaml (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..dda5ef8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +--- +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + exclude: | + (?x)( + README.md + )$ + - id: check-merge-conflict + - id: check-yaml + - id: check-ast + - id: detect-private-key + - id: end-of-file-fixer + + - repo: https://github.com/asottile/pyupgrade + rev: v3.21.2 + hooks: + - id: pyupgrade + args: [--py36-plus] + + - repo: https://github.com/psf/black + rev: 26.1.0 + hooks: + - id: black + language_version: python3.14 + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.1 + hooks: + # Run the linter. + - id: ruff-check + # Run the formatter. + - id: ruff-format diff --git a/TODO.md b/TODO.md index aea8b97..ad7e5e7 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,5 @@ - progress message telegram - incremental updates - move to py (apart from env vars?, devices as objects?) - - linting, pre-commit - rename files to indicate order - only log errors (docker/podman logs work otherwise) diff --git a/compose.yml b/compose.yaml similarity index 100% rename from compose.yml rename to compose.yaml diff --git a/py-utils/json_arg_parser.py b/py-utils/json_arg_parser.py index 2f6b283..5032229 100755 --- a/py-utils/json_arg_parser.py +++ b/py-utils/json_arg_parser.py @@ -19,5 +19,5 @@ def main() -> None: sys.exit(1) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/py-utils/print.py b/py-utils/print.py index 4d4b1f0..ee6ec4a 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -15,8 +15,8 @@ def send_telegram_message(msg: str): "parse_mode": "Markdown", "text": msg, } - response = requests.post( - f"https://api.telegram.org/{os.environ["TELEGRAM_TOKEN"]}/sendMessage", + requests.post( + f"https://api.telegram.org/{os.environ['TELEGRAM_TOKEN']}/sendMessage", data=data, ) @@ -31,20 +31,20 @@ def send_telegram_end(): "parse_mode": "HTML", "sticker": "CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE", } - response = requests.post( - f"https://api.telegram.org/{os.environ["TELEGRAM_TOKEN"]}/sendMessage", + requests.post( + f"https://api.telegram.org/{os.environ['TELEGRAM_TOKEN']}/sendMessage", data=data, ) # Skeleton for printing to stdout def print_success(msg): - print("\033[32m{}\033[00m".format(msg)) + print(f"\033[32m{msg}\033[00m") send_telegram_message(msg) def print_error(msg): - print("\033[31m{}\033[00m".format(msg)) + print(f"\033[31m{msg}\033[00m") send_telegram_message(msg) send_telegram_end() diff --git a/py-utils/xml_manifest_gen.py b/py-utils/xml_manifest_gen.py index 7003b70..be56c50 100755 --- a/py-utils/xml_manifest_gen.py +++ b/py-utils/xml_manifest_gen.py @@ -6,7 +6,12 @@ from urllib.request import urlopen, Request -def is_in_manifest(manifest: xml, project_path: str = "", project_remote: str = "", project_remove: str = "") -> bool: +def is_in_manifest( + manifest: xml, + project_path: str = "", + project_remote: str = "", + project_remove: str = "", +) -> bool: for manifest_project in manifest.findall("project"): if project_path == manifest_project.get("path"): return True @@ -22,8 +27,13 @@ def is_in_manifest(manifest: xml, project_path: str = "", project_remote: str = return False -def add_project_to_manifest(manifest: xml, project_name: str, project_path: str, project_remote: str = "", - project_revision: str = "") -> xml: +def add_project_to_manifest( + manifest: xml, + project_name: str, + project_path: str, + project_remote: str = "", + project_revision: str = "", +) -> xml: if is_in_manifest(manifest=manifest, project_path=project_path): return manifest @@ -44,6 +54,7 @@ def add_project_to_manifest(manifest: xml, project_name: str, project_path: str, manifest.append(element) return manifest + def add_project_remove_to_manifest(manifest: xml, project_remove_name: str) -> xml: if is_in_manifest(manifest=manifest, project_remove=project_remove_name): return manifest @@ -59,7 +70,9 @@ def add_project_remove_to_manifest(manifest: xml, project_remove_name: str) -> x return manifest -def add_remote_to_manifest(manifest: xml, remote_name: str, remote_fetch: str, remote_revision: str = "") -> xml: +def add_remote_to_manifest( + manifest: xml, remote_name: str, remote_fetch: str, remote_revision: str = "" +) -> xml: if is_in_manifest(manifest=manifest, project_remote=remote_name): return manifest @@ -89,13 +102,12 @@ def generate_manifest(local_manifest: xml, remote_manifest: xml) -> xml: manifest=local_manifest, remote_name=projects.get("name"), remote_fetch=projects.get("fetch"), - remote_revision=revision + remote_revision=revision, ) for projects in remote_manifest.findall("remove-project"): local_manifest = add_project_remove_to_manifest( - manifest=local_manifest, - project_remove_name=projects.get("name") + manifest=local_manifest, project_remove_name=projects.get("name") ) for projects in remote_manifest.findall("project"): @@ -114,7 +126,7 @@ def generate_manifest(local_manifest: xml, remote_manifest: xml) -> xml: project_name=projects.get("name"), project_path=projects.get("path"), project_remote=remote, - project_revision=revision + project_revision=revision, ) ElementTree.indent(local_manifest) @@ -135,5 +147,5 @@ def main() -> None: print(ElementTree.tostring(local_manifest).decode()) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/py-utils/xml_roomservice.py b/py-utils/xml_roomservice.py index e0469d3..e26b001 100755 --- a/py-utils/xml_roomservice.py +++ b/py-utils/xml_roomservice.py @@ -25,7 +25,7 @@ def fetch_device_vendor(local_manifest, remote_manifest, device: str) -> xml: project_name=projects.get("name"), project_path=projects.get("path"), project_remote=remote, - project_revision=revision + project_revision=revision, ) ElementTree.indent(local_manifest) @@ -49,5 +49,5 @@ def main() -> None: print(ElementTree.tostring(local_manifest).decode()) -if __name__ == '__main__': +if __name__ == "__main__": main() From c4f45a85243dd4dca86e1ed562fbccad3c69a64b Mon Sep 17 00:00:00 2001 From: sirrgb Date: Mon, 16 Feb 2026 16:45:26 +0100 Subject: [PATCH 28/64] chore: set up pre-commit action * https://github.com/pre-commit/action\?tab\=readme-ov-file\#using-this-action --- .github/workflows/pre-commit.yaml | 10 ++++++++++ .github/workflows/{shellcheck.yml => shellcheck.yaml} | 0 2 files changed, 10 insertions(+) create mode 100644 .github/workflows/pre-commit.yaml rename .github/workflows/{shellcheck.yml => shellcheck.yaml} (100%) diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..79cdce1 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,10 @@ +name: pre-commit +on: [push, pull_request] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yaml similarity index 100% rename from .github/workflows/shellcheck.yml rename to .github/workflows/shellcheck.yaml From 70a3ed8f51d5402ea0c4d036d862ec69064ce7be Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 2 Apr 2026 23:01:48 +0200 Subject: [PATCH 29/64] feat: run as host-user --- README.md | 55 ++-------------------------------------------------- compose.yaml | 23 ---------------------- dockdroid | 37 +++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 76 deletions(-) delete mode 100644 compose.yaml create mode 100644 dockdroid diff --git a/README.md b/README.md index 5ce7f35..99877e9 100644 --- a/README.md +++ b/README.md @@ -11,22 +11,13 @@ This project targets Android 7 up to the most recent version. ## Prerequisites - [Podman](https://podman.io/docs/installation) - - [Podman compose](https://github.com/containers/podman-compose?tab=readme-ov-file#generate-binary-using-dockerpodman-locally) + - podman-docker or alias - or [Docker](https://docs.docker.com/engine/install) - - [Docker Compose](https://docs.docker.com/compose/install) - - [Docker Rootless](https://docs.docker.com/engine/security/rootless) - [SSH](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) - [GitConfig](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) - ZRam (highly recommended): [Debian](https://wiki.debian.org/ZRam), [Fedora](https://github.com/systemd/zram-generator), [Ubuntu, Arch and others](https://wiki.archlinux.org/title/Zram) -### Setting up permissions - -First we need to find the UID, that is used for Docker/Podman. -For Debian, Ubuntu and Gentoo this seems to be 100999 and on Fedora 52587, -which should be $subUID+$containerUID-1 according to the [docker forums](https://forums.docker.com/t/map-more-uid-on-rootless-docker-and-mount-volume/102928/8). - - We need to manually create the required folders for the respective volumes ``` mkdir --parents ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys @@ -43,44 +34,6 @@ git clone https://github.com/SirRGB/dockdroid ~/docker_droid/minideb Then we need to chown that directory to the Docker user: -#### Debian/Ubuntu -``` -sudo chown --recursive 100999:"${UID}" ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys -``` - -#### Fedora -``` -sudo chown --recursive 52587:"${UID}" ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys -``` - -#### Other -(If you know a smarter way to do this please tell me, -I know the available subuids can be found with `grep ${USER} < /etc/subuid | cut --delimiter=':' --fields=2` -I just do not know if the container uid is predictable, -it seems to be 1000 for debian/ubuntu and 100 for fedora) - -Let other users read the directory -``` -sudo chmod --recursive 507 ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys -``` -Run the first docker build -``` -docker compose up --force-recreate --build -``` -Wait until it starts syncing and stop using ctrl + c -Find out the uid by running: -``` -ls --numeric-uid-gid ~/docker_droid/src/Los15/.repo -``` -Give ownership to the uid you found out: -(replace the 1st UID) -``` -sudo chown --recursive UID:"${UID}" ~/docker_droid/src ~/docker_droid/dotfiles ~/docker_droid/ccache ~/docker_droid/logs ~/docker_droid/keys -``` -And remove the incomplete sync -``` -sudo rm --recursive --force ~/docker_droid/src/Los15/ -``` @@ -166,11 +119,7 @@ OTA_REPO_URL=git@github.com:user/ota_config - After setting everything up you should do a test build with the default variables for testing. (Be sure to be in ~/docker_droid/minideb) ``` -podman compose up --force-recreate --build -``` -or -``` -docker compose up --force-recreate --build +bash dockdroid ``` diff --git a/compose.yaml b/compose.yaml deleted file mode 100644 index 82dd241..0000000 --- a/compose.yaml +++ /dev/null @@ -1,23 +0,0 @@ -services: - dockdroid: - build: . - volumes: - #RW - # ROM source - - ~/docker_droid/src:/droid_workdir/src - # Log files - - ~/docker_droid/logs:/droid_workdir/logs - # CCache to speed up builds - - ~/docker_droid/ccache:/mnt/ccache - # Keys for signing - - ~/docker_droid/keys:/droid_workdir/keys - #RO - # Gitconfig for repo - - ~/docker_droid/dotfiles/.gitconfig:/droid_workdir/.gitconfig:ro - # SSH keys for git authentification - - ~/docker_droid/dotfiles/.ssh:/droid_workdir/.ssh:ro - env_file: - - path: ./target.env - required: true - - path: ./config.env - required: false diff --git a/dockdroid b/dockdroid new file mode 100644 index 0000000..a8d48d0 --- /dev/null +++ b/dockdroid @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -euo pipefail +set -x + +_build() { + docker build --tag localhost/sirrgb/dockdroid:latest . +} + +_args() { + #local volumes + volumes=( + -v ~/docker_droid/src:/droid_workdir/src + -v ~/docker_droid/logs:/droid_workdir/logs + -v ~/docker_droid/ccache:/mnt/ccache + -v ~/docker_droid/keys:/droid_workdir/keys + -v ~/docker_droid/dotfiles/.gitconfig:/droid_workdir/.gitconfig:ro + -v ~/docker_droid/dotfiles/.ssh:/droid_workdir/.ssh:ro + ) + # TODO >1 env-file + env_file=~/docker_droid/minideb/target.env + # "${@}" + + if which podman; then + args="--userns=keep-id" + else + args=("--user" "${UID}":"${GID}") + fi +} + +_run() { + docker run "${volumes[@]}" --env-file "${env_file}" "${args[@]}" localhost/sirrgb/dockdroid:latest +} + +_build +_args +_run From ecf5156e533bc5f14e4d6ef7c11ec9dca03c680c Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 4 Jun 2026 22:19:10 +0200 Subject: [PATCH 30/64] fix: adapt upload to gh api changes --- scripts/upload.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/upload.sh b/scripts/upload.sh index 9ed6017..b51eb1e 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -31,8 +31,9 @@ _upload_gh() { # Create a release and get url upload_url=$(curl_cmd \ + --url "https://api.github.com/octocat" \ --request POST \ - --header "Authorization: token ${GITHUB_TOKEN}" \ + --header "Authorization: Bearer ${GITHUB_TOKEN}" \ --header 'content-type: application/json' \ https://api.github.com/repos/"${release_repo}"/releases \ --data "{ \"tag_name\": \"${tag}\", \"body\": \"${desc}\" }" \ From 3e41f89a66be743451a844eec949b97a0a05cf68 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 6 Apr 2026 23:29:40 +0200 Subject: [PATCH 31/64] feat: enable bl relock * if you set up your dt like this: https://review.lineageos.org/c/LineageOS/android_device_google_gs101/+/483174 you can use ROM_BUILD_FLAGS=AVB_CUSTOM_KEY_PATH="${KEYS_DIR}",AVB_CUSTOM_ALGORITHM=RSA4096 to set up signing like intended --- Dockerfile | 1 + README.md | 1 + scripts/packaging.sh | 5 +++++ scripts/setup.sh | 9 +++++++++ scripts/sign.sh | 10 +++++++--- scripts/upload.sh | 16 ++++++++++++++++ 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index f8aad05..18e43b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,7 @@ ENV BUILD_TYPE='' ENV ROM_MANIFEST='' ENV ROM_BRANCH='' ENV ROM_BUILD_FLAGS='' +ENV BL_RELOCK='' # Fallbacks (required for non-standard naming and conflicts) ENV LUNCH_PREFIX_FALLBACK='' diff --git a/README.md b/README.md index 99877e9..267e206 100644 --- a/README.md +++ b/README.md @@ -151,3 +151,4 @@ You can further speed up build times by using tmpfs as described [here](https:// - [LineageOS4MicroG](https://github.com/lineageos4microg/docker-lineage-cicd) - [amyROM](https://github.com/amyROM/vendor_amy/blob/207d5e32c3fba38b9fe1ab9cd12c71ca6b81d653/scripts/generate_json_build_info.sh) - [LineageOS Infra](https://github.com/lineageos-infra/build-config/tree/main/android) +- [Halogen OS](https://github.com/halogenOS/android_external_xos/blob/fb9a58362b930807766100d1288ff809df6b7c51/xostools/xostools.sh) diff --git a/scripts/packaging.sh b/scripts/packaging.sh index a7cb12a..7136e30 100644 --- a/scripts/packaging.sh +++ b/scripts/packaging.sh @@ -52,6 +52,11 @@ _packaging() { then _cleanup_fail fi + + # Extract AVB key + if [[ -n "${BL_RELOCK}" ]]; then + avbtool extract_public_key --key "${KEYS_DIR}"/avbkey_4096.pem --output "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" + fi set -eu } diff --git a/scripts/setup.sh b/scripts/setup.sh index cf3d9d6..4f3e575 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -100,6 +100,15 @@ _keysgen() { openssl pkcs8 -in "${KEYS_DIR}"/"${apex}".pk8 -inform DER -nocrypt -out "${KEYS_DIR}"/"${apex}".pem fi done + + if [[ -n "${BL_RELOCK}" ]]; then + if [[ ! -f "${KEYS_DIR}"/avbkey_4096.x509.pem ]] || [[ ! -f "${KEYS_DIR}"/avbkey_4096.pem ]] ; then + subject="${KEYS_SUBJECT//CN=Android/CN=\$\{apex\}}" + make_key "${KEYS_DIR}"/avbkey_4096 "${subject}" + openssl pkcs8 -in "${KEYS_DIR}"/avbkey_4096.pk8 -inform DER -nocrypt -out "${KEYS_DIR}"/avbkey_4096.pem + fi + fi + unset KEYS_SUBJECT } diff --git a/scripts/sign.sh b/scripts/sign.sh index ee5150d..944738e 100644 --- a/scripts/sign.sh +++ b/scripts/sign.sh @@ -55,11 +55,15 @@ _sign_old() { # New signing process (APEX), A12/up _sign_new() { - local apex_args + local sign_args for apex_key in "${APEX_KEYS[@]}"; do - apex_args+=('--extra_apks' "${apex_key}.apex=${KEYS_DIR}/${apex_key}" '--extra_apex_payload_key' "${apex_key}.apex=${KEYS_DIR}/${apex_key}.pem") + sign_args+=('--extra_apks' "${apex_key}.apex=${KEYS_DIR}/${apex_key}" '--extra_apex_payload_key' "${apex_key}.apex=${KEYS_DIR}/${apex_key}.pem") done + if [[ -n "${BL_RELOCK}" ]]; then + sign_args+=('--avb_vbmeta_key' "${KEYS_DIR}"/avbkey_4096.pem '--avb_vbmeta_algorithm' 'SHA256_RSA4096') + fi + set +eu if ! sign_target_files_apks -o -d "${KEYS_DIR}" \ --extra_apks AdServicesApk.apk="${KEYS_DIR}"/releasekey \ @@ -73,7 +77,7 @@ _sign_new() { --extra_apks ServiceUwbResources.apk="${KEYS_DIR}"/releasekey \ --extra_apks ServiceWifiResources.apk="${KEYS_DIR}"/releasekey \ --extra_apks WifiDialog.apk="${KEYS_DIR}"/releasekey \ - "${apex_args[@]}" \ + "${sign_args[@]}" \ "${OUT}"/obj/PACKAGING/target_files_intermediates/*-target_files*.zip \ "${OUT}"/signed-target_files.zip 2>&1 | tee --append "${LOGS_DIR}"/"${BUILD_DATE}"/sign.txt then diff --git a/scripts/upload.sh b/scripts/upload.sh index b51eb1e..a61b8e6 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -58,11 +58,27 @@ _upload_gh() { --header "Content-Type: $(file -b --mime-type "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}")" \ --upload-file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" \ "${upload_url}"?name="${PACKAGE_NAME//.zip/-recovery.img}" + + + # Upload Recovery + if [[ -n "${BL_RELOCK}" ]]; then + curl_cmd \ + --header 'Accept: application/vnd.github.v3+json' \ + --header "Content-Length: $(stat -c%s "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}")" \ + --header "Authorization: token ${GITHUB_TOKEN}" \ + --header "Content-Type: $(file -b --mime-type "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}")" \ + --upload-file "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" \ + "${upload_url}"?name="${PACKAGE_NAME//.zip/-pkmd.bin}" + fi } _upload_ssh() { scp "${OUT}"/"${PACKAGE_NAME}" "${1}"@"${2}" scp "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" "${1}"@"${2}" + if [[ -n "${BL_RELOCK}" ]]; then + scp "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" "${1}"@"${2}" + fi + DL_OTA_URL="${3}" } From 4e09b256ca8076b19c72571491f97a3885c9b931 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Fri, 12 Jun 2026 18:34:07 +0200 Subject: [PATCH 32/64] chore: do not cache base image builds --- base/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/Makefile b/base/Makefile index 5c160a5..897c72b 100644 --- a/base/Makefile +++ b/base/Makefile @@ -4,7 +4,7 @@ user ?= sirrgb registry ?= docker.io build: - docker build . --tag $(registry)/$(user)/dockdroid-base:latest + docker build . --tag $(registry)/$(user)/dockdroid-base:latest --no-cache run: docker run --interactive --tty $(registry)/$(user)/dockdroid-base:latest From 734dd4e1ff5ef13cf0543f664f1abe59b1d72912 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sat, 13 Jun 2026 22:34:08 +0200 Subject: [PATCH 33/64] fix: guard muppets vendor fetching --- Dockerfile | 1 + scripts/sync.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 18e43b1..d0702c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,7 @@ ENV ROM_MANIFEST='' ENV ROM_BRANCH='' ENV ROM_BUILD_FLAGS='' ENV BL_RELOCK='' +ENV FETCH_MUPPETS='' # Fallbacks (required for non-standard naming and conflicts) ENV LUNCH_PREFIX_FALLBACK='' diff --git a/scripts/sync.sh b/scripts/sync.sh index b42a686..c973a4c 100644 --- a/scripts/sync.sh +++ b/scripts/sync.sh @@ -23,7 +23,7 @@ _sync() { else curl_cmd "${LOCAL_MANIFEST}" --output "${ROM_DIR}"/.repo/local_manifests/manifest.xml fi - elif [[ -z "${CLONE_REPOS}" ]]; then + elif [[ -z "${CLONE_REPOS}" ]] && [[ -n "${FETCH_MUPPETS}" ]]; then # Generate vendor manifest, so that official lineage just builds "${SCRIPT_DIR}"/xml_roomservice.py "${DEVICE}" "${ROM_BRANCH}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml fi From bbb8479840750c27d31dd187c7b74361f3e1b2a0 Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Sat, 11 Jul 2026 20:34:31 +0200 Subject: [PATCH 34/64] chore: update keys list for 17 --- scripts/setup.sh | 4 +++- scripts/sign.sh | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/setup.sh b/scripts/setup.sh index 4f3e575..be493a8 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -25,7 +25,6 @@ _keysgen() { com.android.adservices com.android.adservices.api com.android.appsearch - com.android.appsearch.apk com.android.art com.android.bluetooth com.android.bt @@ -65,6 +64,7 @@ _keysgen() { com.android.networkstack.tethering com.android.neuralnetworks com.android.nfcservices + com.android.npumanager com.android.ondevicepersonalization com.android.os.statsd com.android.permission @@ -86,6 +86,8 @@ _keysgen() { com.android.uwb.resources com.android.virt com.android.vndk.current + com.android.vndk.current.on_vendor + com.android.webapp com.android.wifi com.android.wifi.dialog com.android.wifi.resources diff --git a/scripts/sign.sh b/scripts/sign.sh index 944738e..816d98a 100644 --- a/scripts/sign.sh +++ b/scripts/sign.sh @@ -66,6 +66,7 @@ _sign_new() { set +eu if ! sign_target_files_apks -o -d "${KEYS_DIR}" \ + --extra_apks com.android.appsearch.apk="${KEYS_DIR}"/releasekey \ --extra_apks AdServicesApk.apk="${KEYS_DIR}"/releasekey \ --extra_apks FederatedCompute.apk="${KEYS_DIR}"/releasekey \ --extra_apks HalfSheetUX.apk="${KEYS_DIR}"/releasekey \ @@ -76,6 +77,9 @@ _sign_new() { --extra_apks ServiceConnectivityResources.apk="${KEYS_DIR}"/releasekey \ --extra_apks ServiceUwbResources.apk="${KEYS_DIR}"/releasekey \ --extra_apks ServiceWifiResources.apk="${KEYS_DIR}"/releasekey \ + --extra_apks TelecomServiceResources.apk="${KEYS_DIR}"/releasekey \ + --extra_apks TelecomUi.apk="${KEYS_DIR}"/releasekey \ + --extra_apks WebAppService.apk="${KEYS_DIR}"/releasekey \ --extra_apks WifiDialog.apk="${KEYS_DIR}"/releasekey \ "${sign_args[@]}" \ "${OUT}"/obj/PACKAGING/target_files_intermediates/*-target_files*.zip \ From 63fe83979f1d6b1d4c9a80082bd88a310dd78e33 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 14 Jun 2026 18:24:55 +0200 Subject: [PATCH 35/64] Revert "fix: adapt upload to gh api changes" This reverts commit ecf5156e533bc5f14e4d6ef7c11ec9dca03c680c. --- scripts/upload.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/upload.sh b/scripts/upload.sh index a61b8e6..0e5c4e9 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -31,9 +31,8 @@ _upload_gh() { # Create a release and get url upload_url=$(curl_cmd \ - --url "https://api.github.com/octocat" \ --request POST \ - --header "Authorization: Bearer ${GITHUB_TOKEN}" \ + --header "Authorization: token ${GITHUB_TOKEN}" \ --header 'content-type: application/json' \ https://api.github.com/repos/"${release_repo}"/releases \ --data "{ \"tag_name\": \"${tag}\", \"body\": \"${desc}\" }" \ From c77f1a56bcf119762acf23091bdc43150f94a599 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 30 Jul 2026 22:42:41 +0200 Subject: [PATCH 36/64] chore: move gh upload to py chore: fix linter style issues --- .pre-commit-config.yaml | 6 +-- py-utils/create_github_release.py | 45 ++++++++++++++++++++++ py-utils/print.py | 5 ++- py-utils/upload_github.py | 64 +++++++++++++++++++++++++++++++ py-utils/xml_manifest_gen.py | 8 ++-- py-utils/xml_roomservice.py | 7 ++-- scripts/upload.sh | 31 +++------------ 7 files changed, 129 insertions(+), 37 deletions(-) create mode 100755 py-utils/create_github_release.py create mode 100755 py-utils/upload_github.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dda5ef8..3376520 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,13 +21,13 @@ repos: args: [--py36-plus] - repo: https://github.com/psf/black - rev: 26.1.0 + rev: 26.5.1 hooks: - id: black - language_version: python3.14 + language_version: python3.12 - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.1 + rev: v0.16.5 hooks: # Run the linter. - id: ruff-check diff --git a/py-utils/create_github_release.py b/py-utils/create_github_release.py new file mode 100755 index 0000000..39a92a1 --- /dev/null +++ b/py-utils/create_github_release.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 + +import argparse +import sys + +import requests + + +def arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("-r", "--repo", required=True) + parser.add_argument("-t", "--token", required=True) + parser.add_argument("-n", "--name", required=True) + parser.add_argument("-d", "--desc", required=True) + return parser.parse_args() + + +def create_release(args: argparse.Namespace) -> None: + headers = { + "Accept": "application/vnd.github+json", + "Authorization": "Token " + args.token, + "X-GitHub-Api-Version": "2026-03-10", + } + + headers.update({"Content-Type": "application/x-www-form-urlencoded"}) + data = '{ "tag_name": "' + args.name + '", "body": "' + args.desc + '" }' + + release_repo = args.repo.strip("\"'") + try: + response = requests.post( + "https://api.github.com/repos/" + release_repo + "/releases", + headers=headers, + data=data, + ) + response.raise_for_status() + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) + + print(response.json()["upload_url"].split("{")[0]) + + +if __name__ == "__main__": + create_release(arguments()) diff --git a/py-utils/print.py b/py-utils/print.py index ee6ec4a..e858011 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 + import os import sys @@ -6,7 +7,7 @@ def send_telegram_message(msg: str): - telegram_token = os.getenv("TELEGRAM_TOKEN", False) + telegram_token = os.getenv("TELEGRAM_TOKEN", "") if not telegram_token: return @@ -22,7 +23,7 @@ def send_telegram_message(msg: str): def send_telegram_end(): - telegram_token = os.getenv("TELEGRAM_TOKEN", False) + telegram_token = os.getenv("TELEGRAM_TOKEN", "") if not telegram_token: return diff --git a/py-utils/upload_github.py b/py-utils/upload_github.py new file mode 100755 index 0000000..a98451b --- /dev/null +++ b/py-utils/upload_github.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +import argparse +import json +import subprocess +import sys + +import requests + + +def arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("-u", "--url", required=True) + parser.add_argument("-t", "--token", required=True) + parser.add_argument("-f", "--file", required=True) + return parser.parse_args() + + +def upload_file(args: argparse.Namespace) -> None: + file_size = subprocess.run( + "stat -c%s " + args.file, shell=True, check=True, capture_output=True, text=True + ).stdout + file_type = subprocess.run( + "file -b --mime-type " + args.file, + shell=True, + check=True, + capture_output=True, + text=True, + ).stdout.strip() + + headers = { + "Accept": "application/vnd.github+json", + "Authorization": "Token " + args.token, + "X-GitHub-Api-Version": "2026-03-10", + "Content-Length": file_size, + "Content-Type": file_type, + } + + with open(args.file, "rb") as f: + data = {"files": f.read} + + params = { + "name": args.file.split("/")[-1], + } + + try: + response = requests.put( + args.url + "?name=" + args.file.split("/")[-1], + params=params, + headers=headers, + data=data, + ) + + print(args.url + "?name=" + args.file.split("/")[-1]) + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) + + print(json.loads(response.content)["browser_download_url"]) + + +if __name__ == "__main__": + upload_file(arguments()) diff --git a/py-utils/xml_manifest_gen.py b/py-utils/xml_manifest_gen.py index be56c50..74bce1f 100755 --- a/py-utils/xml_manifest_gen.py +++ b/py-utils/xml_manifest_gen.py @@ -1,9 +1,9 @@ #!/usr/bin/python3 +import sys import xml +from urllib.request import Request, urlopen from xml.etree import ElementTree -import sys -from urllib.request import urlopen, Request def is_in_manifest( @@ -137,8 +137,8 @@ def main() -> None: local_manifest = ElementTree.Element("manifest") for urls in sys.argv[1].split(","): - request = Request(urls, headers={"User-Agent": "Mozilla/5.0"}) - source_manifest = urlopen(request).read() + request = Request(urls) + source_manifest = urlopen(request, timeout=5).read() remote_manifest = ElementTree.fromstring(source_manifest) local_manifest = generate_manifest(local_manifest, remote_manifest) diff --git a/py-utils/xml_roomservice.py b/py-utils/xml_roomservice.py index e26b001..21a8f92 100755 --- a/py-utils/xml_roomservice.py +++ b/py-utils/xml_roomservice.py @@ -1,10 +1,11 @@ #!/usr/bin/python3 +import sys import xml -import xml_manifest_gen +from urllib.request import Request, urlopen from xml.etree import ElementTree -import sys -from urllib.request import urlopen, Request + +import xml_manifest_gen def fetch_device_vendor(local_manifest, remote_manifest, device: str) -> xml: diff --git a/scripts/upload.sh b/scripts/upload.sh index 0e5c4e9..3a730cb 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -30,34 +30,15 @@ _upload_gh() { release_repo="${OTA_REPO_URL//git@github.com:/}" # Create a release and get url - upload_url=$(curl_cmd \ - --request POST \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header 'content-type: application/json' \ - https://api.github.com/repos/"${release_repo}"/releases \ - --data "{ \"tag_name\": \"${tag}\", \"body\": \"${desc}\" }" \ - | tr --delete '\n' | "${SCRIPT_DIR}"/json_arg_parser.py "upload_url" \ - | cut --delimiter='{' --fields=1) + upload_url=$( + "${SCRIPT_DIR}"/create_github_release.py --repo "${release_repo}" --token "${GITHUB_TOKEN}" --name "${tag}" --desc "${desc}" + ) # Upload ROM - DL_OTA_URL=$(curl_cmd \ - --header 'Accept: application/vnd.github.v3+json' \ - --header "Content-Length: $(stat -c%s "${OUT}"/"${PACKAGE_NAME}")" \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header "Content-Type: $(file -b --mime-type "${OUT}"/"${PACKAGE_NAME}")" \ - --upload-file "${OUT}"/"${PACKAGE_NAME}" \ - "${upload_url}"?name="${PACKAGE_NAME}" \ - | tr --delete '\n' | "${SCRIPT_DIR}"/json_arg_parser.py "browser_download_url") + DL_OTA_URL=$("${SCRIPT_DIR}"/upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME}") # Upload Recovery - curl_cmd \ - --header 'Accept: application/vnd.github.v3+json' \ - --header "Content-Length: $(stat -c%s "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}")" \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header "Content-Type: $(file -b --mime-type "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}")" \ - --upload-file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" \ - "${upload_url}"?name="${PACKAGE_NAME//.zip/-recovery.img}" - + "${SCRIPT_DIR}"/upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" # Upload Recovery if [[ -n "${BL_RELOCK}" ]]; then @@ -78,7 +59,7 @@ _upload_ssh() { scp "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" "${1}"@"${2}" fi - DL_OTA_URL="${3}" + export DL_OTA_URL="${3}" } # Upload to SourceForge From c0acf2d636b883d38506159a6da7e1cbde5ac265 Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Sun, 16 Aug 2026 16:31:59 +0200 Subject: [PATCH 37/64] chore: Add com.android.hardware.drm.clearkey key Change-Id: I73d3fc7e4cdf2e25791cad73878eda57e5845345 --- scripts/setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/setup.sh b/scripts/setup.sh index be493a8..5231f26 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -43,6 +43,7 @@ _keysgen() { com.android.hardware.boot com.android.hardware.cas com.android.hardware.contexthub + com.android.hardware.drm.clearkey com.android.hardware.dumpstate com.android.hardware.gatekeeper.nonsecure com.android.hardware.neuralnetworks From 1f4fd2661c19d2b7a285790f29c8a2a585e48e3e Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 13:23:59 +0200 Subject: [PATCH 38/64] chore: use argparse for telegram --- py-utils/print.py | 33 ++++++++++++++++++++++++--------- scripts/print.sh | 6 +++--- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/py-utils/print.py b/py-utils/print.py index e858011..4cb5bf4 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -1,12 +1,30 @@ #!/usr/bin/python3 +import argparse import os -import sys import requests -def send_telegram_message(msg: str): +def arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("-a", "--action", required=True) + parser.add_argument("-m", "--message") + + return parser.parse_args() + + +def eval_arg(args: argparse.Namespace) -> None: + match args.action: + case "print_success": + print_success(args.message) + case "print_error": + print_error(args.message) + case "send_telegram_end": + send_telegram_end() + + +def send_telegram_message(msg: str) -> None: telegram_token = os.getenv("TELEGRAM_TOKEN", "") if not telegram_token: return @@ -22,7 +40,7 @@ def send_telegram_message(msg: str): ) -def send_telegram_end(): +def send_telegram_end() -> None: telegram_token = os.getenv("TELEGRAM_TOKEN", "") if not telegram_token: return @@ -39,19 +57,16 @@ def send_telegram_end(): # Skeleton for printing to stdout -def print_success(msg): +def print_success(msg) -> None: print(f"\033[32m{msg}\033[00m") send_telegram_message(msg) -def print_error(msg): +def print_error(msg) -> None: print(f"\033[31m{msg}\033[00m") send_telegram_message(msg) send_telegram_end() if __name__ == "__main__": - if len(sys.argv) > 2: - globals()[sys.argv[1]](sys.argv[2]) - else: - globals()[sys.argv[1]]() + eval_arg(arguments()) diff --git a/scripts/print.sh b/scripts/print.sh index 7028e18..b0f5173 100644 --- a/scripts/print.sh +++ b/scripts/print.sh @@ -2,11 +2,11 @@ # Skeleton for printing to stdout _print_success() { - "${SCRIPT_DIR}"/print.py print_success "$*" + "${SCRIPT_DIR}"/print.py -a print_success -m "$*" } _print_error() { - "${SCRIPT_DIR}"/print.py print_error "$*" + "${SCRIPT_DIR}"/print.py -a print_error -m "$*" } @@ -77,5 +77,5 @@ _print_ota_fail() { # End _print_done() { _print_success 'Completed successfully' - "${SCRIPT_DIR}"/print.py send_telegram_end + "${SCRIPT_DIR}"/print.py -a send_telegram_end } From 0d119ac1e8623a2c2e2ca4f9d7bddcc7a7519e75 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 13:52:13 +0200 Subject: [PATCH 39/64] feat: allow specifying another env file --- dockdroid | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/dockdroid b/dockdroid index a8d48d0..5a99218 100644 --- a/dockdroid +++ b/dockdroid @@ -3,11 +3,26 @@ set -euo pipefail set -x +config="" +case "${1}" in + "--config" | "-c") + config=${2} + ;; + *) + ;; +esac + _build() { docker build --tag localhost/sirrgb/dockdroid:latest . } _args() { + if which podman; then + args=("--userns=keep-id") + else + args=("--user" "${UID}":"${GID}") + fi + #local volumes volumes=( -v ~/docker_droid/src:/droid_workdir/src @@ -17,14 +32,10 @@ _args() { -v ~/docker_droid/dotfiles/.gitconfig:/droid_workdir/.gitconfig:ro -v ~/docker_droid/dotfiles/.ssh:/droid_workdir/.ssh:ro ) - # TODO >1 env-file - env_file=~/docker_droid/minideb/target.env - # "${@}" - if which podman; then - args="--userns=keep-id" - else - args=("--user" "${UID}":"${GID}") + env_file=~/docker_droid/minideb/target.en + if [[ -n "${config}" ]]; then + args=("${args[@]}" "--env-file" "${config}") fi } From 092cfa070638b9c164cf5bb02f8bce751e36ef41 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 14:26:29 +0200 Subject: [PATCH 40/64] chore: rename files for ordering * py imports cant start with number --- Dockerfile | 2 +- TODO.md | 1 - py-utils/{xml_roomservice.py => 01_xml_roomservice.py} | 4 ++-- py-utils/{json_arg_parser.py => 03_json_arg_parser.py} | 0 ...eate_github_release.py => 07_create_github_release.py} | 0 py-utils/{upload_github.py => 07_upload_github.py} | 0 py-utils/{xml_manifest_gen.py => _01_xml_manifest_gen.py} | 0 scripts/{init.sh => 00_init.sh} | 4 ++-- scripts/{sync.sh => 01_sync.sh} | 6 +++--- scripts/{setup.sh => 02_setup.sh} | 8 ++++---- scripts/{compat.sh => 03_compat.sh} | 2 +- scripts/{lunch.sh => 04_lunch.sh} | 2 +- scripts/{sign.sh => 05_sign.sh} | 2 +- scripts/{packaging.sh => 06_packaging.sh} | 4 ++-- scripts/{upload.sh => 07_upload.sh} | 8 ++++---- scripts/{ota.sh => 08_ota.sh} | 0 16 files changed, 21 insertions(+), 22 deletions(-) rename py-utils/{xml_roomservice.py => 01_xml_roomservice.py} (93%) rename py-utils/{json_arg_parser.py => 03_json_arg_parser.py} (100%) rename py-utils/{create_github_release.py => 07_create_github_release.py} (100%) rename py-utils/{upload_github.py => 07_upload_github.py} (100%) rename py-utils/{xml_manifest_gen.py => _01_xml_manifest_gen.py} (100%) rename scripts/{init.sh => 00_init.sh} (82%) rename scripts/{sync.sh => 01_sync.sh} (93%) rename scripts/{setup.sh => 02_setup.sh} (96%) rename scripts/{compat.sh => 03_compat.sh} (96%) rename scripts/{lunch.sh => 04_lunch.sh} (96%) rename scripts/{sign.sh => 05_sign.sh} (98%) rename scripts/{packaging.sh => 06_packaging.sh} (97%) rename scripts/{upload.sh => 07_upload.sh} (84%) rename scripts/{ota.sh => 08_ota.sh} (100%) diff --git a/Dockerfile b/Dockerfile index d0702c0..8fcfcc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -64,4 +64,4 @@ ENV SSH_USER='' ENV SSH_UPLOAD_URL='' ENV SSH_DOWNLOAD_URL='' -ENTRYPOINT ["/bin/bash", "-c", "${SCRIPT_DIR}/init.sh"] +ENTRYPOINT ["/bin/bash", "-c", "${SCRIPT_DIR}/00_init.sh"] diff --git a/TODO.md b/TODO.md index ad7e5e7..7c3f648 100644 --- a/TODO.md +++ b/TODO.md @@ -5,5 +5,4 @@ - progress message telegram - incremental updates - move to py (apart from env vars?, devices as objects?) -- rename files to indicate order - only log errors (docker/podman logs work otherwise) diff --git a/py-utils/xml_roomservice.py b/py-utils/01_xml_roomservice.py similarity index 93% rename from py-utils/xml_roomservice.py rename to py-utils/01_xml_roomservice.py index 21a8f92..b9aa28d 100755 --- a/py-utils/xml_roomservice.py +++ b/py-utils/01_xml_roomservice.py @@ -5,7 +5,7 @@ from urllib.request import Request, urlopen from xml.etree import ElementTree -import xml_manifest_gen +import _01_xml_manifest_gen def fetch_device_vendor(local_manifest, remote_manifest, device: str) -> xml: @@ -21,7 +21,7 @@ def fetch_device_vendor(local_manifest, remote_manifest, device: str) -> xml: else: revision = projects.get("revision") - local_manifest = xml_manifest_gen.add_project_to_manifest( + local_manifest = _01_xml_manifest_gen.add_project_to_manifest( manifest=local_manifest, project_name=projects.get("name"), project_path=projects.get("path"), diff --git a/py-utils/json_arg_parser.py b/py-utils/03_json_arg_parser.py similarity index 100% rename from py-utils/json_arg_parser.py rename to py-utils/03_json_arg_parser.py diff --git a/py-utils/create_github_release.py b/py-utils/07_create_github_release.py similarity index 100% rename from py-utils/create_github_release.py rename to py-utils/07_create_github_release.py diff --git a/py-utils/upload_github.py b/py-utils/07_upload_github.py similarity index 100% rename from py-utils/upload_github.py rename to py-utils/07_upload_github.py diff --git a/py-utils/xml_manifest_gen.py b/py-utils/_01_xml_manifest_gen.py similarity index 100% rename from py-utils/xml_manifest_gen.py rename to py-utils/_01_xml_manifest_gen.py diff --git a/scripts/init.sh b/scripts/00_init.sh similarity index 82% rename from scripts/init.sh rename to scripts/00_init.sh index 75590f8..d184eae 100644 --- a/scripts/init.sh +++ b/scripts/00_init.sh @@ -13,5 +13,5 @@ BUILD_DATE=$(env TZ="${TIME_ZONE}" date --date=@"${BUILD_DATE_UNIX}" '+%Y%m%d-%H mkdir "${LOGS_DIR}"/"${BUILD_DATE}" unset BIN_DIR -# shellcheck source=scripts/sync.sh -source "${SCRIPT_DIR}"/sync.sh +# shellcheck source=scripts/01_sync.sh +source "${SCRIPT_DIR}"/01_sync.sh diff --git a/scripts/sync.sh b/scripts/01_sync.sh similarity index 93% rename from scripts/sync.sh rename to scripts/01_sync.sh index c973a4c..5d61127 100644 --- a/scripts/sync.sh +++ b/scripts/01_sync.sh @@ -19,13 +19,13 @@ _sync() { if [[ -n "${LOCAL_MANIFEST}" ]]; then if grep -q ',' <<< "${LOCAL_MANIFEST}"; then # Merge local manifests into one to avoid conflicts with duplicate dependencies - "${SCRIPT_DIR}"/xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml + "${SCRIPT_DIR}"/_01_xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml else curl_cmd "${LOCAL_MANIFEST}" --output "${ROM_DIR}"/.repo/local_manifests/manifest.xml fi elif [[ -z "${CLONE_REPOS}" ]] && [[ -n "${FETCH_MUPPETS}" ]]; then # Generate vendor manifest, so that official lineage just builds - "${SCRIPT_DIR}"/xml_roomservice.py "${DEVICE}" "${ROM_BRANCH}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml + "${SCRIPT_DIR}"/01_xml_roomservice.py "${DEVICE}" "${ROM_BRANCH}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml fi local threads threads=$(nproc) @@ -97,4 +97,4 @@ _print_sync_start _sync _print_sync_success -source "${SCRIPT_DIR}"/setup.sh +source "${SCRIPT_DIR}"/02_setup.sh diff --git a/scripts/setup.sh b/scripts/02_setup.sh similarity index 96% rename from scripts/setup.sh rename to scripts/02_setup.sh index 5231f26..63baa39 100644 --- a/scripts/setup.sh +++ b/scripts/02_setup.sh @@ -148,10 +148,10 @@ _repopick() { _ccache _keysgen _get_android_version -# shellcheck source=scripts/compat.sh -source "${SCRIPT_DIR}"/compat.sh +# shellcheck source=scripts/03_compat.sh +source "${SCRIPT_DIR}"/03_compat.sh _run_envsetup _repopick -# shellcheck source=scripts/lunch.sh -source "${SCRIPT_DIR}"/lunch.sh +# shellcheck source=scripts/04_lunch.sh +source "${SCRIPT_DIR}"/04_lunch.sh diff --git a/scripts/compat.sh b/scripts/03_compat.sh similarity index 96% rename from scripts/compat.sh rename to scripts/03_compat.sh index 95f2044..334a211 100644 --- a/scripts/compat.sh +++ b/scripts/03_compat.sh @@ -25,7 +25,7 @@ _setup_jdk8() { --header 'Accept: application/vnd.github+json' \ --header 'X-GitHub-Api-Version: 2022-11-28' \ https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest \ - | tr --delete '\n' | "${SCRIPT_DIR}"/json_arg_parser.py "tag_name") + | tr --delete '\n' | "${SCRIPT_DIR}"/03_json_arg_parser.py "tag_name") jdk_name=OpenJDK8U-jdk_x64_linux_hotspot_$(tr --delete '-' <<< "${jdk_tag//jdk/}").tar.gz mkdir --parents "${jdk_dir}" curl_cmd --remote-name https://github.com/adoptium/temurin8-binaries/releases/download/"${jdk_tag}"/"${jdk_name}" --output-dir "${jdk_dir}" diff --git a/scripts/lunch.sh b/scripts/04_lunch.sh similarity index 96% rename from scripts/lunch.sh rename to scripts/04_lunch.sh index ca40fed..6fcdabf 100644 --- a/scripts/lunch.sh +++ b/scripts/04_lunch.sh @@ -38,5 +38,5 @@ for device in "${DEVICE[@]}"; do _lunch _print_build_start - source "${SCRIPT_DIR}"/sign.sh + source "${SCRIPT_DIR}"/05_sign.sh done diff --git a/scripts/sign.sh b/scripts/05_sign.sh similarity index 98% rename from scripts/sign.sh rename to scripts/05_sign.sh index 816d98a..014b772 100644 --- a/scripts/sign.sh +++ b/scripts/05_sign.sh @@ -106,5 +106,5 @@ if [[ -n "${ROM_BUILD_FLAGS}" ]]; then done else _determine_signing - source "${SCRIPT_DIR}"/packaging.sh + source "${SCRIPT_DIR}"/06_packaging.sh fi diff --git a/scripts/packaging.sh b/scripts/06_packaging.sh similarity index 97% rename from scripts/packaging.sh rename to scripts/06_packaging.sh index 7136e30..a1d55d7 100644 --- a/scripts/packaging.sh +++ b/scripts/06_packaging.sh @@ -75,5 +75,5 @@ _packaging _extract_recovery _print_build_success -# shellcheck source=scripts/upload.sh -source "${SCRIPT_DIR}"/upload.sh +# shellcheck source=scripts/07_upload.sh +source "${SCRIPT_DIR}"/07_upload.sh diff --git a/scripts/upload.sh b/scripts/07_upload.sh similarity index 84% rename from scripts/upload.sh rename to scripts/07_upload.sh index 3a730cb..72a5b11 100644 --- a/scripts/upload.sh +++ b/scripts/07_upload.sh @@ -31,14 +31,14 @@ _upload_gh() { # Create a release and get url upload_url=$( - "${SCRIPT_DIR}"/create_github_release.py --repo "${release_repo}" --token "${GITHUB_TOKEN}" --name "${tag}" --desc "${desc}" + "${SCRIPT_DIR}"/07_create_github_release.py --repo "${release_repo}" --token "${GITHUB_TOKEN}" --name "${tag}" --desc "${desc}" ) # Upload ROM - DL_OTA_URL=$("${SCRIPT_DIR}"/upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME}") + DL_OTA_URL=$("${SCRIPT_DIR}"/07_upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME}") # Upload Recovery - "${SCRIPT_DIR}"/upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" + "${SCRIPT_DIR}"/07_upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" # Upload Recovery if [[ -n "${BL_RELOCK}" ]]; then @@ -81,4 +81,4 @@ if [[ -n "${UPLOAD_TARGET}" ]]; then _print_upload_success fi -source "${SCRIPT_DIR}"/ota.sh +source "${SCRIPT_DIR}"/08_ota.sh diff --git a/scripts/ota.sh b/scripts/08_ota.sh similarity index 100% rename from scripts/ota.sh rename to scripts/08_ota.sh From 38244d48178f976c1e38aecefaf1f8e1739a9e34 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 14:41:29 +0200 Subject: [PATCH 41/64] fix: dont require arguments --- dockdroid | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/dockdroid b/dockdroid index 5a99218..a3d5eb0 100644 --- a/dockdroid +++ b/dockdroid @@ -4,13 +4,15 @@ set -euo pipefail set -x config="" -case "${1}" in - "--config" | "-c") - config=${2} - ;; - *) - ;; -esac +if [[ 0 -ne "${#}" ]]; then + case "${1}" in + "--config" | "-c") + config=${2} + ;; + *) + ;; + esac +fi _build() { docker build --tag localhost/sirrgb/dockdroid:latest . @@ -33,7 +35,7 @@ _args() { -v ~/docker_droid/dotfiles/.ssh:/droid_workdir/.ssh:ro ) - env_file=~/docker_droid/minideb/target.en + env_file=~/docker_droid/minideb/target.env if [[ -n "${config}" ]]; then args=("${args[@]}" "--env-file" "${config}") fi From 58b2ca5760079483129f5d04e348a16f86da857f Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 15:12:37 +0200 Subject: [PATCH 42/64] fix: correct telegram variable name --- py-utils/print.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/py-utils/print.py b/py-utils/print.py index 4cb5bf4..b6d9dae 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -26,43 +26,47 @@ def eval_arg(args: argparse.Namespace) -> None: def send_telegram_message(msg: str) -> None: telegram_token = os.getenv("TELEGRAM_TOKEN", "") + if not telegram_token: return data = { - "chat_id": telegram_token, + "chat_id": os.getenv('TELEGRAM_CHAT', ""), "parse_mode": "Markdown", "text": msg, } + requests.post( - f"https://api.telegram.org/{os.environ['TELEGRAM_TOKEN']}/sendMessage", + "https://api.telegram.org/bot" + telegram_token + "/sendMessage", data=data, ) def send_telegram_end() -> None: telegram_token = os.getenv("TELEGRAM_TOKEN", "") + if not telegram_token: return data = { - "chat_id": telegram_token, + "chat_id": os.getenv('TELEGRAM_CHAT', ""), "parse_mode": "HTML", "sticker": "CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE", } + requests.post( - f"https://api.telegram.org/{os.environ['TELEGRAM_TOKEN']}/sendMessage", + "https://api.telegram.org/bot" + telegram_token + "/sendSticker", data=data, ) # Skeleton for printing to stdout -def print_success(msg) -> None: +def print_success(msg: str) -> None: print(f"\033[32m{msg}\033[00m") send_telegram_message(msg) -def print_error(msg) -> None: +def print_error(msg: str) -> None: print(f"\033[31m{msg}\033[00m") send_telegram_message(msg) send_telegram_end() From a11d785d59971f568743f0580248fb57a12a1838 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 16:35:51 +0200 Subject: [PATCH 43/64] fix: use args instead of env vars for tg --- py-utils/print.py | 50 +++++++++++++++++++------------------------- scripts/03_compat.sh | 1 + scripts/print.sh | 11 ++++++++-- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/py-utils/print.py b/py-utils/print.py index b6d9dae..91f123e 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -1,7 +1,6 @@ #!/usr/bin/python3 import argparse -import os import requests @@ -10,28 +9,25 @@ def arguments() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument("-a", "--action", required=True) parser.add_argument("-m", "--message") + parser.add_argument("-t", "--token") + parser.add_argument("-c", "--chat") + parser.add_argument("-f", "--failed") return parser.parse_args() def eval_arg(args: argparse.Namespace) -> None: match args.action: - case "print_success": - print_success(args.message) - case "print_error": - print_error(args.message) + case "print_message": + print_message(args, False if args.failed else True) case "send_telegram_end": - send_telegram_end() + if args.token and args.chat: + send_telegram_end(args.token, args.chat) -def send_telegram_message(msg: str) -> None: - telegram_token = os.getenv("TELEGRAM_TOKEN", "") - - if not telegram_token: - return - +def send_telegram_message(msg: str, telegram_token: str, telegram_chat: str) -> None: data = { - "chat_id": os.getenv('TELEGRAM_CHAT', ""), + "chat_id": telegram_chat, "parse_mode": "Markdown", "text": msg, } @@ -42,14 +38,9 @@ def send_telegram_message(msg: str) -> None: ) -def send_telegram_end() -> None: - telegram_token = os.getenv("TELEGRAM_TOKEN", "") - - if not telegram_token: - return - +def send_telegram_end(telegram_token: str, telegram_chat: str) -> None: data = { - "chat_id": os.getenv('TELEGRAM_CHAT', ""), + "chat_id": telegram_chat, "parse_mode": "HTML", "sticker": "CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE", } @@ -61,15 +52,16 @@ def send_telegram_end() -> None: # Skeleton for printing to stdout -def print_success(msg: str) -> None: - print(f"\033[32m{msg}\033[00m") - send_telegram_message(msg) - - -def print_error(msg: str) -> None: - print(f"\033[31m{msg}\033[00m") - send_telegram_message(msg) - send_telegram_end() +def print_message(args: argparse.Namespace, failed: bool = False) -> None: + green = "\033[32m" + red = "\033[31m" + no_colour = "\033[00m" + + print(f"{green if not failed else red}{args.message}{no_colour}") + if args.token and args.chat: + send_telegram_message(args.message, args.token, args.chat) + if failed: + send_telegram_end(args.token, args.chat) if __name__ == "__main__": diff --git a/scripts/03_compat.sh b/scripts/03_compat.sh index 334a211..135bd50 100644 --- a/scripts/03_compat.sh +++ b/scripts/03_compat.sh @@ -15,6 +15,7 @@ _init_py2() { _init_py3() { _setup_pyenv pyenv global 3.11 + pip3 install requests } # Set up Temurin 8 and re-enable TLS 1/1.1 diff --git a/scripts/print.sh b/scripts/print.sh index b0f5173..6003519 100644 --- a/scripts/print.sh +++ b/scripts/print.sh @@ -2,11 +2,18 @@ # Skeleton for printing to stdout _print_success() { - "${SCRIPT_DIR}"/print.py -a print_success -m "$*" + args=() + if [[ -n "${TELEGRAM_TOKEN}" ]] && [[ -n "${TELEGRAM_CHAT}" ]]; then + args=("${args[@]}" "--token" "${TELEGRAM_TOKEN}" "--chat" "${TELEGRAM_CHAT}") + fi + "${SCRIPT_DIR}"/print.py --action print_message --message "$*" "${args[@]}" } _print_error() { - "${SCRIPT_DIR}"/print.py -a print_error -m "$*" + if [[ -n "${TELEGRAM_TOKEN}" ]] && [[ -n "${TELEGRAM_CHAT}" ]]; then + args=("${args[@]}" "--token" "${TELEGRAM_TOKEN}" "--chat" "${TELEGRAM_CHAT}") + fi + "${SCRIPT_DIR}"/print.py --action print_message --message "$*" --failed "true" "${args[@]}" } From ff8227b6ed1d152723d44540ceadaaaefead5cee Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 18:57:05 +0200 Subject: [PATCH 44/64] fix: use host python everywhere * less portable, but 3.11 doesnt work with fstrings --- py-utils/07_upload_github.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py-utils/07_upload_github.py b/py-utils/07_upload_github.py index a98451b..c1c5f3b 100755 --- a/py-utils/07_upload_github.py +++ b/py-utils/07_upload_github.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/python3 import argparse import json From 484e5e258f9d3ac1cfe98e787aca21a9268d54ee Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 20:01:26 +0200 Subject: [PATCH 45/64] chore: deprecate json_arg_parser --- py-utils/03_fetch_temurin_tag.py | 10 ++++++++++ py-utils/03_json_arg_parser.py | 23 ----------------------- py-utils/print.py | 2 +- scripts/03_compat.sh | 6 +----- 4 files changed, 12 insertions(+), 29 deletions(-) create mode 100755 py-utils/03_fetch_temurin_tag.py delete mode 100755 py-utils/03_json_arg_parser.py diff --git a/py-utils/03_fetch_temurin_tag.py b/py-utils/03_fetch_temurin_tag.py new file mode 100755 index 0000000..a912a63 --- /dev/null +++ b/py-utils/03_fetch_temurin_tag.py @@ -0,0 +1,10 @@ +#!/usr/bin/python3 + +import json + +import requests + +response = requests.get( + "https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest" +) +print(json.loads(response.content)["tag_name"]) diff --git a/py-utils/03_json_arg_parser.py b/py-utils/03_json_arg_parser.py deleted file mode 100755 index 5032229..0000000 --- a/py-utils/03_json_arg_parser.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/python3 - -import json -import sys - - -def main() -> None: - try: - json_target = json.loads(str(sys.stdin.read())) - search_target = str(sys.argv[1]) - except TypeError: - print("Invalid arguments") - sys.exit(1) - - try: - print(json_target[search_target]) - except KeyError: - print("Argument not found") - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/py-utils/print.py b/py-utils/print.py index 91f123e..801c47c 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -19,7 +19,7 @@ def arguments() -> argparse.Namespace: def eval_arg(args: argparse.Namespace) -> None: match args.action: case "print_message": - print_message(args, False if args.failed else True) + print_message(args, args.failed) case "send_telegram_end": if args.token and args.chat: send_telegram_end(args.token, args.chat) diff --git a/scripts/03_compat.sh b/scripts/03_compat.sh index 135bd50..96ebda2 100644 --- a/scripts/03_compat.sh +++ b/scripts/03_compat.sh @@ -22,11 +22,7 @@ _init_py3() { _setup_jdk8() { local jdk_dir jdk_tag jdk_name jdk_dir="${HOME}"/java/jdk - jdk_tag=$(curl_cmd \ - --header 'Accept: application/vnd.github+json' \ - --header 'X-GitHub-Api-Version: 2022-11-28' \ - https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest \ - | tr --delete '\n' | "${SCRIPT_DIR}"/03_json_arg_parser.py "tag_name") + jdk_tag=$("${SCRIPT_DIR}"/03_fetch_temurin_tag.py) jdk_name=OpenJDK8U-jdk_x64_linux_hotspot_$(tr --delete '-' <<< "${jdk_tag//jdk/}").tar.gz mkdir --parents "${jdk_dir}" curl_cmd --remote-name https://github.com/adoptium/temurin8-binaries/releases/download/"${jdk_tag}"/"${jdk_name}" --output-dir "${jdk_dir}" From 1c7a2f525d9525f9fd5307bea451c66cd19c3d5b Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 22:38:20 +0200 Subject: [PATCH 46/64] fix: actually use upload url variable --- scripts/07_upload.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/07_upload.sh b/scripts/07_upload.sh index 72a5b11..0b05b17 100644 --- a/scripts/07_upload.sh +++ b/scripts/07_upload.sh @@ -35,10 +35,10 @@ _upload_gh() { ) # Upload ROM - DL_OTA_URL=$("${SCRIPT_DIR}"/07_upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME}") + DL_OTA_URL=$("${SCRIPT_DIR}"/07_upload_github.py --url "${upload_url}" --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME}") # Upload Recovery - "${SCRIPT_DIR}"/07_upload_github.py --url upload_url --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" + "${SCRIPT_DIR}"/07_upload_github.py --url "${upload_url}" --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" # Upload Recovery if [[ -n "${BL_RELOCK}" ]]; then From 7efd2ce406286ed69902ab3210dc98403caec061 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 22:38:40 +0200 Subject: [PATCH 47/64] docs: declare local manifest as optional --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 267e206..a9f3926 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,6 @@ Then we need to chown that directory to the Docker user: - ```ROM_DIR```: Only change the last part after src/. Defines the source path within the container - ```ROM_MANIFEST```: URL of the rom manifest you want to sync - ```ROM_BRANCH```: Branch of the rom you want to sync -- ```LOCAL_MANIFEST```: Direct link to the local manifest(s) -or -- ```CLONE_REPOS```: Links to the repo(s) to clone. Repo name MUST have the following pattern https://github.com/user/android_dir1_dir2_dir3/tree/branch, https://github.com/user/dir1_dir2_dir3/tree/branch or https://github.com/user/proprietary_dir1_dir2_dir3/tree/branch. Not recommended. These variables should be defined in the target.env. @@ -61,11 +58,13 @@ DEVICE=cheeseburger,dumpling,TP1803 ROM_DIR=/droid_workdir/src/Los15 ROM_MANIFEST=https://github.com/LineageOS/android.git ROM_BRANCH=lineage-22.2 -LOCAL_MANIFEST=https://raw.githubusercontent.com/SirRGB/local_manifests/refs/heads/main/cheeseburgerdumpling/A15Lineage.xml,https://raw.githubusercontent.com/SirRGB/local_manifests/refs/heads/main/TP1803/A15Lineage.xml ``` ### optional - +- Device tree sources for unofficial support + - ```LOCAL_MANIFEST```: Direct link to the local manifest(s) + or + - ```CLONE_REPOS```: Links to the repo(s) to clone. Repo name MUST have the following pattern https://github.com/user/android_dir1_dir2_dir3/tree/branch, https://github.com/user/dir1_dir2_dir3/tree/branch or https://github.com/user/proprietary_dir1_dir2_dir3/tree/branch. Not recommended. - Fallbacks - ```LUNCH_PREFIX_FALLBACK```: Prefix for lunching, i.e. lineage_ for LineageOS. Needed when neither ```LOCAL_MANIFEST``` or ```CLONE_REPOS``` are specified. - ```ROM_PREFIX_FALLBACK```: Prefix for naming, i.e. lineage will result in a package name like lineage-extraversion(if set)-version-date-device-signed.zip. Needed when *_TARGET_PACKAGE is not defined in vendor/*/build/tasks/* or build/core/Makefile. From 9725831450c729e11ee996ed5fdea5fd6853f598 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 23:03:51 +0200 Subject: [PATCH 48/64] chore: fail on non-200 status --- py-utils/03_fetch_temurin_tag.py | 22 ++++++++++++++++++---- py-utils/07_upload_github.py | 1 + py-utils/print.py | 29 +++++++++++++++++++++-------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/py-utils/03_fetch_temurin_tag.py b/py-utils/03_fetch_temurin_tag.py index a912a63..e95e3bf 100755 --- a/py-utils/03_fetch_temurin_tag.py +++ b/py-utils/03_fetch_temurin_tag.py @@ -1,10 +1,24 @@ #!/usr/bin/python3 import json +import sys import requests -response = requests.get( - "https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest" -) -print(json.loads(response.content)["tag_name"]) + +def main() -> None: + try: + response = requests.get( + "https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest" + ) + response.raise_for_status() + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) + + print(json.loads(response.content)["tag_name"]) + + +if __name__ == "__main__": + main() diff --git a/py-utils/07_upload_github.py b/py-utils/07_upload_github.py index c1c5f3b..d659660 100755 --- a/py-utils/07_upload_github.py +++ b/py-utils/07_upload_github.py @@ -52,6 +52,7 @@ def upload_file(args: argparse.Namespace) -> None: ) print(args.url + "?name=" + args.file.split("/")[-1]) + response.raise_for_status() except requests.exceptions.HTTPError: print(f"http code: {response.status_code}") print(response) diff --git a/py-utils/print.py b/py-utils/print.py index 801c47c..14b7061 100755 --- a/py-utils/print.py +++ b/py-utils/print.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 import argparse +import sys import requests @@ -32,10 +33,16 @@ def send_telegram_message(msg: str, telegram_token: str, telegram_chat: str) -> "text": msg, } - requests.post( - "https://api.telegram.org/bot" + telegram_token + "/sendMessage", - data=data, - ) + try: + response = requests.post( + "https://api.telegram.org/bot" + telegram_token + "/sendMessage", + data=data, + ) + response.raise_for_status() + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) def send_telegram_end(telegram_token: str, telegram_chat: str) -> None: @@ -45,10 +52,16 @@ def send_telegram_end(telegram_token: str, telegram_chat: str) -> None: "sticker": "CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE", } - requests.post( - "https://api.telegram.org/bot" + telegram_token + "/sendSticker", - data=data, - ) + try: + response = requests.post( + "https://api.telegram.org/bot" + telegram_token + "/sendSticker", + data=data, + ) + response.raise_for_status() + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) # Skeleton for printing to stdout From 4751b404246dbfa34421ada53857893f894057a8 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 23:19:52 +0200 Subject: [PATCH 49/64] chore: move key upload to py as well --- scripts/07_upload.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/scripts/07_upload.sh b/scripts/07_upload.sh index 0b05b17..88fed96 100644 --- a/scripts/07_upload.sh +++ b/scripts/07_upload.sh @@ -40,15 +40,9 @@ _upload_gh() { # Upload Recovery "${SCRIPT_DIR}"/07_upload_github.py --url "${upload_url}" --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" - # Upload Recovery + # Upload Keys if [[ -n "${BL_RELOCK}" ]]; then - curl_cmd \ - --header 'Accept: application/vnd.github.v3+json' \ - --header "Content-Length: $(stat -c%s "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}")" \ - --header "Authorization: token ${GITHUB_TOKEN}" \ - --header "Content-Type: $(file -b --mime-type "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}")" \ - --upload-file "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" \ - "${upload_url}"?name="${PACKAGE_NAME//.zip/-pkmd.bin}" + "${SCRIPT_DIR}"/07_upload_github.py --url "${upload_url}" --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" fi } From 0311d9443ba1962463751c6c465265726399efba Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 23:29:52 +0200 Subject: [PATCH 50/64] docs: describe remaining variables --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a9f3926..db8bd3b 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ ROM_BRANCH=lineage-22.2 - ```LOCAL_MANIFEST```: Direct link to the local manifest(s) or - ```CLONE_REPOS```: Links to the repo(s) to clone. Repo name MUST have the following pattern https://github.com/user/android_dir1_dir2_dir3/tree/branch, https://github.com/user/dir1_dir2_dir3/tree/branch or https://github.com/user/proprietary_dir1_dir2_dir3/tree/branch. Not recommended. + - ```FETCH_MUPPETS```: Whether to fetch the official TheMuppets vendor repos. Only works on LineageOS 21 and above due to the respective [manifest](https://github.com/TheMuppets/manifests/blob/lineage-21.0/muppets.xml) groups. Any non-empty value is true. Only works with CLONE_REPOS. + - ```BL_RELOCK```: Signs vbmeta and uploads pkmd custom key. Untested, use at your own risk. - Fallbacks - ```LUNCH_PREFIX_FALLBACK```: Prefix for lunching, i.e. lineage_ for LineageOS. Needed when neither ```LOCAL_MANIFEST``` or ```CLONE_REPOS``` are specified. - ```ROM_PREFIX_FALLBACK```: Prefix for naming, i.e. lineage will result in a package name like lineage-extraversion(if set)-version-date-device-signed.zip. Needed when *_TARGET_PACKAGE is not defined in vendor/*/build/tasks/* or build/core/Makefile. @@ -72,7 +74,7 @@ ROM_BRANCH=lineage-22.2 - ```ROM_OTA_BRANCH_FALLBACK```: Ota branch fallback. Needed when roms have conflicting branch names and ota updates are set up. - ```RELEASETOOL_EXTRA_FLAGS```: Releasetool flags for setting up legacy quirks i.e. skip certain vintf checks. - GitHub Upload - - ```[GITHUB_TOKEN]```: [Github Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) for upload (and/or push) authentification + - ```GITHUB_TOKEN```: [Github Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) for upload (and/or push) authentification - ```OTA_REPO_URL```: for example git@github.com:user/ota_config, will also be used for uploading - Requires ```GITHUB_TOKEN``` or passwordless ssh keys [added to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) - SourceForge Upload From 078e32f512528caac17f627ec55f594eaead468b Mon Sep 17 00:00:00 2001 From: SirRGB Date: Sun, 30 Aug 2026 23:31:03 +0200 Subject: [PATCH 51/64] chore: resort variables --- Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8fcfcc7..44af5a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,14 +45,16 @@ ENV ROM_VERSION_FALLBACK='' ENV ROM_OTA_BRANCH_FALLBACK='' ENV RELEASETOOL_EXTRA_FLAGS='' -# Extra variables +# Repopick +ENV REPOPICK_PICKS='' +ENV REPOPICK_TOPICS='' +ENV REPOPICK_PULLS='' + +# Build env variables ENV CCACHE_SIZE=40 ENV OTA_REPO_URL='' ENV KEYS_SUBJECT='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com' ENV TIME_ZONE='UTC' -ENV REPOPICK_PICKS='' -ENV REPOPICK_TOPICS='' -ENV REPOPICK_PULLS='' ENV DEBUG='' # Authentification From bcf9dba34e85a4ef1f22d4e1332888852eb8b401 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 10:37:55 +0200 Subject: [PATCH 52/64] fix: drop debug print statement * messes with output variable --- py-utils/07_upload_github.py | 1 - 1 file changed, 1 deletion(-) diff --git a/py-utils/07_upload_github.py b/py-utils/07_upload_github.py index d659660..3ff2e94 100755 --- a/py-utils/07_upload_github.py +++ b/py-utils/07_upload_github.py @@ -51,7 +51,6 @@ def upload_file(args: argparse.Namespace) -> None: data=data, ) - print(args.url + "?name=" + args.file.split("/")[-1]) response.raise_for_status() except requests.exceptions.HTTPError: print(f"http code: {response.status_code}") From f6cbada0d0da21c1f053b38df77622ec6c8915eb Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 10:47:36 +0200 Subject: [PATCH 53/64] docs: describe config usage --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index db8bd3b..f838344 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,13 @@ These variables should be defined in config.env. GITHUB_TOKEN=thing1234 OTA_REPO_URL=git@github.com:user/ota_config ``` +You can use config.env for all variables, that span across more than one device. To include this run: + +``` +bash dockdroid -c config.env +``` +`--config` can also be used. Your config file can be named however you please. + From ed12ddde704db8b7c0eb7e6b3f041c666a5e7488 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 11:45:28 +0200 Subject: [PATCH 54/64] fix: actually restore upload functionality --- .pre-commit-config.yaml | 1 - py-utils/07_upload_github.py | 25 ++++--------------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3376520..d87faec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,6 @@ repos: rev: 26.5.1 hooks: - id: black - language_version: python3.12 - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.16.5 diff --git a/py-utils/07_upload_github.py b/py-utils/07_upload_github.py index 3ff2e94..ff101ee 100755 --- a/py-utils/07_upload_github.py +++ b/py-utils/07_upload_github.py @@ -2,7 +2,6 @@ import argparse import json -import subprocess import sys import requests @@ -17,39 +16,23 @@ def arguments() -> argparse.Namespace: def upload_file(args: argparse.Namespace) -> None: - file_size = subprocess.run( - "stat -c%s " + args.file, shell=True, check=True, capture_output=True, text=True - ).stdout - file_type = subprocess.run( - "file -b --mime-type " + args.file, - shell=True, - check=True, - capture_output=True, - text=True, - ).stdout.strip() - headers = { "Accept": "application/vnd.github+json", "Authorization": "Token " + args.token, "X-GitHub-Api-Version": "2026-03-10", - "Content-Length": file_size, - "Content-Type": file_type, + "Content-Type": "application/octet-stream", } with open(args.file, "rb") as f: - data = {"files": f.read} + data = f.read() params = { "name": args.file.split("/")[-1], } + url = f"{args.url}?name={args.file.split('/')[-1]}" try: - response = requests.put( - args.url + "?name=" + args.file.split("/")[-1], - params=params, - headers=headers, - data=data, - ) + response = requests.post(url=url, params=params, headers=headers, data=data) response.raise_for_status() except requests.exceptions.HTTPError: From b1ea21aaae58dc716ad088d3bcb6c9e707f6419d Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 12:26:16 +0200 Subject: [PATCH 55/64] feat: allow providing config names --- README.md | 2 +- dockdroid | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f838344..59779b1 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ bash dockdroid -c config.env - After setting everything up you should do a test build with the default variables for testing. (Be sure to be in ~/docker_droid/minideb) ``` -bash dockdroid +bash dockdroid -r target.env ``` diff --git a/dockdroid b/dockdroid index a3d5eb0..1cfb847 100644 --- a/dockdroid +++ b/dockdroid @@ -3,15 +3,27 @@ set -euo pipefail set -x +# parse args config="" -if [[ 0 -ne "${#}" ]]; then +rom_config="" +while [ 0 -ne "${#}" ]; do case "${1}" in + "--rom" | "-r") + rom_config="${2}" + shift 2 + ;; "--config" | "-c") - config=${2} + config="${2}" + shift 2 ;; *) ;; esac +done + +if [[ -z "${rom_config}" ]]; then + echo "Provide -r or --rom" + exit 2 fi _build() { @@ -25,7 +37,7 @@ _args() { args=("--user" "${UID}":"${GID}") fi - #local volumes + # local volumes volumes=( -v ~/docker_droid/src:/droid_workdir/src -v ~/docker_droid/logs:/droid_workdir/logs @@ -35,7 +47,7 @@ _args() { -v ~/docker_droid/dotfiles/.ssh:/droid_workdir/.ssh:ro ) - env_file=~/docker_droid/minideb/target.env + env_file=~/docker_droid/minideb/"${rom_config}" if [[ -n "${config}" ]]; then args=("${args[@]}" "--env-file" "${config}") fi From 4798e68e414f350a28db6b08ac2f484dbd98adc4 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 12:49:45 +0200 Subject: [PATCH 56/64] fix: escape underscores for telegram --- scripts/print.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/print.sh b/scripts/print.sh index 6003519..5a744fd 100644 --- a/scripts/print.sh +++ b/scripts/print.sh @@ -39,7 +39,7 @@ _print_sync_fail() { # Building _print_build_start() { BUILD_START=$(date +"%s") - _print_success "Build started for ${TARGET_DEVICE}" + _print_success "Build started for ${TARGET_DEVICE/_/\\_}" } _print_build_success() { From 4aae285a198bd4d3a0346e5e535ae9dd2eb26868 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 13:45:30 +0200 Subject: [PATCH 57/64] chore: drop requests * not needed since we are using the hosts python --- scripts/03_compat.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/03_compat.sh b/scripts/03_compat.sh index 96ebda2..5c12161 100644 --- a/scripts/03_compat.sh +++ b/scripts/03_compat.sh @@ -15,7 +15,6 @@ _init_py2() { _init_py3() { _setup_pyenv pyenv global 3.11 - pip3 install requests } # Set up Temurin 8 and re-enable TLS 1/1.1 From 144ce82749171bc77743d250b4ff89900f2c4df1 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Mon, 31 Aug 2026 14:58:19 +0200 Subject: [PATCH 58/64] chore: move temurin download to python --- py-utils/03_download_temurin.py | 48 ++++++++++++++++++++++++++++++++ py-utils/03_fetch_temurin_tag.py | 24 ---------------- scripts/03_compat.sh | 5 ++-- 3 files changed, 50 insertions(+), 27 deletions(-) create mode 100755 py-utils/03_download_temurin.py delete mode 100755 py-utils/03_fetch_temurin_tag.py diff --git a/py-utils/03_download_temurin.py b/py-utils/03_download_temurin.py new file mode 100755 index 0000000..524e40c --- /dev/null +++ b/py-utils/03_download_temurin.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3 + +import argparse +import json +import sys + +import requests + + +def arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("-p", "--path", required=True) + return parser.parse_args() + + +def main(args: argparse.Namespace) -> None: + try: + response = requests.get( + "https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest" + ) + response.raise_for_status() + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) + + tag = json.loads(response.content)["tag_name"] + jdk_name = "OpenJDK8U-jdk_x64_linux_hotspot_" + tag.replace("-", "")[3:] + ".tar.gz" + try: + with requests.get( + "https://github.com/adoptium/temurin8-binaries/releases/download/" + + tag + + "/" + + jdk_name, + stream=True, + ) as r: + response.raise_for_status() + with open(args.path + "/" + jdk_name, "wb") as f: + f.writelines(r.iter_content(chunk_size=8192)) + except requests.exceptions.HTTPError: + print(f"http code: {response.status_code}") + print(response) + sys.exit(1) + print(tag) + + +if __name__ == "__main__": + main(arguments()) diff --git a/py-utils/03_fetch_temurin_tag.py b/py-utils/03_fetch_temurin_tag.py deleted file mode 100755 index e95e3bf..0000000 --- a/py-utils/03_fetch_temurin_tag.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python3 - -import json -import sys - -import requests - - -def main() -> None: - try: - response = requests.get( - "https://api.github.com/repos/adoptium/temurin8-binaries/releases/latest" - ) - response.raise_for_status() - except requests.exceptions.HTTPError: - print(f"http code: {response.status_code}") - print(response) - sys.exit(1) - - print(json.loads(response.content)["tag_name"]) - - -if __name__ == "__main__": - main() diff --git a/scripts/03_compat.sh b/scripts/03_compat.sh index 5c12161..a67dbae 100644 --- a/scripts/03_compat.sh +++ b/scripts/03_compat.sh @@ -21,10 +21,9 @@ _init_py3() { _setup_jdk8() { local jdk_dir jdk_tag jdk_name jdk_dir="${HOME}"/java/jdk - jdk_tag=$("${SCRIPT_DIR}"/03_fetch_temurin_tag.py) - jdk_name=OpenJDK8U-jdk_x64_linux_hotspot_$(tr --delete '-' <<< "${jdk_tag//jdk/}").tar.gz mkdir --parents "${jdk_dir}" - curl_cmd --remote-name https://github.com/adoptium/temurin8-binaries/releases/download/"${jdk_tag}"/"${jdk_name}" --output-dir "${jdk_dir}" + jdk_tag=$("${SCRIPT_DIR}"/03_download_temurin.py --path="${jdk_dir}") + jdk_name=OpenJDK8U-jdk_x64_linux_hotspot_$(tr --delete '-' <<< "${jdk_tag//jdk/}").tar.gz curl_cmd https://github.com/adoptium/temurin8-binaries/releases/download/"${jdk_tag}"/"${jdk_name}".sha256.txt | sed "s|${jdk_name}|${jdk_dir}/${jdk_name}|g" | sha256sum --check tar --extract --verbose --file="${jdk_dir}"/"${jdk_name}" --directory="${jdk_dir}" rm "${jdk_dir}"/"${jdk_name}" From d5a64117b2f66237f613370d35fa9c1bcce99f0e Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 3 Sep 2026 20:05:26 +0200 Subject: [PATCH 59/64] chore: use longform flag consistently --- scripts/08_ota.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/08_ota.sh b/scripts/08_ota.sh index a60b3f6..8d5fb40 100644 --- a/scripts/08_ota.sh +++ b/scripts/08_ota.sh @@ -8,7 +8,7 @@ _ota_info() { local file_size id datetime custom_build_type file_size=$(stat --format=%s "${OUT}"/"${PACKAGE_NAME}") id=$(sha256sum "${OUT}"/"${PACKAGE_NAME}" | cut --delimiter=' ' --fields=1) - datetime=$(grep ro\.build\.date\.utc "${OUT}"/system/build.prop | cut --delimiter='=' -f2) + datetime=$(grep ro\.build\.date\.utc "${OUT}"/system/build.prop | cut --delimiter='=' --fields=2) custom_build_type='UNOFFICIAL' python3 -m json.tool --indent 2 <<< "{\"response\": [{\"datetime\": ${datetime},\"filename\": \"${PACKAGE_NAME}\",\"id\": \"${id}\",\"romtype\": \"${custom_build_type}\", \"size\": ${file_size}, \"url\": \"${DL_OTA_URL}\", \"version\": \"${ROM_VERSION}\"}]}" > "${OUT}"/"${PACKAGE_NAME}".json } From 5bb01e379d7494d03c424af5220b360adc983052 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Thu, 3 Sep 2026 21:16:52 +0200 Subject: [PATCH 60/64] fix: make end-sticker work --- dockdroid | 0 scripts/print.sh | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 dockdroid diff --git a/dockdroid b/dockdroid old mode 100644 new mode 100755 diff --git a/scripts/print.sh b/scripts/print.sh index 5a744fd..afe4dd3 100644 --- a/scripts/print.sh +++ b/scripts/print.sh @@ -84,5 +84,5 @@ _print_ota_fail() { # End _print_done() { _print_success 'Completed successfully' - "${SCRIPT_DIR}"/print.py -a send_telegram_end + "${SCRIPT_DIR}"/print.py --action send_telegram_end --token "${TELEGRAM_TOKEN}" "--chat" "${TELEGRAM_CHAT}" } From f17706ba57ade99df59bbf99a3e7ca6c60c449fb Mon Sep 17 00:00:00 2001 From: SirRGB Date: Tue, 15 Sep 2026 13:13:05 +0200 Subject: [PATCH 61/64] docs: specify target rom env in example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59779b1..1030be0 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ OTA_REPO_URL=git@github.com:user/ota_config You can use config.env for all variables, that span across more than one device. To include this run: ``` -bash dockdroid -c config.env +bash dockdroid -r target.env -c config.env ``` `--config` can also be used. Your config file can be named however you please. From cc94280861287f0d42f6bca5818fc49b608607d2 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Tue, 15 Sep 2026 14:44:51 +0200 Subject: [PATCH 62/64] chore: use readarray * more readable, thank god bash 4 exists --- scripts/01_sync.sh | 2 +- scripts/04_lunch.sh | 2 +- scripts/05_sign.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/01_sync.sh b/scripts/01_sync.sh index 5d61127..09fcf02 100644 --- a/scripts/01_sync.sh +++ b/scripts/01_sync.sh @@ -80,7 +80,7 @@ _clone() { # Wrapper to clone all repos defined in $CLONE_REPOS _clone_all() { - IFS=',' read -r -a "CLONE_REPOS" <<< "${CLONE_REPOS}" + readarray -d "," -t "CLONE_REPOS" <<< "${CLONE_REPOS}" for repo in "${CLONE_REPOS[@]}"; do _clone "${repo}" done diff --git a/scripts/04_lunch.sh b/scripts/04_lunch.sh index 6fcdabf..819e296 100644 --- a/scripts/04_lunch.sh +++ b/scripts/04_lunch.sh @@ -32,7 +32,7 @@ _lunch() { } # Iterate over device array -IFS=',' read -r -a "DEVICE" <<< "${DEVICE}" +readarray -d "," -t "DEVICE" <<< "${DEVICE}" for device in "${DEVICE[@]}"; do TARGET_DEVICE="${device}" _lunch diff --git a/scripts/05_sign.sh b/scripts/05_sign.sh index 014b772..f06eff9 100644 --- a/scripts/05_sign.sh +++ b/scripts/05_sign.sh @@ -97,9 +97,9 @@ _cleanup_fail() { _cleanup if [[ -n "${ROM_BUILD_FLAGS}" ]]; then - IFS=',' read -r -a "ROM_BUILD_FLAGS" <<< "${ROM_BUILD_FLAGS}" + readarray -d ',' -t "ROM_BUILD_FLAGS" <<< "${ROM_BUILD_FLAGS}" for flags in "${ROM_BUILD_FLAGS[@]}"; do - IFS=' ' read -r -a "TARGET_BUILD_FLAGS" <<< "${flags}" + readarray -d ' ' -t "TARGET_BUILD_FLAGS" <<< "${flags}" _print_success "Current build flags: ${flags}" _determine_signing "${TARGET_BUILD_FLAGS[@]}" source "${SCRIPT_DIR}"/packaging.sh From 0033ea1c0964305012b2c1e79822dc31c32421e7 Mon Sep 17 00:00:00 2001 From: SirRGB Date: Tue, 29 Sep 2026 22:44:09 +0200 Subject: [PATCH 63/64] Revert "chore: use readarray" + This reverts commit cc94280861287f0d42f6bca5818fc49b608607d2. * breaks last device due to newline --- scripts/01_sync.sh | 2 +- scripts/04_lunch.sh | 2 +- scripts/05_sign.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/01_sync.sh b/scripts/01_sync.sh index 09fcf02..5d61127 100644 --- a/scripts/01_sync.sh +++ b/scripts/01_sync.sh @@ -80,7 +80,7 @@ _clone() { # Wrapper to clone all repos defined in $CLONE_REPOS _clone_all() { - readarray -d "," -t "CLONE_REPOS" <<< "${CLONE_REPOS}" + IFS=',' read -r -a "CLONE_REPOS" <<< "${CLONE_REPOS}" for repo in "${CLONE_REPOS[@]}"; do _clone "${repo}" done diff --git a/scripts/04_lunch.sh b/scripts/04_lunch.sh index 819e296..6fcdabf 100644 --- a/scripts/04_lunch.sh +++ b/scripts/04_lunch.sh @@ -32,7 +32,7 @@ _lunch() { } # Iterate over device array -readarray -d "," -t "DEVICE" <<< "${DEVICE}" +IFS=',' read -r -a "DEVICE" <<< "${DEVICE}" for device in "${DEVICE[@]}"; do TARGET_DEVICE="${device}" _lunch diff --git a/scripts/05_sign.sh b/scripts/05_sign.sh index f06eff9..014b772 100644 --- a/scripts/05_sign.sh +++ b/scripts/05_sign.sh @@ -97,9 +97,9 @@ _cleanup_fail() { _cleanup if [[ -n "${ROM_BUILD_FLAGS}" ]]; then - readarray -d ',' -t "ROM_BUILD_FLAGS" <<< "${ROM_BUILD_FLAGS}" + IFS=',' read -r -a "ROM_BUILD_FLAGS" <<< "${ROM_BUILD_FLAGS}" for flags in "${ROM_BUILD_FLAGS[@]}"; do - readarray -d ' ' -t "TARGET_BUILD_FLAGS" <<< "${flags}" + IFS=' ' read -r -a "TARGET_BUILD_FLAGS" <<< "${flags}" _print_success "Current build flags: ${flags}" _determine_signing "${TARGET_BUILD_FLAGS[@]}" source "${SCRIPT_DIR}"/packaging.sh From 3b6b4b6c95f0b4708e394fa9df8a5d625ac61eaf Mon Sep 17 00:00:00 2001 From: SirRGB Date: Tue, 29 Sep 2026 22:47:11 +0200 Subject: [PATCH 64/64] chore: drop unneeded field separator --- scripts/05_sign.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/05_sign.sh b/scripts/05_sign.sh index 014b772..62fc10c 100644 --- a/scripts/05_sign.sh +++ b/scripts/05_sign.sh @@ -99,7 +99,7 @@ _cleanup if [[ -n "${ROM_BUILD_FLAGS}" ]]; then IFS=',' read -r -a "ROM_BUILD_FLAGS" <<< "${ROM_BUILD_FLAGS}" for flags in "${ROM_BUILD_FLAGS[@]}"; do - IFS=' ' read -r -a "TARGET_BUILD_FLAGS" <<< "${flags}" + read -r -a "TARGET_BUILD_FLAGS" <<< "${flags}" _print_success "Current build flags: ${flags}" _determine_signing "${TARGET_BUILD_FLAGS[@]}" source "${SCRIPT_DIR}"/packaging.sh