Skip to content

feat: bundle Mieru native binary (no external plugin required)#12

Merged
hawkff merged 8 commits into
mainfrom
feature/mieru-bundled-binary
Jun 15, 2026
Merged

feat: bundle Mieru native binary (no external plugin required)#12
hawkff merged 8 commits into
mainfrom
feature/mieru-bundled-binary

Conversation

@hawkff

@hawkff hawkff commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Makes Mieru work without the separate moe.matsuri.exe.mieru plugin by building the
Mieru client from source for all Android ABIs and bundling it as
app/executableSo/<abi>/libmieru.so.

How it works

Reuses the existing bundled-binary mechanism (the same one Hysteria uses):

  • app/executableSo/<abi>/libmieru.so is packaged into the APK (via the
    jniLibs.srcDir("executableSo") hook) and extracted to nativeLibraryDir at install.
  • PluginManager.initNativeInternal resolves mieru-plugin -> libmieru.so from
    nativeLibraryDir. If the bundled binary is absent it still falls back to the external
    APK plugin, so nothing breaks for existing plugin users.
  • The existing MieruBean / MieruFmt.buildMieruConfig / BoxInstance run-contract is
    unchanged: invoked as <path> run, config via MIERU_CONFIG_JSON_FILE, VPN socket
    protection via MIERU_PROTECT_PATH. Verified upstream mieru v3.34.0 still honors both.

Changes

  • buildScript/lib/mieru.sh (./run lib mieru): cross-compiles enfein/mieru v3.34.0
    via the NDK for arm64-v8a, armeabi-v7a, x86, x86_64. (Upstream only ships an arm64
    prebuilt and the old matsuri plugin shipped arm64+x86_64; this covers all four.)
  • PluginManager.initNativeInternal: add "mieru-plugin" -> soIfExist("libmieru.so").
  • Executable.EXECUTABLES: add libmieru.so for orphan-process cleanup.
  • ci.yml, build.yml, preview.yml, release.yml: a Native Build (Mieru) job builds
    and caches the binaries (Go+NDK), the build job restores the cache, and a
    Verify Mieru Artifacts step fails fast if any ABI's libmieru.so is missing — so
    release/preview APKs always bundle Mieru.

Verification (AWS Linux builder)

  • ./run lib mieru produces all 4 ABI binaries (proper Android PIE executables).
  • ./gradlew app:assembleOssDebug and assembleOssRelease succeed; verified
    lib/<abi>/libmieru.so is packaged in the APK for all 4 ABIs (debug and release).
  • Confirmed the Mieru build works under both NDK 25.0.8775105 and NDK 27 (the
    ubuntu-latest default), so the CI job resolves the runner's NDK via env_ndk.sh's
    ANDROID_NDK_HOME fallback — the same mechanism the existing libcore job uses.
  • Build-script robustness: validates ANDROID_NDK_HOME, supports linux-x86_64 /
    darwin-x86_64 / darwin-arm64 NDK hosts, and re-clones if the source checkout is corrupted.

Notes on rejected review suggestions

  • "Bump Go 1.24.9 -> 1.24.13": out of scope. The pin matches go.mod's toolchain go1.24.9 (set in the merged Go-toolchain-align PR); a Go patch bump is a separate
    maintenance concern.
  • "Add setup-ndk for 25.0.8775105 in the Mieru CI job": unnecessary. Verified the build
    works with the runner's default NDK (27) via the existing env_ndk.sh fallback,
    consistent with the libcore job which uses the same pattern.

Runtime testing note

Build/packaging verified (binary present + executable contract intact). Live proxy
runtime test pending the batched emulator QA (EC2 metal/vCPU quota increase pending).

Scope

  • 1 new build script, 2 small Kotlin changes, 4 CI workflow updates. No core/Go changes,
    no Android UI changes (the existing plugin-resolution fallback handles UX), no DB/
    serialization changes. Binaries are gitignored and built in CI (not committed).

