Skip to content

Commit 51cda3a

Browse files
committed
ci+bg: harden cache against PR poisoning; soften sidecar readiness gate
CI: split every actions/cache into restore + gated save. Producer caches (libcore, sidecars, gradle) restore then save only on non-pull_request runs and cache misses; consumer caches in the APK job are restore-only. This stops untrusted PR runs from writing caches that trusted runs later restore. (CodeRabbit) bg: awaitExternalProcessesReady no longer hard-fails VPN start for non- MasterDnsVPN sidecars. MasterDnsVPN still throws on timeout (it must bind before the first dial), but Mieru/Naive/TrojanGo/Hysteria now log a warning and continue, restoring the prior fire-and-forget behavior where the first sing-box dial retries. (Greptile, PR #18 follow-up)
1 parent 972db68 commit 51cda3a

5 files changed

Lines changed: 130 additions & 25 deletions

File tree

.github/workflows/build.yml

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
2828
- name: LibCore Cache
2929
id: cache
30-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
30+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
3131
with:
3232
path: |
3333
app/libs/libcore.aar
@@ -40,6 +40,13 @@ jobs:
4040
- name: Native Build
4141
if: steps.cache.outputs.cache-hit != 'true'
4242
run: ./run lib core
43+
- name: Save LibCore Cache
44+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
45+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
46+
with:
47+
path: |
48+
app/libs/libcore.aar
49+
key: ${{ steps.cache.outputs.cache-primary-key }}
4350
sidecars:
4451
name: Native Build (Sidecars)
4552
runs-on: namespace-profile-nekoyay
@@ -50,7 +57,7 @@ jobs:
5057
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
5158
- name: Sidecars Cache
5259
id: cache
53-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
60+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
5461
with:
5562
path: |
5663
app/executableSo
@@ -72,6 +79,13 @@ jobs:
7279
- name: Naive Download
7380
if: steps.cache.outputs.cache-hit != 'true'
7481
run: ./run lib naive
82+
- name: Save Sidecars Cache
83+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
84+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
85+
with:
86+
path: |
87+
app/executableSo
88+
key: ${{ steps.cache.outputs.cache-primary-key }}
7589
build:
7690
name: Build OSS APK
7791
runs-on: namespace-profile-nekoyay
@@ -86,7 +100,7 @@ jobs:
86100
- name: Libcore Status
87101
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
88102
- name: LibCore Cache
89-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
103+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
90104
with:
91105
path: |
92106
app/libs/libcore.aar
@@ -95,7 +109,7 @@ jobs:
95109
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
96110
- name: Sidecars Cache
97111
id: sidecars-cache
98-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
112+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
99113
with:
100114
path: |
101115
app/executableSo
@@ -110,8 +124,9 @@ jobs:
110124
fi
111125
done
112126
done
113-
- name: Gradle cache
114-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
127+
- name: Gradle cache (restore)
128+
id: gradle-cache
129+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
115130
with:
116131
path: ~/.gradle
117132
key: gradle-oss-${{ hashFiles('**/*.gradle.kts') }}
@@ -127,6 +142,12 @@ jobs:
127142
APK=$(find app/build/outputs/apk -name '*arm64-v8a*.apk')
128143
APK=$(dirname $APK)
129144
echo "APK=$APK" >> $GITHUB_ENV
145+
- name: Save Gradle cache
146+
if: github.event_name != 'pull_request' && steps.gradle-cache.outputs.cache-hit != 'true'
147+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
148+
with:
149+
path: ~/.gradle
150+
key: ${{ steps.gradle-cache.outputs.cache-primary-key }}
130151
- name: Upload Artifacts
131152
uses: actions/upload-artifact@v5
132153
with:

.github/workflows/ci.yml

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
3333
- name: LibCore Cache
3434
id: cache
35-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
35+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
3636
with:
3737
path: |
3838
app/libs/libcore.aar
@@ -45,6 +45,13 @@ jobs:
4545
- name: Native Build
4646
if: steps.cache.outputs.cache-hit != 'true'
4747
run: ./run lib core
48+
- name: Save LibCore Cache
49+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
50+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
51+
with:
52+
path: |
53+
app/libs/libcore.aar
54+
key: ${{ steps.cache.outputs.cache-primary-key }}
4855
sidecars:
4956
name: Native Build (Sidecars)
5057
runs-on: namespace-profile-nekoyay
@@ -55,7 +62,7 @@ jobs:
5562
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
5663
- name: Sidecars Cache
5764
id: cache
58-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
65+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
5966
with:
6067
path: |
6168
app/executableSo
@@ -77,6 +84,13 @@ jobs:
7784
- name: Naive Download
7885
if: steps.cache.outputs.cache-hit != 'true'
7986
run: ./run lib naive
87+
- name: Save Sidecars Cache
88+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
89+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
90+
with:
91+
path: |
92+
app/executableSo
93+
key: ${{ steps.cache.outputs.cache-primary-key }}
8094
build:
8195
name: Build OSS APK
8296
runs-on: namespace-profile-nekoyay
@@ -96,7 +110,7 @@ jobs:
96110
- name: Libcore Status
97111
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
98112
- name: LibCore Cache
99-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
113+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
100114
with:
101115
path: |
102116
app/libs/libcore.aar
@@ -105,7 +119,7 @@ jobs:
105119
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
106120
- name: Sidecars Cache
107121
id: sidecars-cache
108-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
122+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
109123
with:
110124
path: |
111125
app/executableSo
@@ -120,8 +134,9 @@ jobs:
120134
fi
121135
done
122136
done
123-
- name: Gradle cache
124-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
137+
- name: Gradle cache (restore)
138+
id: gradle-cache
139+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
125140
with:
126141
path: ~/.gradle
127142
key: gradle-oss-${{ hashFiles('**/*.gradle.kts') }}-ci
@@ -137,6 +152,24 @@ jobs:
137152
APK=$(find app/build/outputs/apk -name '*arm64-v8a*.apk')
138153
APK=$(dirname $APK)
139154
echo "APK=$APK" >> $GITHUB_ENV
155+
- name: Save Gradle cache
156+
if: github.event_name != 'pull_request' && steps.gradle-cache.outputs.cache-hit != 'true'
157+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
158+
with:
159+
path: ~/.gradle
160+
key: ${{ steps.gradle-cache.outputs.cache-primary-key }}
161+
- name: Gradle Build
162+
env:
163+
BUILD_PLUGIN: none
164+
run: |
165+
echo "sdk.dir=${ANDROID_HOME}" > local.properties
166+
echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties
167+
export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}"
168+
./run init action gradle
169+
./gradlew app:assembleOssDebug
170+
APK=$(find app/build/outputs/apk -name '*arm64-v8a*.apk')
171+
APK=$(dirname $APK)
172+
echo "APK=$APK" >> $GITHUB_ENV
140173
- name: Upload Artifacts
141174
uses: actions/upload-artifact@v5
142175
with:

