diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4bfa83e..747f40c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,29 +22,6 @@ on: type: boolean required: true - outputs: - kernel_version: - description: "Kernel version" - value: ${{ jobs.build.outputs.kernel_version }} - susfs_version: - description: "SUSFS version" - value: ${{ jobs.build.outputs.susfs_version }} - toolchain: - description: "Toolchain" - value: ${{ jobs.build.outputs.toolchain }} - build_date: - description: "Build timestamp" - value: ${{ jobs.build.outputs.build_date }} - release_repo: - description: "Release repo" - value: ${{ jobs.build.outputs.release_repo }} - release_branch: - description: "Release branch" - value: ${{ jobs.build.outputs.release_branch }} - kernel_name: - description: "Kernel name" - value: ${{ jobs.build.outputs.kernel_name }} - workflow_dispatch: inputs: KSU: @@ -89,15 +66,6 @@ jobs: TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }} - outputs: - kernel_version: ${{ steps.build.outputs.kernel_version }} - susfs_version: ${{ steps.build.outputs.susfs_version }} - toolchain: ${{ steps.build.outputs.toolchain }} - build_date: ${{ steps.build.outputs.build_date }} - release_repo: ${{ steps.build.outputs.release_repo }} - release_branch: ${{ steps.build.outputs.release_branch }} - kernel_name: ${{ steps.build.outputs.kernel_name }} - steps: - name: Fail SUSFS requirement check if: ${{ inputs.SUSFS == true && inputs.KSU == 'NONE' }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 64118f1..de491e3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,9 +20,7 @@ jobs: - { name: "Non-KSU", KSU: "NONE", SUSFS: false, LXC: false } - { name: "Non-KSU-LXC", KSU: "NONE", SUSFS: false, LXC: true } - { name: "RKSU", KSU: "RKSU", SUSFS: false, LXC: false } - - { name: "RKSU-SUSFS", KSU: "RKSU", SUSFS: true, LXC: false } - { name: "RKSU-LXC", KSU: "RKSU", SUSFS: false, LXC: true } - - { name: "RKSU-SUSFS-LXC", KSU: "RKSU", SUSFS: true, LXC: true } - { name: "KSUN", KSU: "NEXT", SUSFS: false, LXC: false } - { name: "KSUN-SUSFS", KSU: "NEXT", SUSFS: true, LXC: false } - { name: "KSUN-LXC", KSU: "NEXT", SUSFS: false, LXC: true } @@ -46,14 +44,6 @@ jobs: needs: build if: ${{ github.event.inputs.create_release }} runs-on: ubuntu-latest - env: - KERNEL_VER: ${{ needs.build.outputs.kernel_version }} - SUSFS_VER: ${{ needs.build.outputs.susfs_version }} - TOOLCHAIN: ${{ needs.build.outputs.toolchain }} - BUILD_DATE: ${{ needs.build.outputs.build_date }} - RELEASE_REPO: ${{ needs.build.outputs.release_repo }} - RELEASE_BRANCH: ${{ needs.build.outputs.release_branch }} - KERNEL_NAME: ${{ needs.build.outputs.kernel_name }} steps: - name: Checkout current repo @@ -66,34 +56,23 @@ jobs: with: path: release_files + - name: Import build configs + run: | + source "$GITHUB_WORKSPACE/config.sh" + { + echo "KERNEL_NAME=$KERNEL_NAME" + echo "RELEASE_REPO=$RELEASE_REPO" + echo "RELEASE_BRANCH=$RELEASE_BRANCH" + } >> "$GITHUB_ENV" + - name: Generate new tag env: GH_TOKEN: ${{ secrets.GH_TOKEN }} RELEASE_REPO: ${{ env.RELEASE_REPO }} run: | - LATEST_TAG=$(gh release list --repo "$RELEASE_REPO" --limit 100 --json tagName --jq '.[].tagName' | sort -V | tail -n1) - - LATEST=${LATEST_TAG#v} - - if [[ -z "$LATEST" ]]; then - RELEASE_TAG="v1.0" - else - MAJOR=${LATEST%.*} - MINOR=${LATEST#*.} + TAG_PY="$GITHUB_WORKSPACE/py/tag.py" - # Force them to be numbers - MAJOR=$((MAJOR + 0)) - MINOR=$((MINOR + 0)) - - if [ "$MINOR" -ge 9 ]; then - MAJOR=$((MAJOR + 1)) - MINOR=0 - else - MINOR=$((MINOR + 1)) - fi - - RELEASE_TAG="v${MAJOR}.${MINOR}" - fi + RELEASE_TAG=$(python3 "$TAG_PY" "$RELEASE_REPO") echo "New tag: $RELEASE_TAG" echo "RELEASE_TAG=$RELEASE_TAG" >> "$GITHUB_ENV" @@ -112,16 +91,6 @@ jobs: --- - ### Build Information - - | Component | Information | - |-----------|---------| - | **Kernel Version** | `${{ env.KERNEL_VER }}` | - | **Toolchain** | `${{ env.TOOLCHAIN }}` | - | **Build Date** | `${{ env.BUILD_DATE }}` | - - --- - ### Variants Suffixes | Suffix | Description | @@ -145,6 +114,8 @@ jobs: TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }} run: | + TG_PY="$GITHUB_WORKSPACE/py/tg.py" + escape_md_v2() { python3 - "$*" <<'PY' import sys, re @@ -154,32 +125,12 @@ jobs: PY } - telegram_send_msg() { - local resp err - - resp=$(curl -sX POST https://api.telegram.org/bot"${TG_BOT_TOKEN}"/sendMessage \ - -d chat_id="${TG_CHAT_ID}" \ - -d parse_mode="MarkdownV2" \ - -d disable_web_page_preview=true \ - -d text="$1") - - if ! echo "$resp" | jq -e '.ok == true' > /dev/null; then - err=$(echo "$resp" | jq -r '.description') - echo "::error::telegram_send_msg(): ${err:-Unknown error} $*" >&2 - exit 1 - fi - } - message=$( - cat< /dev/null 2>&1 sed -i '/^config LSM$/,/^help$/{ /^[[:space:]]*default/ { /baseband_guard/! s/bpf/bpf,baseband_guard/ } }' security/Kconfig config --enable CONFIG_BBG diff --git a/config.sh b/config.sh new file mode 100644 index 0000000..670d02f --- /dev/null +++ b/config.sh @@ -0,0 +1,31 @@ +# shellcheck shell=bash +# shellcheck disable=SC2034 +# +# ESK Kernel builder configuration +# + +################################################################################ +# Project Identity +################################################################################ +KERNEL_NAME="ESK" +KERNEL_DEFCONFIG="gki_defconfig" + +# Kbuild identity +KBUILD_BUILD_USER="builder" +KBUILD_BUILD_HOST="esk" + +# Used for timestamps in logs/messages +TIMEZONE="Asia/Ho_Chi_Minh" + +# Where release artifacts are published +RELEASE_REPO="ESK-Project/esk-releases" +RELEASE_BRANCH="main" + +################################################################################ +# Build knobs +################################################################################ +# Clang LTO mode: thin | full +CLANG_LTO="thin" + +# Parallel build jobs (override: JOBS=16 ./build.sh) +JOBS="${JOBS:-$(nproc --all)}" diff --git a/py/tag.py b/py/tag.py new file mode 100644 index 0000000..ff384c4 --- /dev/null +++ b/py/tag.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +from typing import Any, NoReturn +import json +import subprocess +import sys + + +def die(reason: str) -> NoReturn: + print(f"[ERROR] {reason}", file=sys.stderr) + sys.exit(1) + + +def usage() -> None: + die("Usage: tag.py ") + + +def parse(tag: str) -> tuple[int, int]: + tag = tag.strip() + if tag[:1] in ("v", "V"): + tag = tag[1:] + major, minor = tag.split(".") + return int(major), int(minor) + + +def main() -> None: + if len(sys.argv) != 2: + usage() + + repo: str = sys.argv[1].strip() + if not repo: + usage() + + try: + raw: str = subprocess.check_output( + ["gh", "release", "list", "--repo", repo, "--limit", "100", "--json", "tagName"], + text=True, stderr=subprocess.STDOUT + ) + except subprocess.CalledProcessError as e: + die(f"gh failed: {e.output.strip()}") + + data: list[dict[str, Any]] = json.loads(raw) + tags: list[str] = [x["tagName"] for x in data if x.get("tagName")] + + next_tag: str + + if not tags: + next_tag = "v1.0" + sys.stdout.write(next_tag) + return + + latest: str = max(tags, key=parse) + major, minor = parse(latest) + + if minor >= 9: + major += 1 + minor = 0 + else: + minor += 1 + + next_tag = f"v{major}.{minor}" + sys.stdout.write(next_tag) + + +if __name__ == "__main__": + main() diff --git a/py/tg.py b/py/tg.py index 481cbae..07bef41 100644 --- a/py/tg.py +++ b/py/tg.py @@ -1,69 +1,80 @@ +# +# Handle Telegram bot api +# + import os import sys from pathlib import Path +from typing import Any, Final, NoReturn + import requests -def die(reason): + +def die(reason) -> NoReturn: print(f"[ERROR] {reason}", file=sys.stderr) sys.exit(1) -def env(name, default = None): - val = os.environ.get(name) - if val is None or val == "": - if default is not None: - return default + +def env(name) -> str: + val: str | None = os.environ.get(name) + if not val: die(f"Cannot get environment variable: {name}") return val -BOT_TOKEN = env("TG_BOT_TOKEN") -CHAT_ID = env("TG_CHAT_ID") -def tg_api_url(method): +BOT_TOKEN: Final[str] = env("TG_BOT_TOKEN") +CHAT_ID: Final[str] = env("TG_CHAT_ID") + + +def tg_api_url(method: str): return f"https://api.telegram.org/bot{BOT_TOKEN}/{method}" -def read_stdin(): + +def read_stdin() -> str: return sys.stdin.read().rstrip() -def tg_send_message(text): + +def tg_send_message(text: str): payload = { "chat_id": CHAT_ID, "parse_mode": "MarkdownV2", "disable_web_page_preview": "true", - "text": text + "text": text, } - resp = requests.post(url=tg_api_url("sendMessage"), json=payload, timeout=30) + resp: requests.Response = requests.post(url=tg_api_url("sendMessage"), json=payload, timeout=30) resp.raise_for_status() j = resp.json() if not j.get("ok"): die(f"sendMessage failed: {j.get('description', 'Unknown error')}") -def tg_send_document(file_path: Path, caption) -> None: + +def tg_send_document(file_path: Path, caption: str) -> None: if not file_path.exists(): die(f"File not found: {file_path}") - payload = { + payload: dict[str, str] = { "chat_id": CHAT_ID, "parse_mode": "MarkdownV2", "caption": caption, "disable_web_page_preview": "true", } with file_path.open("rb") as f: - r = requests.post( + resp: requests.Response = requests.post( tg_api_url("sendDocument"), data=payload, files={"document": (file_path.name, f)}, timeout=180, ) - r.raise_for_status() - j = r.json() + resp.raise_for_status() + j: dict[str, Any] = resp.json() if not j.get("ok"): die(f"sendDocument failed: {j.get('description', 'Unknown error')}") -def usage() -> None: +def usage() -> NoReturn: print( "Usage:\n" - " tg.py msg # reads caption from stdin\n" - " tg.py doc # reads caption from stdin, uploads file\n", + " tg.py msg # reads caption from stdin\n" + " tg.py doc # reads caption from stdin, uploads file\n", file=sys.stderr, ) sys.exit(1) @@ -73,8 +84,8 @@ def main() -> None: if len(sys.argv) < 2: usage() - cmd = sys.argv[1] - text = read_stdin() + cmd: str = sys.argv[1] + text: str = read_stdin() if not text: die("stdin is empty") @@ -90,5 +101,6 @@ def main() -> None: usage() + if __name__ == "__main__": - main() \ No newline at end of file + main()