hawkff added 7 commits June 15, 2026 15:49
Build the Mieru client from source for all 4 Android ABIs and bundle it as
app/executableSo/<abi>/libmieru.so, so Mieru profiles work without installing
the separate moe.matsuri.exe.mieru plugin.

- buildScript/lib/mieru.sh: cross-compiles enfein/mieru v3.34.0 via the NDK
  for arm64-v8a, armeabi-v7a, x86, x86_64 (./run lib mieru).
- PluginManager.initNativeInternal: resolve mieru-plugin -> libmieru.so from
  nativeLibraryDir, mirroring the bundled-Hysteria mechanism. Falls back to the
  external APK plugin when the bundled binary is absent.
- Executable.EXECUTABLES: add libmieru.so so orphaned processes are cleaned up.
- ci.yml: build + cache the Mieru binaries (Go+NDK) and restore before Gradle.

Reuses the existing MieruBean / MieruFmt buildMieruConfig / BoxInstance run
contract (config via MIERU_CONFIG_JSON_FILE, socket protection via
MIERU_PROTECT_PATH) unchanged; upstream mieru v3 honors both.
Address review feedback and ensure shipping APKs bundle Mieru:
- Add the Mieru native-build job + cache restore + artifact verification to
  build.yml, preview.yml, release.yml (previously only ci.yml had it), so
  release/preview APKs also bundle libmieru.so.
- Include buildScript/init/env.sh in the Mieru cache-status hash (mieru.sh
  sources it).
- Pin MIERU_VERSION as a workflow env and include it in the cache key so a
  version override invalidates stale binaries.
- Add a 'Verify Mieru Artifacts' step in each build job that fails fast if any
  ABI's libmieru.so is missing (guards against a silent cache miss shipping an
  APK without the bundled binary).
- mieru.sh: validate ANDROID_NDK_HOME is set before use.
GitHub Actions cache restore does not reliably preserve the execute bit, so
testing with -x could falsely fail on a cache hit. The runtime execute
permission is applied by Android when extracting from the APK; here we only
need to confirm the binary exists.
Fail fast with a clear message if neither the linux-x86_64 nor darwin-x86_64
NDK LLVM toolchain dir exists, instead of a cryptic CC-not-found later.
Guard the incremental-fetch path: if fetch/checkout fail (e.g. a corrupted
.mieru-build from a prior failed run), remove and clone fresh instead of
erroring out.
Add a darwin-arm64 fallback for the NDK LLVM toolchain so local Mieru builds
work natively on Apple Silicon Macs (newer NDKs ship darwin-arm64).
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@hawkff, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 7 hours and 54 minutes. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fcd64a7d-9820-4e5e-a69d-09bf67eaf513

📥 Commits

Reviewing files that changed from the base of the PR and between f685fc6 and 8b04339.

📒 Files selected for processing (7)
  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/preview.yml
  • .github/workflows/release.yml
  • app/src/main/java/io/nekohasekai/sagernet/bg/Executable.kt
  • app/src/main/java/io/nekohasekai/sagernet/plugin/PluginManager.kt
  • buildScript/lib/mieru.sh
📝 Walkthrough

Walkthrough

Adds Mieru as a native plugin: a new buildScript/lib/mieru.sh cross-compiles libmieru.so for four Android ABIs using the NDK. All three primary CI/CD workflows gain a dedicated mieru job with versioned caching and artifact verification. Executable.kt and PluginManager.kt register libmieru.so at runtime.

Changes

Mieru Native Plugin Integration