.github/workflows/preview.yml

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
2424
- name: LibCore Cache
2525
id: cache
26-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
26+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
2727
with:
2828
path: |
2929
app/libs/libcore.aar
@@ -36,6 +36,13 @@ jobs:
3636
- name: Native Build
3737
if: steps.cache.outputs.cache-hit != 'true'
3838
run: ./run lib core
39+
- name: Save LibCore Cache
40+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
41+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
42+
with:
43+
path: |
44+
app/libs/libcore.aar
45+
key: ${{ steps.cache.outputs.cache-primary-key }}
3946
sidecars:
4047
name: Native Build (Sidecars)
4148
runs-on: namespace-profile-nekoyay
@@ -46,7 +53,7 @@ jobs:
4653
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
4754
- name: Sidecars Cache
4855
id: cache
49-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
56+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
5057
with:
5158
path: |
5259
app/executableSo
@@ -68,6 +75,13 @@ jobs:
6875
- name: Naive Download
6976
if: steps.cache.outputs.cache-hit != 'true'
7077
run: ./run lib naive
78+
- name: Save Sidecars Cache
79+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
80+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
81+
with:
82+
path: |
83+
app/executableSo
84+
key: ${{ steps.cache.outputs.cache-primary-key }}
7185
build:
7286
name: Build OSS APK
7387
runs-on: namespace-profile-nekoyay
@@ -82,7 +96,7 @@ jobs:
8296
- name: Libcore Status
8397
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
8498
- name: LibCore Cache
85-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
99+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
86100
with:
87101
path: |
88102
app/libs/libcore.aar
@@ -91,7 +105,7 @@ jobs:
91105
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
92106
- name: Sidecars Cache
93107
id: sidecars-cache
94-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
108+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
95109
with:
96110
path: |
97111
app/executableSo
@@ -106,8 +120,9 @@ jobs:
106120
fi
107121
done
108122
done
109-
- name: Gradle cache
110-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
123+
- name: Gradle cache (restore)
124+
id: gradle-cache
125+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
111126
with:
112127
path: ~/.gradle
113128
key: gradle-oss-${{ hashFiles('**/*.gradle.kts') }}
@@ -123,6 +138,12 @@ jobs:
123138
APK=$(find app/build/outputs/apk -name '*arm64-v8a*.apk')
124139
APK=$(dirname $APK)
125140
echo "APK=$APK" >> $GITHUB_ENV
141+
- name: Save Gradle cache
142+
if: github.event_name != 'pull_request' && steps.gradle-cache.outputs.cache-hit != 'true'
143+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
144+
with:
145+
path: ~/.gradle
146+
key: ${{ steps.gradle-cache.outputs.cache-primary-key }}
126147
- uses: actions/upload-artifact@v5
127148
with:
128149
name: APKs

