Skip to content

Commit 6df1824

Browse files
authored
env, ci: add better CI diagnosis via is_manageable/0 for when sdkmanager is broken (#341)
1 parent 5c42029 commit 6df1824

File tree

6 files changed

+90
-39
lines changed

6 files changed

+90
-39
lines changed

.github/workflows/matrix_ci.yml

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
runs-on: ${{ matrix.os }}
1818
strategy:
1919
matrix:
20-
os: [ubuntu-20.04]
20+
os: [ubuntu-24.04]
2121
java-version: [11,15,20]
2222
android-api: [31, 33]
2323
fail-fast: false
@@ -55,7 +55,20 @@ jobs:
5555
- name: Run vab --help
5656
run: vab --help
5757

58-
- name: Run vab doctor
58+
- name: Run 'vab doctor' before install
59+
run: vab doctor
60+
61+
# It is a Sisyphus task to get all combinations of the pre-installed SDK / tools and Java working
62+
# so we simply remove the system install and use our own minimal base-setup via 'vab install auto'...
63+
- name: Setup predictable Android environment
64+
run: |
65+
sudo rm -fr /usr/local/lib/android # location of pre-installed SDK on Ubuntu
66+
unset ANDROID_SDK_ROOT # These are set in the CI by default
67+
unset ANDROID_HOME
68+
unset ANDROID_NDK_ROOT
69+
vab install auto
70+
71+
- name: Run 'vab doctor' after install
5972
run: vab doctor
6073

6174
- name: Run tests
@@ -70,12 +83,11 @@ jobs:
7083
- name: Run vab install build-tools
7184
run: vab install "build-tools;29.0.0"
7285

73-
- name: Run vab doctor2
86+
- name: Run 'vab doctor' after build-tools install
7487
run: vab doctor
7588

7689
- name: Build examples as APK + AAB (Java ${{ matrix.java-version }}) ${{ matrix.android-api }}
7790
run: |
78-
7991
declare -a v_examples=('flappylearning' '2048' 'fireworks' 'tetris' 'sokol/particles' 'sokol/drawing.v' 'sokol/freetype_raven.v' 'gg/polygons.v' 'gg/raven_text_rendering.v' 'gg/rectangles.v' 'gg/stars.v' 'gg/worker_thread.v')
8092
8193
for example in "${v_examples[@]}"; do
@@ -101,13 +113,13 @@ jobs:
101113
runs-on: ${{ matrix.os }}
102114
strategy:
103115
matrix:
104-
os: [ubuntu-20.04]
116+
os: [ubuntu-24.04]
105117
java-version: [11, 15, 20]
106118
android-api: [31, 33]
107119
fail-fast: false
108120
timeout-minutes: 20
109121
env:
110-
VAB_FLAGS: -v 3 -gc none --build-tools 29.0.0
122+
VAB_FLAGS: -v 3 -gc none
111123
steps:
112124
- uses: actions/setup-java@v4
113125
with:
@@ -166,13 +178,13 @@ jobs:
166178
runs-on: ${{ matrix.os }}
167179
strategy:
168180
matrix:
169-
os: [ubuntu-20.04]
181+
os: [ubuntu-24.04]
170182
java-version: [8] # 9, 10 is in a bad state currently
171183
android-api: [31, 33]
172184
fail-fast: false
173185
timeout-minutes: 20
174186
env:
175-
VAB_FLAGS: -v 3 --build-tools 29.0.0
187+
VAB_FLAGS: -v 3
176188
steps:
177189
- uses: actions/setup-java@v4
178190
with:
@@ -208,7 +220,7 @@ jobs:
208220
run: |
209221
sudo rm -fr /usr/local/lib/android
210222
211-
- name: Run 'vab doctor'
223+
- name: Run 'vab doctor' before install
212224
run: vab doctor
213225

214226
- name: Run 'vab install auto'
@@ -218,7 +230,7 @@ jobs:
218230
unset ANDROID_NDK_ROOT
219231
vab install auto
220232
221-
- name: Run vab doctor
233+
- name: Run 'vab doctor' after install
222234
run: vab doctor
223235

224236
- name: Run tests

android/env/env.v

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub const accepted_components = ['auto', 'cmdline-tools', 'platform-tools', 'ndk
2424
// build-tools - Version where apksigner is included from
2525

2626
@[deprecated: 'use get_default_components() instead']
27+
@[deprecated_after: '2027-01-01']
2728
pub const default_components = {
2829
'cmdline-tools': {
2930
'name': 'cmdline-tools'
@@ -154,6 +155,9 @@ pub fn (io &InstallOptions) verbose(verbosity_level int, msg string) {
154155
}
155156
}
156157

158+
// managable returns `true` if the host system's SDK can be managed by `vab`.
159+
@[deprecated: 'use "is_manageable() or { false }" instead']
160+
@[deprecated_after: '2027-07-20']
157161
pub fn managable() bool {
158162
sdk_is_writable := os.is_writable(sdk.root())
159163
// sdkmanager checks
@@ -199,7 +203,55 @@ pub fn managable() bool {
199203
return sdk_is_writable && has_sdkmanager && sdkmanger_works
200204
}
201205

206+
// is_manageable returns `true` if the host system's SDK can be managed by `vab`, an error with
207+
// details is returned otherwise.
208+
pub fn is_manageable() !bool {
209+
if !os.is_writable(sdk.root()) {
210+
return error('No permission to write in Android SDK root. Please install manually or ensure write access to "${sdk.root()}".')
211+
}
212+
213+
// sdkmanager checks
214+
sdkm := sdkmanager()
215+
if sdkm == '' {
216+
return error('An executable `sdkmanager` seems to be missing.')
217+
}
218+
// We have detected `sdkmanager` - but does it work with the Java version? *sigh*
219+
// Android development will let us find out I guess:
220+
cmd := [
221+
sdkm,
222+
'--list',
223+
]
224+
mut cmd_res := util.run(cmd)
225+
if cmd_res.exit_code > 0 {
226+
// Failed let's try a workaround from stackoverflow:
227+
// https://stackoverflow.com/a/51644855/1904615
228+
if 'windows' == os.user_os() {
229+
util.run([
230+
'set JAVA_OPTS=-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee',
231+
])
232+
util.run([
233+
'set JAVA_OPTS=-XX:+IgnoreUnrecognizedVMOptions --add-modules java.xml.bind',
234+
])
235+
} else {
236+
util.run([
237+
"export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'",
238+
])
239+
util.run([
240+
"export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.xml.bind'",
241+
])
242+
}
243+
// Let try again
244+
cmd_res = util.run(cmd)
245+
if cmd_res.exit_code != 0 {
246+
return error('The detected `sdkmanager` seems outdated or incompatible with the Java version used. Manual intervention is needed.\nPath: "${sdkmanager()}"\nVersion: ${sdkmanager_version()}\nOutput: ${cmd_res.output}')
247+
}
248+
// Give up trying to fix this horrible eco-system
249+
}
250+
return true
251+
}
252+
202253
@[deprecated: 'use install_components instead']
254+
@[deprecated_after: '2027-01-01']
203255
pub fn install(components string, verbosity int) int {
204256
mut iopts := []InstallOptions{}
205257
mut ensure_sdk := true
@@ -500,16 +552,9 @@ pub fn install_components(arguments []string, verbosity int) ! {
500552
fn install_opt(opt InstallOptions) !bool {
501553
loose := opt.dep == .bundletool || opt.dep == .aapt2
502554

503-
if !loose && !managable() {
504-
if !os.is_writable(sdk.root()) {
505-
return error(@MOD + '.' + @FN + ' ' +
506-
'No permission to write in Android SDK root. Please install manually or ensure write access to "${sdk.root()}".')
507-
} else {
508-
return error(@MOD + '.' + @FN + ' ' +
509-
'The `sdkmanager` seems outdated or incompatible with the Java version used". Please fix your setup manually.\nPath: "${sdkmanager()}"\nVersion: ${sdkmanager_version()}')
510-
}
555+
if !loose {
556+
is_manageable()!
511557
}
512-
513558
// Accept all SDK licenses
514559
$if windows {
515560
os.mkdir_all(work_path) or {}

cli/cli.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub fn input_from_args(arguments []string) (string, []string) {
111111
// args_to_options returns an `Option` merged from (CLI/Shell) `arguments` using `defaults` as
112112
// values where no value can be obtained from `arguments`.
113113
@[deprecated: 'use options_from_arguments and run_vab_sub_command instead']
114+
@[deprecated_after: '2027-01-01']
114115
pub fn args_to_options(arguments []string, defaults Options) !(Options, &flag.FlagParser) {
115116
mut args := arguments.clone()
116117

cli/doctor.v

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,16 @@ import vab.android.env
1414
// diagnosticing the work environment.
1515
pub fn doctor(opt Options) {
1616
sdkm := env.sdkmanager()
17-
env_managable := env.managable()
17+
env_managable := env.is_manageable() or {
18+
util.vab_notice('${err.msg()}',
19+
details: 'For `${exe_short_name}` to control it\'s own dependencies, please update `sdkmanager` found in:
20+
"${sdkm}"
21+
or use a Java version that is compatible with your `sdkmanager`.
22+
You can set the `SDKMANAGER` env variable or try your luck with `${exe_short_name} install auto`.
23+
See https://stackoverflow.com/a/61176718/1904615 for more help.\n'
24+
)
25+
false
26+
}
1827
env_vars := os.environ()
1928

2029
// Validate Android `sdkmanager` tool
@@ -31,23 +40,6 @@ pub fn doctor(opt Options) {
3140
See https://stackoverflow.com/a/61176718/1904615 for more help.\n'
3241
}
3342
util.vab_notice('No "sdkmanager" could be detected.', details)
34-
} else {
35-
if !env_managable {
36-
sdk_is_writable := os.is_writable(sdk.root())
37-
if !sdk_is_writable {
38-
util.vab_notice('The SDK at "${sdk.root()}" is not writable.',
39-
details: "`${exe_short_name}` is not able to control the SDK and it's dependencies."
40-
)
41-
} else {
42-
util.vab_notice('The detected `sdkmanager` seems outdated or incompatible with the Java version used.',
43-
details: 'For `${exe_short_name}` to control it\'s own dependencies, please update `sdkmanager` found in:
44-
"${sdkm}"
45-
or use a Java version that is compatible with your `sdkmanager`.
46-
You can set the `SDKMANAGER` env variable or try your luck with `${exe_short_name} install auto`.
47-
See https://stackoverflow.com/a/61176718/1904615 for more help.\n'
48-
)
49-
}
50-
}
5143
}
5244

5345
avdmanager := env.avdmanager()

cli/options.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ fn (mut o Options) merge_additional_args(default_additional_args []string) {
428428
// extend_from_dot_vab will merge the `Options` with any content
429429
// found in any `.vab` config files.
430430
@[deprecated: 'use options_from_dot_vab instead']
431+
@[deprecated_after: '2027-01-01']
431432
pub fn (mut opt Options) extend_from_dot_vab() {
432433
// Look up values in input .vab file next to input if no flags or defaults was set
433434
dot_vab_file := dot_vab_path(opt.input)

tests/at-runtime/emulator/emulator_test.vv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const test_v_examples = [
2626
'gg/worker_thread.v',
2727
]
2828

29-
const env_is_managable = env.managable()
29+
const env_is_manageable = env.is_manageable() or { false }
3030

3131
const is_ci = os.getenv('CI') != ''
3232

@@ -77,7 +77,7 @@ fn ensure_env() {
7777
os.unsetenv('ANDROID_SERIAL')
7878

7979
if !env.has_emulator() {
80-
assert env_is_managable == true, 'These tests requires a *writable* SDK'
80+
assert env_is_manageable == true, 'These tests requires a *writable* SDK'
8181
eprintln('No emulator detected. Installing...')
8282
install_emulator_res := run([vab_exe, 'install', 'emulator'])
8383
if install_emulator_res.exit_code != 0 {

0 commit comments

Comments
 (0)