Layer / File(s) Summary
Cross-compilation build script
buildScript/lib/mieru.sh
New bash script that validates ANDROID_NDK_HOME, resolves the NDK LLVM toolchain, clones Mieru at the pinned tag (MIERU_VERSION, default v3.34.0), and runs go build for arm64-v8a, armeabi-v7a, x86, and x86_64, placing stripped libmieru.so files under app/executableSo/<abi>/.
CI/CD mieru job and build job wiring
.github/workflows/build.yml, .github/workflows/ci.yml, .github/workflows/preview.yml
Each workflow gains a MIERU_VERSION environment variable and a mieru job (hashes build scripts, caches app/executableSo, installs Go on cache miss, runs ./run lib mieru). The build job is updated to depend on mieru and gains steps to restore the Mieru cache and verify libmieru.so presence for all four ABIs before the Gradle build.
Android runtime registration
app/src/main/java/io/nekohasekai/sagernet/bg/Executable.kt, app/src/main/java/io/nekohasekai/sagernet/plugin/PluginManager.kt
libmieru.so is added to the EXECUTABLES set (used by killAll) and a mieru-plugin branch is added to PluginManager.initNativeInternal to resolve libmieru.so from nativeLibraryDir.

Sequence Diagram(s)

sequenceDiagram
  participant mieru_job as mieru job
  participant cache as GitHub Actions Cache
  participant build_job as build job
  participant gradle as Gradle Build

  mieru_job->>mieru_job: compute mieru_status hash
  mieru_job->>cache: restore app/executableSo (key: MIERU_VERSION+hash)
  alt cache miss
    mieru_job->>mieru_job: install Go
    mieru_job->>mieru_job: ./run lib mieru → libmieru.so ×4 ABIs
    mieru_job->>cache: save app/executableSo
  end
  mieru_job-->>build_job: job complete (needs satisfied)
  build_job->>cache: restore mieru-cache
  build_job->>build_job: verify libmieru.so for each ABI
  build_job->>gradle: run Android Gradle build
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 A library hops in from Go's distant land,
Cross-compiled for arms with a NDK hand.
Three workflows now cache what the rabbit has built,
With hashes and versions and no sense of guilt.
libmieru.so lands in its Android den —
The plugin is wired, let the tunneling begin! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: bundling the Mieru native binary to eliminate the need for an external plugin.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the feature, implementation approach, verification steps, and addressing prior review feedback.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@hawkff hawkff marked this pull request as ready for review June 15, 2026 20:19
@hawkff

hawkff commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

Please focus on the bundled-binary mechanism, the plugin-resolution fallback (bundled -> external APK), CI cross-compilation wiring, and process lifecycle/cleanup.

Two notes on prior local-review findings I assessed and did not apply:

  1. NDK in the Mieru CI job: I verified mieru cross-compiles successfully with BOTH NDK 25.0.8775105 and NDK 27 (the ubuntu-latest default). The job resolves the runner's NDK via env_ndk.sh's ANDROID_NDK_HOME fallback, identical to the existing libcore job. No setup-ndk step needed.
  2. Go 1.24.9: intentionally matches go.mod's toolchain go1.24.9 (from the merged Go-align PR); a Go patch bump is out of scope here.

All 4 ABIs verified packaged in both debug and release APKs on the builder.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get the list of changed files and diffs
gh pr view 12 --repo hawkff/NekoBoxForAndroid --json files,title,body | jq '.files[].path'

Length of output: 485


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get the full diff
gh pr diff 12 --repo hawkff/NekoBoxForAndroid

Length of output: 13300


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== .gitignore (root) ==="
cat .gitignore 2>/dev/null || echo "not found"

echo ""
echo "=== app/.gitignore ==="
cat app/.gitignore 2>/dev/null || echo "not found"

echo ""
echo "=== soIfExist in PluginManager.kt ==="
grep -n "soIfExist\|initNativeInternal\|nativeLibraryDir\|fallback\|pluginId\|external" \
  app/src/main/java/io/nekohasekai/sagernet/plugin/PluginManager.kt

echo ""
echo "=== Executable.kt full EXECUTABLES context ==="
grep -n -A 30 "EXECUTABLES\|killAll\|killProcess" \
  app/src/main/java/io/nekohasekai/sagernet/bg/Executable.kt | head -80

