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 90% rename from .github/workflows/shellcheck.yml rename to .github/workflows/shellcheck.yaml index b921833..d24a1ea 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yaml @@ -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 {} + diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d87faec --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,34 @@ +--- +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.5.1 + hooks: + - id: black + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.16.5 + hooks: + # Run the linter. + - id: ruff-check + # Run the formatter. + - id: ruff-format diff --git a/Dockerfile b/Dockerfile index 1343d8d..44af5a1 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}" @@ -35,6 +35,8 @@ ENV BUILD_TYPE='' 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='' @@ -43,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 @@ -62,4 +66,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/README.md b/README.md index 29b6207..1030be0 100644 --- a/README.md +++ b/README.md @@ -11,30 +11,21 @@ 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-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 -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 ``` @@ -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 -n ~/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 -rf ~/docker_droid/src/Los15/ -``` @@ -93,9 +46,6 @@ sudo rm -rf ~/docker_droid/src/Los15/ - ```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. @@ -108,27 +58,46 @@ 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. + - ```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. + - ```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)``` + - ```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 - ```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_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 - 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. @@ -136,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 -r target.env -c config.env +``` +`--config` can also be used. Your config file can be named however you please. + @@ -151,18 +127,14 @@ 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 -r target.env ``` ## 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 @@ -187,3 +159,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/TODO.md b/TODO.md index 38f45dc..7c3f648 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +1,8 @@ ## ToDo - make vendor pulling work for multiple devices +- GSI/patch handling +- project linkfile handling +- progress message telegram +- incremental updates +- move to py (apart from env vars?, devices as objects?) +- only log errors (docker/podman logs work otherwise) 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/base/Makefile b/base/Makefile index d19644e..897c72b 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 --no-cache 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 diff --git a/base/README.md b/base/README.md new file mode 100644 index 0000000..de43b92 --- /dev/null +++ b/base/README.md @@ -0,0 +1,10 @@ +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` + +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. diff --git a/compose.yml b/compose.yml deleted file mode 100644 index 82dd241..0000000 --- a/compose.yml +++ /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 100755 index 0000000..1cfb847 --- /dev/null +++ b/dockdroid @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -euo pipefail +set -x + +# parse args +config="" +rom_config="" +while [ 0 -ne "${#}" ]; do + case "${1}" in + "--rom" | "-r") + rom_config="${2}" + shift 2 + ;; + "--config" | "-c") + config="${2}" + shift 2 + ;; + *) + ;; + esac +done + +if [[ -z "${rom_config}" ]]; then + echo "Provide -r or --rom" + exit 2 +fi + +_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 + -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 + ) + + env_file=~/docker_droid/minideb/"${rom_config}" + if [[ -n "${config}" ]]; then + args=("${args[@]}" "--env-file" "${config}") + fi +} + +_run() { + docker run "${volumes[@]}" --env-file "${env_file}" "${args[@]}" localhost/sirrgb/dockdroid:latest +} + +_build +_args +_run diff --git a/py-utils/xml_roomservice.py b/py-utils/01_xml_roomservice.py similarity index 87% rename from py-utils/xml_roomservice.py rename to py-utils/01_xml_roomservice.py index e0469d3..b9aa28d 100755 --- a/py-utils/xml_roomservice.py +++ b/py-utils/01_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 _01_xml_manifest_gen def fetch_device_vendor(local_manifest, remote_manifest, device: str) -> xml: @@ -20,12 +21,12 @@ 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"), project_remote=remote, - project_revision=revision + project_revision=revision, ) ElementTree.indent(local_manifest) @@ -49,5 +50,5 @@ def main() -> None: print(ElementTree.tostring(local_manifest).decode()) -if __name__ == '__main__': +if __name__ == "__main__": main() 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/07_create_github_release.py b/py-utils/07_create_github_release.py new file mode 100755 index 0000000..39a92a1 --- /dev/null +++ b/py-utils/07_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/07_upload_github.py b/py-utils/07_upload_github.py new file mode 100755 index 0000000..ff101ee --- /dev/null +++ b/py-utils/07_upload_github.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 + +import argparse +import json +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: + headers = { + "Accept": "application/vnd.github+json", + "Authorization": "Token " + args.token, + "X-GitHub-Api-Version": "2026-03-10", + "Content-Type": "application/octet-stream", + } + + with open(args.file, "rb") as f: + data = f.read() + + params = { + "name": args.file.split("/")[-1], + } + + url = f"{args.url}?name={args.file.split('/')[-1]}" + try: + response = requests.post(url=url, params=params, 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(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/_01_xml_manifest_gen.py similarity index 65% rename from py-utils/xml_manifest_gen.py rename to py-utils/_01_xml_manifest_gen.py index 5c0f96c..74bce1f 100755 --- a/py-utils/xml_manifest_gen.py +++ b/py-utils/_01_xml_manifest_gen.py @@ -1,16 +1,25 @@ #!/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(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 @@ -18,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 @@ -41,7 +55,24 @@ def add_project_to_manifest(manifest: xml, project_name: str, project_path: str, return manifest -def add_remote_to_manifest(manifest: xml, remote_name: str, remote_fetch: str, remote_revision: str = "") -> xml: +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): return manifest @@ -71,7 +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") ) for projects in remote_manifest.findall("project"): @@ -90,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) @@ -101,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) @@ -111,5 +147,5 @@ def main() -> None: print(ElementTree.tostring(local_manifest).decode()) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/py-utils/json_arg_parser.py b/py-utils/json_arg_parser.py deleted file mode 100755 index 2f6b283..0000000 --- a/py-utils/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 new file mode 100755 index 0000000..14b7061 --- /dev/null +++ b/py-utils/print.py @@ -0,0 +1,81 @@ +#!/usr/bin/python3 + +import argparse +import sys + +import requests + + +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_message": + print_message(args, args.failed) + case "send_telegram_end": + if args.token and args.chat: + send_telegram_end(args.token, args.chat) + + +def send_telegram_message(msg: str, telegram_token: str, telegram_chat: str) -> None: + data = { + "chat_id": telegram_chat, + "parse_mode": "Markdown", + "text": msg, + } + + 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: + data = { + "chat_id": telegram_chat, + "parse_mode": "HTML", + "sticker": "CAADBQADGgEAAixuhBPbSa3YLUZ8DBYE", + } + + 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 +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__": + eval_arg(arguments()) 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 85% rename from scripts/sync.sh rename to scripts/01_sync.sh index 0660be0..5d61127 100644 --- a/scripts/sync.sh +++ b/scripts/01_sync.sh @@ -17,11 +17,15 @@ _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 - xml_manifest_gen.py "${LOCAL_MANIFEST}" > "${ROM_DIR}"/.repo/local_manifests/manifest.xml - elif [[ -z "${CLONE_REPOS}" ]]; then + if grep -q ',' <<< "${LOCAL_MANIFEST}"; then + # Merge local manifests into one to avoid conflicts with duplicate dependencies + "${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 - 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) @@ -71,7 +75,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 @@ -93,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 85% rename from scripts/setup.sh rename to scripts/02_setup.sh index cf3d9d6..63baa39 100644 --- a/scripts/setup.sh +++ b/scripts/02_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 @@ -44,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 @@ -65,6 +65,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 +87,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 @@ -100,6 +103,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 } @@ -136,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 80% rename from scripts/compat.sh rename to scripts/03_compat.sh index e4ffab1..a67dbae 100644 --- a/scripts/compat.sh +++ b/scripts/03_compat.sh @@ -21,14 +21,9 @@ _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' | 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}" + 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}" @@ -55,7 +50,7 @@ _key_size_recovery() { if [[ "${ANDROID_VERSION}" -lt 10 ]]; then _init_py2 # A10-15 -else +elif [[ "${ANDROID_VERSION}" -lt 16 ]]; then _init_py3 fi diff --git a/scripts/lunch.sh b/scripts/04_lunch.sh similarity index 95% rename from scripts/lunch.sh rename to scripts/04_lunch.sh index b2d126b..6fcdabf 100644 --- a/scripts/lunch.sh +++ b/scripts/04_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 @@ -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 82% rename from scripts/sign.sh rename to scripts/05_sign.sh index 2711a6b..62fc10c 100644 --- a/scripts/sign.sh +++ b/scripts/05_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 @@ -56,13 +55,18 @@ _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 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 \ @@ -73,8 +77,11 @@ _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 \ - "${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 @@ -88,18 +95,16 @@ _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}" 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 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 92% rename from scripts/packaging.sh rename to scripts/06_packaging.sh index c99ddf7..a1d55d7 100644 --- a/scripts/packaging.sh +++ b/scripts/06_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 } @@ -66,11 +71,9 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _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 56% rename from scripts/upload.sh rename to scripts/07_upload.sh index 1091038..88fed96 100644 --- a/scripts/upload.sh +++ b/scripts/07_upload.sh @@ -30,39 +30,30 @@ _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' | json_arg_parser.py "upload_url" \ - | cut --delimiter='{' -f1) + upload_url=$( + "${SCRIPT_DIR}"/07_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' | json_arg_parser.py "browser_download_url") + DL_OTA_URL=$("${SCRIPT_DIR}"/07_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}"/07_upload_github.py --url "${upload_url}" --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" + + # Upload Keys + if [[ -n "${BL_RELOCK}" ]]; then + "${SCRIPT_DIR}"/07_upload_github.py --url "${upload_url}" --token "${GITHUB_TOKEN}" --file "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" + fi } _upload_ssh() { scp "${OUT}"/"${PACKAGE_NAME}" "${1}"@"${2}" scp "${OUT}"/"${PACKAGE_NAME//.zip/-recovery.img}" "${1}"@"${2}" - DL_OTA_URL="${3}" + if [[ -n "${BL_RELOCK}" ]]; then + scp "${OUT}"/"${PACKAGE_NAME//.zip/-pkmd.bin}" "${1}"@"${2}" + fi + + export DL_OTA_URL="${3}" } # Upload to SourceForge @@ -79,11 +70,9 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _upload 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 93% rename from scripts/ota.sh rename to scripts/08_ota.sh index cf79bd6..8d5fb40 100644 --- a/scripts/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 } @@ -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 @@ -32,18 +45,8 @@ _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/}" - fi - - # Specify a fallback, so that roms, that purely rely on android numbers dont 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,,}")" + _cleanup_fail fi if [[ -n "${target_ota_repo_url}" ]]; then @@ -56,8 +59,6 @@ _cleanup_fail() { exit 1 } -trap _cleanup_fail ERR - _ota_info if [[ -n "${OTA_REPO_URL}" ]]; then _push_ota_info diff --git a/scripts/print.sh b/scripts/print.sh index 572ddc3..afe4dd3 100644 --- a/scripts/print.sh +++ b/scripts/print.sh @@ -1,40 +1,19 @@ #!/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 "$*" + 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() { - echo -e "${RED}$*${NC}" - _telegram "$*" - _telegram_separator + 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[@]}" } @@ -60,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() { @@ -95,13 +74,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 --action send_telegram_end --token "${TELEGRAM_TOKEN}" "--chat" "${TELEGRAM_CHAT}" }