From e001d2158100339c965f88fbe18da5e8d19bd591 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 13:54:49 +0530 Subject: [PATCH 1/5] feat(core): add versioned build manifest flow --- VERSION | 1 + scripts/core/manifest.sh | 105 +++++++++++++++++++++++++++++++++++++++ scripts/core/module.sh | 42 +++++++++++----- scripts/core/version.sh | 15 ++++++ scripts/patcher_a13.sh | 14 +++++- scripts/patcher_a14.sh | 14 +++++- scripts/patcher_a15.sh | 16 +++++- scripts/patcher_a16.sh | 16 +++++- 8 files changed, 202 insertions(+), 21 deletions(-) create mode 100644 VERSION create mode 100644 scripts/core/manifest.sh create mode 100644 scripts/core/version.sh diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..4a36342 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.0.0 diff --git a/scripts/core/manifest.sh b/scripts/core/manifest.sh new file mode 100644 index 0000000..542c52e --- /dev/null +++ b/scripts/core/manifest.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +# scripts/core/manifest.sh +# Build manifest generation for traceability and reproducibility. + +# Requires: PATCH_ENGINE_VERSION (from version.sh) +# Usage: generate_manifest [workflow_run_id] [workflow_url] +# Output: writes build-manifest.json to $WORK_DIR (or cwd) + +generate_manifest() { + local device="$1" + local base_rom="$2" + local android_version="$3" + local api_level="$4" + local features_csv="$5" + local workflow_run_id="${6:-local}" + local workflow_url="${7:-}" + + local manifest_file="${WORK_DIR:-.}/build-manifest.json" + local git_commit git_branch build_time + + git_commit="$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')" + git_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')" + build_time="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" + + # Build features JSON array from CSV + local features_json="[]" + if [ -n "$features_csv" ]; then + features_json=$(echo "$features_csv" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | \ + awk 'BEGIN{printf "["} NR>1{printf ","} {printf "\"%s\"", $0} END{printf "]"}') + fi + + # Collect checksums of produced artifacts + local checksums_json="{" + local first=1 + for artifact in framework_patched.jar services_patched.jar miui-services_patched.jar miui-framework_patched.jar; do + if [ -f "${WORK_DIR:-.}/$artifact" ]; then + local hash + hash="$(sha256sum "${WORK_DIR:-.}/$artifact" | cut -d' ' -f1)" + [ $first -eq 0 ] && checksums_json+="," + checksums_json+="\"${artifact}\": \"sha256:${hash}\"" + first=0 + fi + done + checksums_json+="}" + + # Read tool versions from lock file + local apktool_version="unknown" + local lock_file="${WORK_DIR:-.}/tools/versions.lock" + if [ -f "$lock_file" ] && command -v python3 >/dev/null 2>&1; then + apktool_version=$(python3 -c " +import json, sys +try: + d = json.load(open('$lock_file')) + print(d.get('apktool', {}).get('version', 'unknown')) +except: + print('unknown') +" 2>/dev/null) + fi + + cat > "$manifest_file" </dev/null 2>&1; then + local zip_hash + zip_hash="$(sha256sum "$zip_file" | cut -d' ' -f1)" + python3 -c " +import json, sys +try: + with open('$manifest_file', 'r') as f: + m = json.load(f) + m['checksums']['module_zip'] = 'sha256:$zip_hash' + with open('$manifest_file', 'w') as f: + json.dump(m, f, indent=2) +except Exception as e: + print(f'[WARN] Failed to update manifest with ZIP checksum: {e}', file=sys.stderr) +" + echo "[INFO] Updated manifest with module ZIP checksum" + fi +} diff --git a/scripts/core/module.sh b/scripts/core/module.sh index 7913c6b..19ccbd4 100755 --- a/scripts/core/module.sh +++ b/scripts/core/module.sh @@ -2,11 +2,23 @@ # scripts/core/module.sh # Module creation functions +# Source dependencies +SCRIPT_CORE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=scripts/core/version.sh +[ -z "$PATCH_ENGINE_VERSION" ] && source "$SCRIPT_CORE_DIR/version.sh" +# shellcheck source=scripts/core/manifest.sh +source "$SCRIPT_CORE_DIR/manifest.sh" + create_module() { - # local api_level="$1" # Currently unused but kept for future use + local api_level="$1" local device_name="$2" local version_name="$3" local kaorios_enabled="${4:-0}" + # New metadata parameters for manifest generation + local android_version="${5:-}" + local features_csv="${6:-}" + local workflow_run_id="${7:-local}" + local workflow_url="${8:-}" log "Creating module using FrameworkPatcherModule for $device_name (v$version_name)" @@ -40,18 +52,8 @@ create_module() { # Remove updateJson line sed -i "/^updateJson=/d" "$module_prop" - # Add universal compatibility properties - { - echo "minMagisk=20400" - echo "ksu=1" - echo "minKsu=10904" - echo "sufs=1" - echo "minSufs=10000" - echo "minApi=34" - echo "maxApi=34" - echo "requireReboot=true" - echo "support=https://t.me/Jefino9488" - } >>"$module_prop" + # Note: compatibility properties (minMagisk, ksu, etc.) are already in the template. + # Do NOT append them again — this previously caused duplication. fi # Update customize.sh with framework replacements @@ -141,6 +143,17 @@ create_module() { log "✓ Kaorios Toolbox files added to module" fi + # Generate build manifest + generate_manifest "$device_name" "$version_name" "${android_version:-unknown}" "${api_level:-unknown}" "$features_csv" "$workflow_run_id" "$workflow_url" + + # Embed manifest in module ZIP + local manifest_src="${WORK_DIR:-.}/build-manifest.json" + if [ -f "$manifest_src" ]; then + mkdir -p "$build_dir/META-INF" + cp "$manifest_src" "$build_dir/META-INF/build-manifest.json" + log "Embedded build manifest in module" + fi + local safe_version safe_version=$(printf "%s" "$version_name" | sed 's/[. ]/-/g') local zip_name="Framework-Patcher-${device_name}-${safe_version}.zip" @@ -160,6 +173,9 @@ create_module() { return 1 fi + # Update manifest with final ZIP checksum + update_manifest_with_zip_checksum "$zip_name" + log "Created module: $zip_name" echo "$zip_name" } diff --git a/scripts/core/version.sh b/scripts/core/version.sh new file mode 100644 index 0000000..3583e18 --- /dev/null +++ b/scripts/core/version.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# scripts/core/version.sh +# Reads the patch engine version from the VERSION file. +# Source this file to get PATCH_ENGINE_VERSION in your environment. + +_VERSION_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/VERSION" + +if [ ! -f "$_VERSION_FILE" ]; then + echo "[ERROR] VERSION file not found at $_VERSION_FILE" >&2 + PATCH_ENGINE_VERSION="unknown" +else + PATCH_ENGINE_VERSION="$(tr -d '[:space:]' < "$_VERSION_FILE")" +fi + +export PATCH_ENGINE_VERSION diff --git a/scripts/patcher_a13.sh b/scripts/patcher_a13.sh index 95e4e1a..cfe09d3 100755 --- a/scripts/patcher_a13.sh +++ b/scripts/patcher_a13.sh @@ -534,6 +534,7 @@ patch_miui_framework() { # Source helper functions SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/helper.sh" +source "$SCRIPT_DIR/core/version.sh" # Main function main() { @@ -626,12 +627,20 @@ EOF # Display selected features echo "============================================" + echo "Framework Patcher Engine v${PATCH_ENGINE_VERSION:-unknown}" + echo "============================================" echo "Selected Features:" [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && echo " ✓ Disable Signature Verification" [ $FEATURE_KAORIOS_TOOLBOX -eq 1 ] && echo " ✓ Include Kaorios Toolbox" [ $FEATURE_ADD_GBOARD -eq 1 ] && echo " ✓ Add Gboard Support" echo "============================================" + # Build features CSV for manifest + local FEATURES_CSV="" + [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}disable_signature_verification" + [ $FEATURE_KAORIOS_TOOLBOX -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}kaorios_toolbox" + [ $FEATURE_ADD_GBOARD -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}add_gboard" + # Initialize environment and check tools init_env ensure_tools || exit 1 @@ -653,8 +662,9 @@ EOF patch_miui_framework fi - # Create module - create_module "$API_LEVEL" "$DEVICE_NAME" "$VERSION_NAME" "$FEATURE_KAORIOS_TOOLBOX" + # Create module with manifest metadata + create_module "$API_LEVEL" "$DEVICE_NAME" "$VERSION_NAME" "$FEATURE_KAORIOS_TOOLBOX" \ + "13" "$FEATURES_CSV" "${WORKFLOW_RUN_ID:-local}" "${WORKFLOW_URL:-}" echo "All patching completed successfully!" } diff --git a/scripts/patcher_a14.sh b/scripts/patcher_a14.sh index 025c911..512f4ad 100644 --- a/scripts/patcher_a14.sh +++ b/scripts/patcher_a14.sh @@ -534,6 +534,7 @@ patch_miui_framework() { # Source helper functions SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/helper.sh" +source "$SCRIPT_DIR/core/version.sh" # Main function main() { @@ -626,12 +627,20 @@ EOF # Display selected features echo "============================================" + echo "Framework Patcher Engine v${PATCH_ENGINE_VERSION:-unknown}" + echo "============================================" echo "Selected Features:" [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && echo " ✓ Disable Signature Verification" [ $FEATURE_KAORIOS_TOOLBOX -eq 1 ] && echo " ✓ Include Kaorios Toolbox" [ $FEATURE_ADD_GBOARD -eq 1 ] && echo " ✓ Add Gboard Support" echo "============================================" + # Build features CSV for manifest + local FEATURES_CSV="" + [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}disable_signature_verification" + [ $FEATURE_KAORIOS_TOOLBOX -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}kaorios_toolbox" + [ $FEATURE_ADD_GBOARD -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}add_gboard" + # Initialize environment and check tools init_env ensure_tools || exit 1 @@ -653,8 +662,9 @@ EOF patch_miui_framework fi - # Create module - create_module "$API_LEVEL" "$DEVICE_NAME" "$VERSION_NAME" "$FEATURE_KAORIOS_TOOLBOX" + # Create module with manifest metadata + create_module "$API_LEVEL" "$DEVICE_NAME" "$VERSION_NAME" "$FEATURE_KAORIOS_TOOLBOX" \ + "14" "$FEATURES_CSV" "${WORKFLOW_RUN_ID:-local}" "${WORKFLOW_URL:-}" echo "All patching completed successfully!" } diff --git a/scripts/patcher_a15.sh b/scripts/patcher_a15.sh index 805de75..6150be7 100644 --- a/scripts/patcher_a15.sh +++ b/scripts/patcher_a15.sh @@ -1269,6 +1269,7 @@ patch_miui_framework() { # Source helper functions SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/helper.sh" +source "$SCRIPT_DIR/core/version.sh" # Main function main() { @@ -1378,6 +1379,8 @@ EOF # Display selected features echo "============================================" + echo "Framework Patcher Engine v${PATCH_ENGINE_VERSION:-unknown}" + echo "============================================" echo "Selected Features:" [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && echo " ✓ Disable Signature Verification" [ $FEATURE_CN_NOTIFICATION_FIX -eq 1 ] && echo " ✓ CN Notification Fix" @@ -1386,6 +1389,14 @@ EOF [ $FEATURE_ADD_GBOARD -eq 1 ] && echo " ✓ Add Gboard Support" echo "============================================" + # Build features CSV for manifest + local FEATURES_CSV="" + [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}disable_signature_verification" + [ $FEATURE_CN_NOTIFICATION_FIX -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}cn_notification_fix" + [ $FEATURE_DISABLE_SECURE_FLAG -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}disable_secure_flag" + [ $FEATURE_KAORIOS_TOOLBOX -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}kaorios_toolbox" + [ $FEATURE_ADD_GBOARD -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}add_gboard" + # Initialize environment and check tools init_env ensure_tools || exit 1 @@ -1407,8 +1418,9 @@ EOF patch_miui_framework fi - # Create module - create_module "$API_LEVEL" "$DEVICE_NAME" "$VERSION_NAME" "$FEATURE_KAORIOS_TOOLBOX" + # Create module with manifest metadata + create_module "$API_LEVEL" "$DEVICE_NAME" "$VERSION_NAME" "$FEATURE_KAORIOS_TOOLBOX" \ + "15" "$FEATURES_CSV" "${WORKFLOW_RUN_ID:-local}" "${WORKFLOW_URL:-}" echo "All patching completed successfully!" } diff --git a/scripts/patcher_a16.sh b/scripts/patcher_a16.sh index 7a216b3..80ca2ef 100755 --- a/scripts/patcher_a16.sh +++ b/scripts/patcher_a16.sh @@ -1294,6 +1294,7 @@ patch_miui_framework() { # Source helper functions SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/helper.sh" +source "$SCRIPT_DIR/core/version.sh" # ---------------------------------------------- # Main entrypoint @@ -1403,6 +1404,8 @@ EOF # Display selected features log "============================================" + log "Framework Patcher Engine v${PATCH_ENGINE_VERSION:-unknown}" + log "============================================" log "Selected Features:" [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && log " ✓ Disable Signature Verification" [ $FEATURE_CN_NOTIFICATION_FIX -eq 1 ] && log " ✓ CN Notification Fix" @@ -1411,6 +1414,14 @@ EOF [ $FEATURE_ADD_GBOARD -eq 1 ] && log " ✓ Add Gboard Support" log "============================================" + # Build features CSV for manifest + local FEATURES_CSV="" + [ $FEATURE_DISABLE_SIGNATURE_VERIFICATION -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}disable_signature_verification" + [ $FEATURE_CN_NOTIFICATION_FIX -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}cn_notification_fix" + [ $FEATURE_DISABLE_SECURE_FLAG -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}disable_secure_flag" + [ $FEATURE_KAORIOS_TOOLBOX -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}kaorios_toolbox" + [ $FEATURE_ADD_GBOARD -eq 1 ] && FEATURES_CSV="${FEATURES_CSV:+$FEATURES_CSV,}add_gboard" + init_env ensure_tools || exit 1 @@ -1435,9 +1446,10 @@ EOF patch_miui_framework fi - # Create module + # Create module with manifest metadata log "Creating Magisk/KSU module..." - create_module "$api_level" "$device_name" "$version_name" "$FEATURE_KAORIOS_TOOLBOX" + create_module "$api_level" "$device_name" "$version_name" "$FEATURE_KAORIOS_TOOLBOX" \ + "16" "$FEATURES_CSV" "${WORKFLOW_RUN_ID:-local}" "${WORKFLOW_URL:-}" log "✓ All operations completed successfully!" } From 81964f07cc12efa400a942a86be4fa320e372792 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 13:54:57 +0530 Subject: [PATCH 2/5] ci(workflows): verify apktool and version sync --- .github/workflows/android13.yml | 35 +++++++++++++++----- .github/workflows/android14.yml | 35 +++++++++++++++----- .github/workflows/android15.yml | 41 +++++++++++++++++++----- .github/workflows/android16.yml | 35 +++++++++++++++----- .github/workflows/feature-test-suite.yml | 19 +++++++++++ tools/versions.lock | 8 +++++ 6 files changed, 141 insertions(+), 32 deletions(-) create mode 100644 tools/versions.lock diff --git a/.github/workflows/android13.yml b/.github/workflows/android13.yml index 08190ee..9518e25 100644 --- a/.github/workflows/android13.yml +++ b/.github/workflows/android13.yml @@ -67,9 +67,17 @@ jobs: - name: Prepare tools directory run: | mkdir -p tools + APKTOOL_URL=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['url'])") + APKTOOL_SHA=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['sha256'])") if [ ! -f tools/apktool.jar ]; then - wget -O tools/apktool.jar https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar + wget -q -O tools/apktool.jar "$APKTOOL_URL" fi + ACTUAL_SHA=$(sha256sum tools/apktool.jar | cut -d' ' -f1) + if [ "$ACTUAL_SHA" != "$APKTOOL_SHA" ]; then + echo "❌ apktool.jar SHA256 mismatch!" + exit 1 + fi + echo "✅ apktool.jar verified" - name: Download framework JARs run: | @@ -234,6 +242,9 @@ jobs: echo "Running patcher with JAR flags: $JAR_FLAGS" echo "Feature flags: $FEATURE_FLAGS" + export WORKFLOW_RUN_ID="${{ github.run_id }}" + export WORKFLOW_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + ./scripts/patcher_a13.sh \ "${{ github.event.inputs.api_level }}" \ "${{ steps.set_codename.outputs.codename }}" \ @@ -257,13 +268,10 @@ jobs: - name: Set Release Info id: release_info run: | - # Format version name to be git tag friendly - SAFE_VERSION=$(echo "${{ github.event.inputs.version_name }}" | sed 's/[^a-zA-Z0-9._-]/_/g') - # Add timestamp to ensure unique tags - TIMESTAMP=$(date +'%Y%m%d-%H%M%S') - RELEASE_TAG="${{ steps.set_codename.outputs.codename }}_${SAFE_VERSION}_${TIMESTAMP}" + RELEASE_TAG="build-tmp-${{ github.run_id }}" + RELEASE_NAME="Android 13 | ${{ steps.set_codename.outputs.codename }} | ${{ github.event.inputs.version_name }}" echo "tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT - echo "name=Android 13 Framework Patch for ${{ github.event.inputs.device_name }} (${{ github.event.inputs.version_name }})" >> $GITHUB_OUTPUT + echo "name=${RELEASE_NAME}" >> $GITHUB_OUTPUT - name: Find Module ZIP id: find_zip @@ -392,7 +400,9 @@ jobs: with: tag_name: ${{ steps.release_info.outputs.tag }} name: ${{ steps.release_info.outputs.name }} - files: ${{ steps.find_zip.outputs.file_path }} + files: | + ${{ steps.find_zip.outputs.file_path }} + build-manifest.json body: | ${{ steps.generate_release_body.outputs.release_body }} @@ -426,6 +436,15 @@ jobs: path: build_log_android13.txt retention-days: 7 + - name: Upload build manifest + if: success() + uses: actions/upload-artifact@v4 + with: + name: build-manifest-${{ github.run_id }} + if-no-files-found: warn + path: build-manifest.json + retention-days: 30 + - name: Send Telegram Notification (Success) if: success() && github.event.inputs.user_id != '' run: | diff --git a/.github/workflows/android14.yml b/.github/workflows/android14.yml index 174ec18..f11cd5e 100644 --- a/.github/workflows/android14.yml +++ b/.github/workflows/android14.yml @@ -67,9 +67,17 @@ jobs: - name: Prepare tools directory run: | mkdir -p tools + APKTOOL_URL=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['url'])") + APKTOOL_SHA=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['sha256'])") if [ ! -f tools/apktool.jar ]; then - wget -O tools/apktool.jar https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar + wget -q -O tools/apktool.jar "$APKTOOL_URL" fi + ACTUAL_SHA=$(sha256sum tools/apktool.jar | cut -d' ' -f1) + if [ "$ACTUAL_SHA" != "$APKTOOL_SHA" ]; then + echo "❌ apktool.jar SHA256 mismatch!" + exit 1 + fi + echo "✅ apktool.jar verified" - name: Download framework JARs run: | @@ -234,6 +242,9 @@ jobs: echo "Running patcher with JAR flags: $JAR_FLAGS" echo "Feature flags: $FEATURE_FLAGS" + export WORKFLOW_RUN_ID="${{ github.run_id }}" + export WORKFLOW_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + ./scripts/patcher_a14.sh \ "${{ github.event.inputs.api_level }}" \ "${{ steps.set_codename.outputs.codename }}" \ @@ -257,13 +268,10 @@ jobs: - name: Set Release Info id: release_info run: | - # Format version name to be git tag friendly - SAFE_VERSION=$(echo "${{ github.event.inputs.version_name }}" | sed 's/[^a-zA-Z0-9._-]/_/g') - # Add timestamp to ensure unique tags - TIMESTAMP=$(date +'%Y%m%d-%H%M%S') - RELEASE_TAG="${{ steps.set_codename.outputs.codename }}_${SAFE_VERSION}_${TIMESTAMP}" + RELEASE_TAG="build-tmp-${{ github.run_id }}" + RELEASE_NAME="Android 14 | ${{ steps.set_codename.outputs.codename }} | ${{ github.event.inputs.version_name }}" echo "tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT - echo "name=Android 14 Framework Patch for ${{ github.event.inputs.device_name }} (${{ github.event.inputs.version_name }})" >> $GITHUB_OUTPUT + echo "name=${RELEASE_NAME}" >> $GITHUB_OUTPUT - name: Find Module ZIP id: find_zip @@ -392,7 +400,9 @@ jobs: with: tag_name: ${{ steps.release_info.outputs.tag }} name: ${{ steps.release_info.outputs.name }} - files: ${{ steps.find_zip.outputs.file_path }} + files: | + ${{ steps.find_zip.outputs.file_path }} + build-manifest.json body: | ${{ steps.generate_release_body.outputs.release_body }} @@ -426,6 +436,15 @@ jobs: path: build_log_android14.txt retention-days: 7 + - name: Upload build manifest + if: success() + uses: actions/upload-artifact@v4 + with: + name: build-manifest-${{ github.run_id }} + if-no-files-found: warn + path: build-manifest.json + retention-days: 30 + - name: Send Telegram Notification (Success) if: success() && github.event.inputs.user_id != '' run: | diff --git a/.github/workflows/android15.yml b/.github/workflows/android15.yml index f92aa85..31ae333 100644 --- a/.github/workflows/android15.yml +++ b/.github/workflows/android15.yml @@ -67,9 +67,21 @@ jobs: - name: Prepare tools directory run: | mkdir -p tools + # Read pinned version from lock file + APKTOOL_URL=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['url'])") + APKTOOL_SHA=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['sha256'])") if [ ! -f tools/apktool.jar ]; then - wget -O tools/apktool.jar https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar + wget -q -O tools/apktool.jar "$APKTOOL_URL" fi + # Verify SHA256 + ACTUAL_SHA=$(sha256sum tools/apktool.jar | cut -d' ' -f1) + if [ "$ACTUAL_SHA" != "$APKTOOL_SHA" ]; then + echo "❌ apktool.jar SHA256 mismatch!" + echo " Expected: $APKTOOL_SHA" + echo " Actual: $ACTUAL_SHA" + exit 1 + fi + echo "✅ apktool.jar verified (SHA256 match)" - name: Download framework JARs run: | @@ -243,6 +255,10 @@ jobs: echo "Running patcher with JAR flags: $JAR_FLAGS" echo "Feature flags: $FEATURE_FLAGS" + # Pass CI metadata for build manifest + export WORKFLOW_RUN_ID="${{ github.run_id }}" + export WORKFLOW_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + ./scripts/patcher_a15.sh \ ${{ github.event.inputs.api_level }} \ "${{ steps.set_codename.outputs.codename }}" \ @@ -266,13 +282,11 @@ jobs: - name: Set Release Info id: release_info run: | - # Format version name to be git tag friendly - SAFE_VERSION=$(echo "${{ github.event.inputs.version_name }}" | sed 's/[^a-zA-Z0-9._-]/_/g') - # Add timestamp to ensure unique tags - TIMESTAMP=$(date +'%Y%m%d-%H%M%S') - RELEASE_TAG="${{ steps.set_codename.outputs.codename }}_${SAFE_VERSION}_${TIMESTAMP}" + # Use temporary tag — will be cleaned up by scheduled workflow + RELEASE_TAG="build-tmp-${{ github.run_id }}" + RELEASE_NAME="Android 15 | ${{ steps.set_codename.outputs.codename }} | ${{ github.event.inputs.version_name }}" echo "tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT - echo "name=Android 15 Framework Patch for ${{ github.event.inputs.device_name }} (${{ github.event.inputs.version_name }})" >> $GITHUB_OUTPUT + echo "name=${RELEASE_NAME}" >> $GITHUB_OUTPUT - name: Find Module ZIP id: find_zip @@ -410,7 +424,9 @@ jobs: with: tag_name: ${{ steps.release_info.outputs.tag }} name: ${{ steps.release_info.outputs.name }} - files: ${{ steps.find_zip.outputs.file_path }} + files: | + ${{ steps.find_zip.outputs.file_path }} + build-manifest.json body: | ${{ steps.generate_release_body.outputs.release_body }} @@ -444,6 +460,15 @@ jobs: path: build_log_android15.txt retention-days: 7 + - name: Upload build manifest + if: success() + uses: actions/upload-artifact@v4 + with: + name: build-manifest-${{ github.run_id }} + if-no-files-found: warn + path: build-manifest.json + retention-days: 30 + - name: Send Telegram Notification (Success) if: success() && github.event.inputs.user_id != '' run: | diff --git a/.github/workflows/android16.yml b/.github/workflows/android16.yml index a5d2f62..ec20f9c 100644 --- a/.github/workflows/android16.yml +++ b/.github/workflows/android16.yml @@ -67,9 +67,17 @@ jobs: - name: Prepare tools directory run: | mkdir -p tools + APKTOOL_URL=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['url'])") + APKTOOL_SHA=$(python3 -c "import json; print(json.load(open('tools/versions.lock'))['apktool']['sha256'])") if [ ! -f tools/apktool.jar ]; then - wget -O tools/apktool.jar https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar + wget -q -O tools/apktool.jar "$APKTOOL_URL" fi + ACTUAL_SHA=$(sha256sum tools/apktool.jar | cut -d' ' -f1) + if [ "$ACTUAL_SHA" != "$APKTOOL_SHA" ]; then + echo "❌ apktool.jar SHA256 mismatch!" + exit 1 + fi + echo "✅ apktool.jar verified" - name: Download framework JARs run: | @@ -243,6 +251,9 @@ jobs: echo "Running patcher with JAR flags: $JAR_FLAGS" echo "Feature flags: $FEATURE_FLAGS" + export WORKFLOW_RUN_ID="${{ github.run_id }}" + export WORKFLOW_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + ./scripts/patcher_a16.sh \ "${{ github.event.inputs.api_level }}" \ "${{ steps.set_codename.outputs.codename }}" \ @@ -266,13 +277,10 @@ jobs: - name: Set Release Info id: release_info run: | - # Format version name to be git tag friendly - SAFE_VERSION=$(echo "${{ github.event.inputs.version_name }}" | sed 's/[^a-zA-Z0-9._-]/_/g') - # Add timestamp to ensure unique tags - TIMESTAMP=$(date +'%Y%m%d-%H%M%S') - RELEASE_TAG="${{ steps.set_codename.outputs.codename }}_${SAFE_VERSION}_${TIMESTAMP}" + RELEASE_TAG="build-tmp-${{ github.run_id }}" + RELEASE_NAME="Android 16 | ${{ steps.set_codename.outputs.codename }} | ${{ github.event.inputs.version_name }}" echo "tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT - echo "name=Android 16 Framework Patch for ${{ github.event.inputs.device_name }} (${{ github.event.inputs.version_name }})" >> $GITHUB_OUTPUT + echo "name=${RELEASE_NAME}" >> $GITHUB_OUTPUT - name: Find Module ZIP id: find_zip @@ -401,7 +409,9 @@ jobs: with: tag_name: ${{ steps.release_info.outputs.tag }} name: ${{ steps.release_info.outputs.name }} - files: ${{ steps.find_zip.outputs.file_path }} + files: | + ${{ steps.find_zip.outputs.file_path }} + build-manifest.json body: | ${{ steps.generate_release_body.outputs.release_body }} @@ -435,6 +445,15 @@ jobs: path: build_log_android16.txt retention-days: 7 + - name: Upload build manifest + if: success() + uses: actions/upload-artifact@v4 + with: + name: build-manifest-${{ github.run_id }} + if-no-files-found: warn + path: build-manifest.json + retention-days: 30 + - name: Send Telegram Notification (Success) if: success() && github.event.inputs.user_id != '' run: | diff --git a/.github/workflows/feature-test-suite.yml b/.github/workflows/feature-test-suite.yml index c7bace9..a99760a 100644 --- a/.github/workflows/feature-test-suite.yml +++ b/.github/workflows/feature-test-suite.yml @@ -10,6 +10,25 @@ on: workflow_dispatch: jobs: + version-check: + name: Version consistency check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Validate VERSION matches CHANGELOG + run: | + VERSION=$(tr -d '[:space:]' < VERSION) + if [ -z "$VERSION" ]; then + echo "❌ VERSION file is empty" + exit 1 + fi + if ! grep -q "## \[${VERSION}\]" CHANGELOG.md; then + echo "❌ VERSION file ($VERSION) has no matching entry in CHANGELOG.md" + echo "Add a '## [${VERSION}]' section to CHANGELOG.md before merging." + exit 1 + fi + echo "✅ VERSION $VERSION matches CHANGELOG.md" + feature-tests: name: Android ${{ matrix.android_version }} feature tests runs-on: ubuntu-latest diff --git a/tools/versions.lock b/tools/versions.lock new file mode 100644 index 0000000..a80adcd --- /dev/null +++ b/tools/versions.lock @@ -0,0 +1,8 @@ +{ + "apktool": { + "version": "2.9.3", + "url": "https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar", + "sha256": "effb69dab2f93806cafc0d232f6be32c2551b8d51c67650f575e46c016908fdd", + "filename": "apktool.jar" + } +} From a757221b251135ff0471698468dd02eb707e3ca5 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 13:54:59 +0530 Subject: [PATCH 3/5] ci(release): add engine and index workflows --- .github/workflows/cleanup-tags.yml | 77 +++++++++++ .github/workflows/release-engine.yml | 101 +++++++++++++++ .github/workflows/update-build-index.yml | 158 +++++++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 .github/workflows/cleanup-tags.yml create mode 100644 .github/workflows/release-engine.yml create mode 100644 .github/workflows/update-build-index.yml diff --git a/.github/workflows/cleanup-tags.yml b/.github/workflows/cleanup-tags.yml new file mode 100644 index 0000000..e943470 --- /dev/null +++ b/.github/workflows/cleanup-tags.yml @@ -0,0 +1,77 @@ +name: Cleanup Build Tags + +on: + schedule: + # Run weekly on Sunday at 03:00 UTC + - cron: '0 3 * * 0' + workflow_dispatch: + inputs: + dry_run: + description: 'Dry run — show what would be deleted without deleting' + required: false + default: 'true' + type: choice + options: + - 'true' + - 'false' + +jobs: + cleanup: + name: Cleanup temporary build tags + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # need full history for tags + + - name: Find and delete temporary and legacy build tags + env: + DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} + run: | + echo "Scanning for temporary and legacy build tags..." + + # New temporary tags + legacy patterns from older workflows. + # Keep semantic version tags (vX.Y.Z) intact. + TAGS=$( + { + git tag -l 'build-tmp-*' + git tag -l 'android13-*' + git tag -l 'android14-*' + git tag -l 'android15-*' + git tag -l 'android16-*' + } | sed '/^$/d' | sort -u + ) + + COUNT=$(printf '%s\n' "$TAGS" | sed '/^$/d' | wc -l | tr -d ' ') + + echo "Found $COUNT cleanup candidate tags" + + if [ "$COUNT" -eq 0 ]; then + echo "No temporary tags to clean up" + exit 0 + fi + + if [ "$DRY_RUN" = "true" ]; then + echo "=== DRY RUN — would delete these tags ===" + echo "$TAGS" + echo "=== End of dry run ===" + else + echo "Deleting $COUNT temporary build tags..." + printf '%s\n' "$TAGS" | while read -r tag; do + if [ -n "$tag" ]; then + git push --delete origin "$tag" 2>/dev/null || echo "Failed to delete $tag (may already be gone)" + git tag -d "$tag" 2>/dev/null || true + fi + done + echo "✅ Cleanup complete" + fi + + - name: Summary + run: | + REMAINING=$(git tag | wc -l) + echo "Total remaining tags: $REMAINING" + echo "Engine release tags:" + git tag -l 'v*' | head -20 diff --git a/.github/workflows/release-engine.yml b/.github/workflows/release-engine.yml new file mode 100644 index 0000000..26b9fb1 --- /dev/null +++ b/.github/workflows/release-engine.yml @@ -0,0 +1,101 @@ +name: Release Patch Engine + +on: + workflow_dispatch: + inputs: + version: + description: 'Engine version to release (must match VERSION file, e.g., 3.0.0)' + required: true + type: string + +jobs: + release: + name: Release Engine v${{ github.event.inputs.version }} + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate version + run: | + FILE_VERSION=$(tr -d '[:space:]' < VERSION) + INPUT_VERSION="${{ github.event.inputs.version }}" + if [ "$FILE_VERSION" != "$INPUT_VERSION" ]; then + echo "❌ VERSION file ($FILE_VERSION) does not match input ($INPUT_VERSION)" + echo "Update the VERSION file first, then run this workflow." + exit 1 + fi + echo "✅ Version validated: v${INPUT_VERSION}" + + - name: Check tag doesn't already exist + run: | + if git rev-parse "v${{ github.event.inputs.version }}" >/dev/null 2>&1; then + echo "❌ Tag v${{ github.event.inputs.version }} already exists" + exit 1 + fi + + - name: Generate changelog excerpt + id: changelog + run: | + VERSION="${{ github.event.inputs.version }}" + # Extract the section for this version from CHANGELOG.md + EXCERPT=$(awk "/^## \[${VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md) + if [ -z "$EXCERPT" ]; then + EXCERPT="No changelog entry found for v${VERSION}. Please update CHANGELOG.md." + fi + # Output using heredoc delimiter + echo "body<> $GITHUB_OUTPUT + echo "$EXCERPT" >> $GITHUB_OUTPUT + echo "CHANGELOG_EOF" >> $GITHUB_OUTPUT + + - name: Create engine release + id: create_release + uses: softprops/action-gh-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ github.event.inputs.version }} + name: "Patch Engine v${{ github.event.inputs.version }}" + body: | + # Patch Engine v${{ github.event.inputs.version }} + + ${{ steps.changelog.outputs.body }} + + --- + **Full Changelog:** [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/master/CHANGELOG.md) + make_latest: true + generate_release_notes: false + + - name: Checkout gh-pages + uses: actions/checkout@v4 + with: + ref: gh-pages + path: gh-pages + + - name: Update latest stable JSON + run: | + mkdir -p gh-pages/builds + + cat > gh-pages/builds/latest.json < Date: Sun, 26 Apr 2026 13:55:01 +0530 Subject: [PATCH 4/5] docs(release): document platform upgrade --- CHANGELOG.md | 27 ++++ RELEASE.md | 42 +++++++ implementation_plan.md | 275 +++++++++++++++++++++++++++++++++++++++++ task.md | 28 +++++ 4 files changed, 372 insertions(+) create mode 100644 RELEASE.md create mode 100644 implementation_plan.md create mode 100644 task.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 085a02a..2d1cff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [3.0.0] - 2026-04-26 + +### Platform Upgrade - Production Hardening + +### Added + +- `VERSION` file as the single source of patch engine version (`3.0.0`) +- `scripts/core/version.sh` to export `PATCH_ENGINE_VERSION` +- `scripts/core/manifest.sh` for structured `build-manifest.json` generation +- `tools/versions.lock` with pinned apktool URL/version/SHA256 +- Build index workflows and release workflows for platform-level automation +- `RELEASE.md` as human-readable stable release pointer + +### Changed + +- All patcher scripts now show the patch engine version in startup banner +- Module generation now embeds `META-INF/build-manifest.json` +- Build flows now include manifest artifacts and reproducibility metadata +- Feature test workflow now enforces VERSION/CHANGELOG consistency + +### Fixed + +- Removed duplicated compatibility properties from `build_module/module.prop` +- Standardized release metadata generation across Android build workflows + +--- + ## [2.0.0] - 2025-10-13 ### Major Release - Feature Selection System diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..ee74124 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,42 @@ +# Current Stable Release + +**Patch Engine Version:** v3.0.0 +**Release Date:** 2026-04-26 +**Status:** Stable + +## Supported Platforms + +| Android Version | API Level | Status | +|-----------------|-----------|--------| +| Android 13 | 33 | ✅ Supported | +| Android 14 | 34 | ✅ Supported | +| Android 15 | 35 | ✅ Supported | +| Android 16 | 36 | ✅ Supported | + +## Available Features + +| Feature | A13 | A14 | A15 | A16 | +|---------|-----|-----|-----|-----| +| Disable Signature Verification | ✅ | ✅ | ✅ | ✅ | +| CN Notification Fix | — | — | ✅ | ✅ | +| Disable Secure Flag | — | — | ✅ | ✅ | +| Kaorios Toolbox | ✅ | ✅ | ✅ | ✅ | +| Add Gboard Support | ✅ | ✅ | ✅ | ✅ | + +## How to Get a Build + +- **Telegram Bot**: [@FrameworkPatcherBot](https://t.me/FrameworkPatcherBot) +- **Web Interface**: [framework-patcher-v2.vercel.app](https://framework-patcher-v2.vercel.app) +- **GitHub Actions**: Trigger manually from the [Actions tab](https://github.com/FrameworksForge/FrameworkPatcher/actions) + +## Build Index API + +Machine-readable build index available at: +`https://frameworksforge.github.io/FrameworkPatcher/builds/index.json` + +## Compatibility + +All modules are compatible with: +- Magisk (v20.4+) +- KernelSU (v0.9.4+) +- SUFS diff --git a/implementation_plan.md b/implementation_plan.md new file mode 100644 index 0000000..87c931c --- /dev/null +++ b/implementation_plan.md @@ -0,0 +1,275 @@ +# Production-Grade Platform Upgrade — v2 (Revised) + +Addresses all 5 critical gaps identified in review. + +--- + +## Changes from v1 + +| Issue | v1 (broken) | v2 (fixed) | +|-------|-------------|------------| +| Per-build tags | Renamed but still created | **Deleted after release creation** — zero tag accumulation | +| Build index | None | **`gh-pages` JSON index** — queryable by device/ROM | +| Reproducibility | Manifest = docs only | **Pinned deps + SHA256 checksums** | +| VERSION sync | Manual | **CI-enforced** — build fails on mismatch | +| Latest stable API | Human-only RELEASE.md | **Machine-readable JSON endpoint** | + +--- + +## Open Questions + +1. **Tag cleanup**: Keep existing 3,087 tags, delete them, or archive to a file then delete? +2. **Android 13**: Include in upgrades or treat as frozen/legacy? +3. **GitHub Pages**: Is `gh-pages` branch acceptable for hosting the build index, or prefer a different hosting? + +--- + +## Component 1: VERSION File + version.sh + +#### [NEW] `VERSION` +``` +3.0.0 +``` + +#### [NEW] `scripts/core/version.sh` +Reads VERSION file, exports `PATCH_ENGINE_VERSION`. Sourced by all patcher scripts. + +--- + +## Component 2: Build Manifest System + +#### [NEW] `scripts/core/manifest.sh` + +`generate_manifest()` function that produces `build-manifest.json`: + +```json +{ + "schema_version": "1.0", + "patch_engine_version": "3.0.0", + "git_commit": "ebbf4e1", + "device": "vermeer", + "base_rom": "OS3.0.7.0", + "android_version": "15", + "api_level": "35", + "features": ["disable_signature_verification"], + "build_time": "2026-04-26T12:00:00Z", + "checksums": { + "module_zip": "sha256:abc123...", + "framework_patched": "sha256:def456..." + }, + "tool_versions": { + "apktool": "2.9.3" + }, + "workflow_run_id": "12345678" +} +``` + +Key additions vs v1: **SHA256 checksums** of all outputs + **tool version pins**. + +#### [MODIFY] `scripts/core/module.sh` +- Import `manifest.sh` +- Call `generate_manifest()` in `create_module()` +- Embed manifest at `META-INF/build-manifest.json` inside module ZIP +- Compute SHA256 of module ZIP after creation, update manifest + +#### [MODIFY] All 4 patcher scripts +- Source `version.sh` at top +- Print engine version in startup banner +- Pass metadata through to `create_module()` + +--- + +## Component 3: Reproducibility + +#### [NEW] `tools/versions.lock` +```json +{ + "apktool": { + "version": "2.9.3", + "url": "https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar", + "sha256": "" + } +} +``` + +#### [MODIFY] All 4 CI workflows — "Prepare tools" step +- Read tool URL + hash from `tools/versions.lock` +- Verify SHA256 after download (fail build if mismatch) +- Pin `actions/checkout@v4`, `actions/upload-artifact@v4` (already pinned ✓) + +#### [MODIFY] `.gitmodules` +- Pin kaorios_toolbox submodule to a specific commit + +--- + +## Component 4: Zero Per-Build Git Tags + +#### [MODIFY] All 4 CI workflows — Release steps + +**Pattern: create tag → create release → delete tag.** + +The release persists after tag deletion. No tag accumulation. + +```yaml +- name: Set Release Info + id: release_info + run: | + RELEASE_TAG="build-tmp-${{ github.run_id }}" + RELEASE_NAME="Android 15 | ${{ steps.set_codename.outputs.codename }} | ${{ github.event.inputs.version_name }}" + echo "tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT + echo "name=${RELEASE_NAME}" >> $GITHUB_OUTPUT + +- name: Create Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.release_info.outputs.tag }} + name: ${{ steps.release_info.outputs.name }} + files: | + ${{ steps.find_zip.outputs.file_path }} + build-manifest.json + +- name: Delete temporary tag + if: success() + run: git push --delete origin "${{ steps.release_info.outputs.tag }}" || true +``` + +Result: releases exist with assets, **zero new tags in the repo**. + +--- + +## Component 5: Build Index (gh-pages) + +#### [NEW] `.github/workflows/update-build-index.yml` + +Triggered after each build workflow completes (via `workflow_run`). Updates `builds/index.json` on the `gh-pages` branch. + +**Index structure:** +```json +{ + "schema_version": "1.0", + "last_updated": "2026-04-26T12:00:00Z", + "engine_version": "3.0.0", + "builds": { + "vermeer": { + "OS3.0.7.0": { + "android_version": "15", + "release_url": "https://github.com/.../releases/12345", + "download_url": "https://github.com/.../download/...", + "patch_version": "3.0.0", + "features": ["disable_signature_verification"], + "build_time": "2026-04-26T12:00:00Z", + "checksum": "sha256:abc123..." + } + } + } +} +``` + +**Queryable at:** `https://frameworksforge.github.io/FrameworkPatcher/builds/index.json` + +This workflow: +1. Checks out `gh-pages` +2. Downloads manifest artifact from the triggering run +3. Merges into `index.json` (upsert by device+ROM key) +4. Commits and pushes + +--- + +## Component 6: Latest Stable API + +#### [NEW] `builds/latest.json` (on gh-pages) + +```json +{ + "engine_version": "3.0.0", + "release_url": "https://github.com/FrameworksForge/FrameworkPatcher/releases/tag/v3.0.0", + "release_date": "2026-04-26", + "supported_android": ["13", "14", "15", "16"] +} +``` + +Updated by the engine release workflow (Component 7). Machine-readable endpoint at: +`https://frameworksforge.github.io/FrameworkPatcher/builds/latest.json` + +#### [NEW] `RELEASE.md` +Human-readable pointer to current stable, features, and how to get builds. + +--- + +## Component 7: Engine Release Workflow + +#### [NEW] `.github/workflows/release-engine.yml` + +- Manual trigger with `version` input +- Validates `VERSION` file matches input +- Creates SemVer Git tag (`v3.0.0`) — these are the **only** tags +- Creates GitHub Release marked as "Latest" +- Updates `builds/latest.json` on `gh-pages` + +--- + +## Component 8: CI-Enforced Version Sync + +#### [MODIFY] `.github/workflows/feature-test-suite.yml` + +Add a new job `version-check` that runs on every push/PR: + +```yaml +version-check: + name: Version consistency check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Validate VERSION matches CHANGELOG + run: | + VERSION=$(cat VERSION) + if ! grep -q "## \[${VERSION}\]" CHANGELOG.md; then + echo "❌ VERSION file ($VERSION) has no matching entry in CHANGELOG.md" + exit 1 + fi + echo "✅ VERSION $VERSION matches CHANGELOG.md" +``` + +Fails the build if `VERSION` and `CHANGELOG.md` drift. + +--- + +## Component 9: CHANGELOG + module.prop Fixes + +#### [MODIFY] `CHANGELOG.md` +Add `[3.0.0]` section documenting the platform upgrade. + +#### [MODIFY] `build_module/module.prop` +Remove duplicated properties (lines 16-24 are exact copies of 7-15). + +--- + +## Implementation Order + +``` +1. VERSION + version.sh (pure additive) +2. tools/versions.lock (pure additive) +3. manifest.sh (pure additive) +4. Update module.sh (backward compatible) +5. Update patcher scripts (backward compatible) +6. Update CI workflows (⚡ behavioral change — tags) +7. Build index workflow (new workflow) +8. Engine release workflow (new workflow) +9. Version check in test suite (CI guard) +10. CHANGELOG + module.prop fixes (cleanup) +``` + +Steps 1-5 are safe and non-breaking. Step 6 is the critical behavioral change. + +--- + +## Verification Plan + +1. **YAML validation** — parse all workflow files +2. **Local patcher test** — run with test JARs, verify manifest in ZIP +3. **Version check** — verify CI catches VERSION/CHANGELOG mismatch +4. **Workflow dry-run** — trigger a test build, verify: + - No new Git tag persists after release + - Release has manifest + ZIP attached + - Build index updates on gh-pages +5. **Feature test suite** — existing tests still pass diff --git a/task.md b/task.md new file mode 100644 index 0000000..0f5f0b9 --- /dev/null +++ b/task.md @@ -0,0 +1,28 @@ +# Platform Upgrade — Task Tracker + +## Phase 1: Foundation (non-breaking) +- [x] Create `VERSION` file (3.0.0) +- [x] Create `scripts/core/version.sh` +- [x] Create `tools/versions.lock` with apktool SHA256 +- [x] Create `scripts/core/manifest.sh` +- [x] Fix `build_module/module.prop` duplication + +## Phase 2: Integration (backward-compatible) +- [x] Update `scripts/core/module.sh` — embed manifest in ZIP +- [x] Update patcher scripts (a13/a14/a15/a16) — source version.sh, pass metadata +- [x] Update `CHANGELOG.md` — add 3.0.0 entry + +## Phase 3: CI Restructuring (behavioral change) +- [x] Update all 4 patcher workflows — deferred tag cleanup, manifest upload, structured release body +- [x] Add version-check job to `feature-test-suite.yml` + +## Phase 4: Platform Infrastructure +- [x] Create `update-build-index.yml` — gh-pages index with concurrency control, JSON validation, per-device split +- [x] Create `release-engine.yml` — SemVer engine releases +- [x] Create `cleanup-tags.yml` — scheduled batch tag cleanup (old + build-tmp) +- [x] Create `RELEASE.md` + +## Phase 5: Verification +- [x] Validate all YAML files parse correctly +- [x] Verify VERSION/CHANGELOG consistency check works +- [x] Lint shell scripts From 09d8b6ecafb9ee416a40b38201bbddde52bfd68c Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 14:00:38 +0530 Subject: [PATCH 5/5] fix(core): guard version var in strict mode --- scripts/core/module.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/core/module.sh b/scripts/core/module.sh index 19ccbd4..3e1d4a1 100755 --- a/scripts/core/module.sh +++ b/scripts/core/module.sh @@ -5,7 +5,9 @@ # Source dependencies SCRIPT_CORE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=scripts/core/version.sh -[ -z "$PATCH_ENGINE_VERSION" ] && source "$SCRIPT_CORE_DIR/version.sh" +if [ -z "${PATCH_ENGINE_VERSION:-}" ]; then + source "$SCRIPT_CORE_DIR/version.sh" +fi # shellcheck source=scripts/core/manifest.sh source "$SCRIPT_CORE_DIR/manifest.sh"