echo ""
echo "=== env.sh sources ==="
cat buildScript/init/env.sh 2>/dev/null || echo "not found"

echo ""
echo "=== env_ndk.sh ==="
cat buildScript/init/env_ndk.sh 2>/dev/null || echo "not found"

echo ""
echo "=== check executableSo dir ==="
find app/executableSo -name "*.so" 2>/dev/null | head -20 || echo "no executableSo files in tree"

echo ""
echo "=== existing libcore / hysteria build scripts for comparison ==="
ls buildScript/lib/ 2>/dev/null

echo ""
echo "=== hysteria.sh for pattern reference ==="
cat buildScript/lib/hysteria.sh 2>/dev/null | head -60 || echo "not found"

echo ""
echo "=== check CGO usage in mieru upstream cmd/mieru or main.go ==="
# Can't run go build, but see if we can inspect the mieru source for cgo
# Just note the build_abi params; can't clone here
echo "Cannot access upstream source in sandbox."

Length of output: 6325



@hawkff: Acknowledged on both prior findings — NDK fallback via env_ndk.sh and Go 1.24.9 matching go.mod toolchain. Here is the full review.


Review Summary

The overall architecture is sound and consistent with the existing Hysteria bundled-binary pattern. The plugin fallback chain, process-lifecycle integration, and CI cache design are all correct. A few issues worth addressing:


🔴 Medium

1. .mieru-build not in .gitignore

mieru.sh creates .mieru-build/ in the repo root but it is not listed in .gitignore. A local ./run lib mieru leaves an untracked ~50 MB git checkout that git status will surface and could accidentally be staged.

# .gitignore
+/.mieru-build

2. env_ndk.sh excluded from the Mieru Status cache-key hash

All four workflows compute:

run: cat buildScript/lib/mieru.sh buildScript/init/env.sh | sha1sum > mieru_status

env.sh sources env_ndk.sh, whose NDK version pin (25.0.8775105) directly controls which compiler is used. If the NDK pin in env_ndk.sh is bumped, the cache key won't change and stale binaries built with the old NDK will be reused.

-run: cat buildScript/lib/mieru.sh buildScript/init/env.sh | sha1sum > mieru_status
+run: cat buildScript/lib/mieru.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > mieru_status

(Applies to all four workflows in both the mieru and build jobs.)


🟡 Minor

3. MIERU_VERSION duplicated across 8 job-level env: blocks

Each of the four workflows defines MIERU_VERSION: v3.34.0 in both the mieru job and the build job. A workflow-level env: block reduces this to 4 definitions and makes version bumps a single-line change per file:

+env:
+  MIERU_VERSION: v3.34.0
+
 jobs:
   libcore:
   mieru:
-    env:
-      MIERU_VERSION: v3.34.0
   build:
-    env:
-      MIERU_VERSION: v3.34.0

4. set -o pipefail missing in mieru.sh

set -e is set but not set -o pipefail. There are no pipe chains inside the script body today, so the practical risk is low — but it's a good guard for future edits:

-set -e
+set -euo pipefail

(-u would also catch unbound variable typos at no cost.)

5. .mieru-build temp dir not cleaned up on success

The shallow clone stays on disk after a successful build. In CI this is reclaimed at job end, but locally it accumulates. A simple rm -rf "$WORK" at the end of mieru.sh (after the ls confirmation line) avoids the mess.

6. CGO_ENABLED=1 — confirm cgo dependency