.github/workflows/release.yml

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
3030
- name: LibCore Cache
3131
id: cache
32-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
32+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
3333
with:
3434
path: |
3535
app/libs/libcore.aar
@@ -42,6 +42,13 @@ jobs:
4242
- name: Native Build
4343
if: steps.cache.outputs.cache-hit != 'true'
4444
run: ./run lib core
45+
- name: Save LibCore Cache
46+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
47+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
48+
with:
49+
path: |
50+
app/libs/libcore.aar
51+
key: ${{ steps.cache.outputs.cache-primary-key }}
4552
sidecars:
4653
name: Native Build (Sidecars)
4754
runs-on: namespace-profile-nekoyay
@@ -52,7 +59,7 @@ jobs:
5259
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
5360
- name: Sidecars Cache
5461
id: cache
55-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
62+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
5663
with:
5764
path: |
5865
app/executableSo
@@ -74,6 +81,13 @@ jobs:
7481
- name: Naive Download
7582
if: steps.cache.outputs.cache-hit != 'true'
7683
run: ./run lib naive
84+
- name: Save Sidecars Cache
85+
if: github.event_name != 'pull_request' && steps.cache.outputs.cache-hit != 'true'
86+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
87+
with:
88+
path: |
89+
app/executableSo
90+
key: ${{ steps.cache.outputs.cache-primary-key }}
7791
build:
7892
name: Build OSS APK
7993
runs-on: namespace-profile-nekoyay
@@ -88,7 +102,7 @@ jobs:
88102
- name: Libcore Status
89103
run: git ls-files libcore | xargs cat | sha1sum > libcore_status
90104
- name: LibCore Cache
91-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
105+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
92106
with:
93107
path: |
94108
app/libs/libcore.aar
@@ -97,7 +111,7 @@ jobs:
97111
run: cat buildScript/lib/mieru.sh buildScript/lib/hysteria2.sh buildScript/lib/masterdnsvpn.sh buildScript/lib/naive.sh buildScript/init/env.sh buildScript/init/env_ndk.sh | sha1sum > sidecars_status
98112
- name: Sidecars Cache
99113
id: sidecars-cache
100-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
114+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
101115
with:
102116
path: |
103117
app/executableSo
@@ -112,8 +126,9 @@ jobs:
112126
fi
113127
done
114128
done
115-
- name: Gradle cache
116-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
129+
- name: Gradle cache (restore)
130+
id: gradle-cache
131+
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
117132
with:
118133
path: ~/.gradle
119134
key: gradle-oss-${{ hashFiles('**/*.gradle.kts') }}
@@ -129,6 +144,12 @@ jobs:
129144
APK=$(find app/build/outputs/apk -name '*arm64-v8a*.apk')
130145
APK=$(dirname $APK)
131146
echo "APK=$APK" >> $GITHUB_ENV
147+
- name: Save Gradle cache
148+
if: github.event_name != 'pull_request' && steps.gradle-cache.outputs.cache-hit != 'true'
149+
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
150+
with:
151+
path: ~/.gradle
152+
key: ${{ steps.gradle-cache.outputs.cache-primary-key }}
132153
- uses: actions/upload-artifact@v5
133154
with:
134155
name: APKs

app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,16 @@ abstract class BoxInstance(
294294
if (pending.isNotEmpty()) delay(50)
295295
}
296296
if (pending.isNotEmpty()) {
297-
throw IOException("sidecar listener not ready on port(s): ${pending.joinToString()}")
297+
// MasterDnsVPN must have its listener up before the first dial (it crashed
298+
// otherwise), so a timeout there is fatal. Other sidecars (Mieru/Naïve/
299+
// TrojanGo/Hysteria) were historically fire-and-forget: the first sing-box
300+
// dial retries, so a slow bind shouldn't hard-fail VPN start — log and continue.
301+
val message = "sidecar listener not ready on port(s): ${pending.joinToString()}"
302+
if (hasMasterDnsVpn) {
303+
throw IOException(message)
304+
} else {
305+
Logs.w("$message; continuing (sing-box will retry the connection)")
306+
}
298307
}
299308
}
300309
}

0 commit comments

Comments
 (0)