The script uses CGO_ENABLED=1 with the Android Clang cross-compiler. This is valid and produces a proper Android PIE binary. If cmd/mieru has no actual import "C" cgo calls (mieru's VPN socket-protection uses MIERU_PROTECT_PATH via a pure-Go dialer), CGO_ENABLED=0 would produce a fully-static binary with no Bionic libc dependency, which is slightly simpler. This is informational — CGO_ENABLED=1 is not wrong.


✅ What looks good

Area Assessment
Plugin resolution fallback (bundled → external APK) soIfExist returns null on miss → initNative falls through to APK plugin lookup — correct
EXECUTABLES addition killAll matches by exe.name from /proc/<pid>/cmdline; libmieru.so naming is consistent with other entries
NDK toolchain detection with macOS fallbacks linux-x86_64 → darwin-x86_64 → darwin-arm64 cascade is robust
ANDROID_NDK_HOME resolution order source buildScript/init/env.sh (which sources env_ndk.sh) runs before the mieru.sh validation check, so the env_ndk.sh fallback chain correctly populates the variable first
Cache key design Hashing workflow files + script content + MIERU_VERSION is solid and matches the libcore pattern
Verify Mieru Artifacts fail-fast guard All 4 ABIs checked before Gradle starts — good safety net
Cache key isolation ci.yml uses -mieru-ci suffix; other workflows use -mieru — consistent with libcore convention
need_clone re-clone logic Defensive handling of corrupted checkouts
API level 21 cross-compilers android21-clang for all ABIs — correct minimum API

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/build.yml (1)

41-90: ⚠️ Potential issue | 🟠 Major

Pin GitHub Actions to commit SHAs and disable checkout credential persistence.

The new Mieru workflow additions use floating action tags and lack checkout credential persistence hardening. This weakens supply-chain guarantees for CI execution.

  • .github/workflows/build.yml#L42,47,54: pin actions/checkout@v5, actions/cache@v5, and actions/setup-go@v6 to commit SHAs; add persist-credentials: false to the checkout step.
  • .github/workflows/ci.yml#L47,52,59: apply the same pinning and persist-credentials: false hardening to checkout, cache, and setup-go.
  • .github/workflows/preview.yml#L38,43,50: apply the same pinning and checkout hardening.
  • .github/workflows/release.yml#L44,49,56: apply the same pinning and checkout hardening.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build.yml around lines 41 - 90, Pin GitHub Actions to
specific commit SHAs instead of floating version tags and add credential
persistence hardening to improve supply-chain security. In
.github/workflows/build.yml (lines 41-90), replace actions/checkout@v5 with its
SHA-pinned equivalent, add persist-credentials: false to the checkout step, and
pin actions/cache@v5 and actions/setup-go@v6 to their respective commit SHAs.
Apply the identical pinning changes for checkout, cache, and setup-go actions in
.github/workflows/ci.yml (lines 46-99), .github/workflows/preview.yml (lines
37-85), and .github/workflows/release.yml (lines 43-91), ensuring that each
checkout action across all four workflow files includes the persist-credentials:
false configuration.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build.yml:
- Around line 35-59: Add explicit least-privilege permissions to the mieru job
definitions across multiple workflow files to reduce blast radius. For each of
the following files and their specified line ranges, add a permissions section
at the job level with contents: read permissions: in .github/workflows/build.yml
(lines 35-59) add permissions with contents: read to the mieru job, in
.github/workflows/ci.yml (lines 40-64) add the same permissions configuration to
the corresponding mieru job, in .github/workflows/preview.yml (lines 31-55) add
the same permissions configuration to the mieru job, and in
.github/workflows/release.yml (lines 37-61) add the same permissions
configuration to the mieru job. The permissions should be specified as a
top-level key under each mieru job, not under the steps.

---

Outside diff comments:
In @.github/workflows/build.yml:
- Around line 41-90: Pin GitHub Actions to specific commit SHAs instead of
floating version tags and add credential persistence hardening to improve
supply-chain security. In .github/workflows/build.yml (lines 41-90), replace
actions/checkout@v5 with its SHA-pinned equivalent, add persist-credentials:
false to the checkout step, and pin actions/cache@v5 and actions/setup-go@v6 to
their respective commit SHAs. Apply the identical pinning changes for checkout,
cache, and setup-go actions in .github/workflows/ci.yml (lines 46-99),
.github/workflows/preview.yml (lines 37-85), and .github/workflows/release.yml
(lines 43-91), ensuring that each checkout action across all four workflow files
includes the persist-credentials: false configuration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5dfef8df-5bd3-4936-9c3e-08ae34a19a56

📥 Commits

Reviewing files that changed from the base of the PR and between f685fc6 and 489f034.

📒 Files selected for processing (7)
  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/preview.yml
  • .github/workflows/release.yml
  • app/src/main/java/io/nekohasekai/sagernet/bg/Executable.kt
  • app/src/main/java/io/nekohasekai/sagernet/plugin/PluginManager.kt
  • buildScript/lib/mieru.sh

Comment thread .github/workflows/build.yml
…ION, pipefail

- Include buildScript/init/env_ndk.sh (NDK version pin) in the Mieru cache-key
  hash so bumping the NDK invalidates stale binaries.
- Hoist MIERU_VERSION to a single workflow-level env block per workflow (was
  duplicated in the mieru and build jobs).
- Add 'set -o pipefail' to mieru.sh as a defensive guard.
@hawkff

hawkff commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Addressed the env_ndk.sh cache-hash, consolidated MIERU_VERSION to workflow-level env, and added set -o pipefail.

On the latest local-review findings (all assessed, none applied):

  1. 'Go 1.24.9 is invalid, use 1.26.4' — incorrect. go1.24.9 is a real release (present on go.dev/dl; latest 1.24.x patch is 1.24.13) and is running on the build machine. It matches go.mod's toolchain go1.24.9. A Go patch bump spans all workflows and is out of scope for this Mieru PR.
    2/3. hashFiles('.github/workflows/*') in the mieru cache key 'over-invalidates' — this is the pre-existing libcore cache-key convention I deliberately matched for consistency; it's a minor cache-efficiency nit, not a correctness issue, and narrowing only the mieru keys would diverge from the libcore pattern.

Builds verified on the Linux builder (all 4 ABIs packaged, debug + release).

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

@hawkff: Acknowledged — the three addressed items (env_ndk.sh in the cache-hash, workflow-level MIERU_VERSION, set -euo pipefail) are confirmed applied. The two declined findings are accepted:

  1. Go 1.24.9 — confirmed valid; go1.24.9 is a real release and correctly matches go.mod's toolchain go1.24.9 directive. A patch-version bump is a separate maintenance concern outside this PR's scope.
  2. hashFiles('.github/workflows/*') in the Mieru cache key — intentional consistency with the existing libcore convention; narrowing would diverge from the established pattern without a correctness benefit.

Triggering a full re-review on the updated branch now.


✏️ Learnings added
Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/12

Timestamp: 2026-06-15T21:04:39.537Z
Learning: In the NekoBoxForAndroid repo (hawkff/NekoBoxForAndroid), Go 1.24.9 is a valid, real Go release that intentionally matches the `toolchain go1.24.9` directive in `go.mod` (established in a prior merged Go-alignment PR). Do not flag it as invalid or suggest bumping the Go version — a patch-version bump spans all workflows and is considered out of scope for feature PRs.

Learnt from: hawkff
URL: https://github.com/hawkff/NekoBoxForAndroid/pull/12

Timestamp: 2026-06-15T21:04:39.537Z
Learning: In the NekoBoxForAndroid repo (hawkff/NekoBoxForAndroid), the `hashFiles('.github/workflows/*')` component in the Mieru CI cache keys is an intentional choice to match the pre-existing libcore cache-key convention for consistency. Do not flag it as over-invalidating — narrowing only the Mieru keys would diverge from the established libcore pattern.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
buildScript/lib/mieru.sh (1)

20-53: ⚠️ Potential issue | 🟠 Major

Pin Mieru to an immutable commit SHA (not only a tag).

Building from MIERU_VERSION alone allows silent source drift if the upstream tag is moved, which can ship unreviewed native binaries. Add a pinned MIERU_COMMIT, verify the tag resolves to it, and include that commit value in CI cache keys.

Proposed hardening diff
-MIERU_VERSION="${MIERU_VERSION:-v3.34.0}"
+MIERU_VERSION="${MIERU_VERSION:-v3.34.0}"
+# Immutable source pin for reproducible/safe builds.
+MIERU_COMMIT="${MIERU_COMMIT:-1532c85cc8ca08dff469326f35a3f027697c6950}"
@@
-if [ -d "$WORK/.git" ]; then
-  if git -C "$WORK" fetch --depth 1 origin "refs/tags/$MIERU_VERSION" \
-     && git -C "$WORK" checkout -q FETCH_HEAD; then
+if [ -d "$WORK/.git" ]; then
+  if git -C "$WORK" fetch --depth 1 origin "$MIERU_COMMIT" "refs/tags/$MIERU_VERSION" \
+     && [ "$(git -C "$WORK" rev-parse "$MIERU_VERSION^{commit}")" = "$MIERU_COMMIT" ] \
+     && git -C "$WORK" checkout -q --detach "$MIERU_COMMIT"; then
     need_clone=0
   else
     echo ">> existing $WORK is unusable; re-cloning"
   fi
 fi
 if [ "$need_clone" -eq 1 ]; then
   rm -rf "$WORK"
-  git clone --depth 1 --branch "$MIERU_VERSION" https://github.com/enfein/mieru.git "$WORK"
+  git clone --no-checkout https://github.com/enfein/mieru.git "$WORK"
+  git -C "$WORK" fetch --depth 1 origin "$MIERU_COMMIT" "refs/tags/$MIERU_VERSION"
+  [ "$(git -C "$WORK" rev-parse "$MIERU_VERSION^{commit}")" = "$MIERU_COMMIT" ]
+  git -C "$WORK" checkout -q --detach "$MIERU_COMMIT"
 fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@buildScript/lib/mieru.sh` around lines 20 - 53, The current implementation
pins only the Mieru tag via MIERU_VERSION variable, which allows source drift if
the upstream tag is moved, potentially shipping unreviewed native binaries. Add
a new MIERU_COMMIT variable to pin the build to a specific immutable commit SHA.
After fetching the tag in the git fetch operation (in the section where git -C
"$WORK" fetch --depth 1 origin "refs/tags/$MIERU_VERSION" is called), verify
that the fetched tag resolves to the expected commit by comparing it against the
pinned MIERU_COMMIT value before proceeding with the git checkout. This ensures
that builds are reproducible and cannot silently drift if upstream tags are
modified.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@buildScript/lib/mieru.sh`:
- Around line 20-53: The current implementation pins only the Mieru tag via
MIERU_VERSION variable, which allows source drift if the upstream tag is moved,
potentially shipping unreviewed native binaries. Add a new MIERU_COMMIT variable
to pin the build to a specific immutable commit SHA. After fetching the tag in
the git fetch operation (in the section where git -C "$WORK" fetch --depth 1
origin "refs/tags/$MIERU_VERSION" is called), verify that the fetched tag
resolves to the expected commit by comparing it against the pinned MIERU_COMMIT
value before proceeding with the git checkout. This ensures that builds are
reproducible and cannot silently drift if upstream tags are modified.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0664743e-9f6d-4fc3-b3b9-1f191d28f17a

📥 Commits

Reviewing files that changed from the base of the PR and between 489f034 and 8b04339.

📒 Files selected for processing (5)
  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/preview.yml
  • .github/workflows/release.yml
  • buildScript/lib/mieru.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/build.yml
  • .github/workflows/preview.yml
  • .github/workflows/release.yml

@hawkff hawkff merged commit d5f66df into main Jun 15, 2026
4 checks passed
@hawkff hawkff deleted the feature/mieru-bundled-binary branch June 15, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant