Repository navigation
953 lines (928 loc) · 50.9 KB
/
Copy pathpr.yml
File metadata and controls
953 lines (928 loc) · 50.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
name: PR CI
on:
workflow_dispatch:
pull_request:
branches:
- master
# paths rather than paths-ignore, because this list both excludes and re-includes and only
# this form supports that: a "!" entry in paths-ignore is not a re-inclusion, so the entries
# for setup-workspace.sh and the database check scripts below never took effect there. The
# last matching pattern decides, so this reads as "everything, except these, except these".
paths:
- '**'
- '!.github/workflows/scripts-android.yml'
- '!.github/workflows/scripts-ios.yml'
- '!scripts/**'
- 'scripts/setup-workspace.sh'
# Run from this workflow and nowhere else, so ignoring the whole directory meant a change
# to one of them -- including one that breaks the check itself -- merged without it ever
# running.
- 'scripts/ci/db-cipher-interop.sh'
- 'scripts/ci/check-android-cipher-package-compiles.sh'
- 'scripts/ci/check-js-sqlite-wasm.sh'
# Every Maven step in this matrix runs through retry.sh, and the apt helpers gate the
# Linux legs, so a change to one of them that nothing exercises can merge and then break
# the matrix it was meant to protect.
- 'scripts/ci/retry.sh'
- 'scripts/ci/apt-get-update.sh'
- 'scripts/ci/apt-get-install.sh'
- 'scripts/ci/tests/apt-get-update-test.sh'
# The native warning gate's parser self-test runs from this workflow and nowhere
# else -- the legs that run the gate itself need a compiler. Ignoring these meant a
# change to the parser, its fixture or a baseline could merge without the one check
# that would have caught it ever running.
- 'scripts/check-native-warnings.py'
- 'scripts/check-native-warnings.sh'
- 'scripts/native-warnings/**'
# Same reason: the C++ linkage gate runs from this workflow and nowhere else, so
# ignoring scripts/** would let a change that weakens it merge unexercised.
- 'scripts/check-native-cpp-linkage.py'
# Same: the builder define-toggle lint runs from this workflow and nowhere else.
- 'scripts/check-builder-define-toggles.py'
- 'scripts/check-cast-semantics.sh'
- 'scripts/cast-semantics-baseline.txt'
# The build hint gates are run from this workflow and nowhere else, and one
# of them holds an empty baseline. Ignoring the whole directory meant a
# change that breaks a gate, or that adds a line to the baseline, could
# merge without the gate it weakens ever running.
- 'scripts/check-build-hint-catalog.sh'
- 'scripts/check-build-hint-catalog.py'
- 'scripts/build_hint_miner.py'
- 'scripts/build-hint-catalog-baseline.txt'
- 'scripts/build-hint-computed-sites.txt'
- 'scripts/gen-build-hint-annotations.sh'
# Same reasoning for the cn1lib native gates: they run from this workflow
# and nowhere else, and the stubs are the API surface their Android check
# compiles against, so excluding scripts/ wholesale would let a change to
# any of them merge without the gate it belongs to ever running.
- 'scripts/check-native-peer-returns.py'
- 'scripts/check-cn1lib-android-api.py'
- 'scripts/check-cn1lib-native-coverage.py'
- 'scripts/ci/select-cn1lib-checks.py'
- 'scripts/check-cn1lib-native-sources.py'
- 'scripts/cn1lib-api-check/**'
# The certificate wizard's own tests run in this workflow (see "Run Certificate Wizard
# tests"), so a change to the wizard alone has to trigger it.
- 'scripts/certificatewizard/**'
- '!docs/**'
- '!**/*.md'
- '!.github/workflows/developer-guide-docs.yml'
- '!.github/workflows/website-docs.yml'
- '!.github/workflows/initializr-cn1-version-pr.yml'
- '!CodenameOneDesigner/**'
- '!Ports/IOSPort/**'
push:
branches:
- master
# paths rather than paths-ignore, because this list both excludes and re-includes and only
# this form supports that: a "!" entry in paths-ignore is not a re-inclusion, so the entries
# for setup-workspace.sh and the database check scripts below never took effect there. The
# last matching pattern decides, so this reads as "everything, except these, except these".
paths:
- '**'
- '!.github/workflows/scripts-android.yml'
- '!.github/workflows/scripts-ios.yml'
- '!scripts/**'
- 'scripts/setup-workspace.sh'
# Run from this workflow and nowhere else, so ignoring the whole directory meant a change
# to one of them -- including one that breaks the check itself -- merged without it ever
# running.
- 'scripts/ci/db-cipher-interop.sh'
- 'scripts/ci/check-android-cipher-package-compiles.sh'
- 'scripts/ci/check-js-sqlite-wasm.sh'
# Every Maven step in this matrix runs through retry.sh, and the apt helpers gate the
# Linux legs, so a change to one of them that nothing exercises can merge and then break
# the matrix it was meant to protect.
- 'scripts/ci/retry.sh'
- 'scripts/ci/apt-get-update.sh'
- 'scripts/ci/apt-get-install.sh'
- 'scripts/ci/tests/apt-get-update-test.sh'
# The native warning gate's parser self-test runs from this workflow and nowhere
# else -- the legs that run the gate itself need a compiler. Ignoring these meant a
# change to the parser, its fixture or a baseline could merge without the one check
# that would have caught it ever running.
- 'scripts/check-native-warnings.py'
- 'scripts/check-native-warnings.sh'
- 'scripts/native-warnings/**'
# Same reason: the C++ linkage gate runs from this workflow and nowhere else, so
# ignoring scripts/** would let a change that weakens it merge unexercised.
- 'scripts/check-native-cpp-linkage.py'
# Same: the builder define-toggle lint runs from this workflow and nowhere else.
- 'scripts/check-builder-define-toggles.py'
- 'scripts/check-cast-semantics.sh'
- 'scripts/cast-semantics-baseline.txt'
# The build hint gates are run from this workflow and nowhere else, and one
# of them holds an empty baseline. Ignoring the whole directory meant a
# change that breaks a gate, or that adds a line to the baseline, could
# merge without the gate it weakens ever running.
- 'scripts/check-build-hint-catalog.sh'
- 'scripts/check-build-hint-catalog.py'
- 'scripts/build_hint_miner.py'
- 'scripts/build-hint-catalog-baseline.txt'
- 'scripts/build-hint-computed-sites.txt'
- 'scripts/gen-build-hint-annotations.sh'
# Same reasoning for the cn1lib native gates: they run from this workflow
# and nowhere else, and the stubs are the API surface their Android check
# compiles against, so excluding scripts/ wholesale would let a change to
# any of them merge without the gate it belongs to ever running.
- 'scripts/check-native-peer-returns.py'
- 'scripts/check-cn1lib-android-api.py'
- 'scripts/check-cn1lib-native-coverage.py'
- 'scripts/ci/select-cn1lib-checks.py'
- 'scripts/check-cn1lib-native-sources.py'
- 'scripts/cn1lib-api-check/**'
# The certificate wizard's own tests run in this workflow (see "Run Certificate Wizard
# tests"), so a change to the wizard alone has to trigger it.
- 'scripts/certificatewizard/**'
- '!docs/**'
- '!**/*.md'
- '!.github/workflows/developer-guide-docs.yml'
- '!.github/workflows/website-docs.yml'
- '!.github/workflows/initializr-cn1-version-pr.yml'
- '!CodenameOneDesigner/**'
- '!Ports/IOSPort/**'
permissions:
contents: write
pull-requests: write
issues: write
packages: read
env:
# Turn the ParparVM native-signature check on for every translation this
# workflow forks -- the Maven plugin, the ParparVM integration tests, the build
# scripts -- since a forked process inherits the environment. Deliberately NOT
# the translator's default: making the old soft failure hard would change the
# outcome of customer builds that succeed today, so it is ours to enforce, not
# theirs to trip over. See NativeSignatureVerifier.
CN1_NATIVE_VERIFY: strict
# A method the translator culled as unreachable is still emitted as a stub,
# because dispatch tables name it. With this on, the stub aborts with the
# method's name instead of returning 0, so a wrong cull fails the suite that
# reached it rather than shipping a silent null. Ours to enforce, like
# CN1_NATIVE_VERIFY: customer builds keep the plain stub. See
# BytecodeMethod.appendMethodC. Not in the size or perf benchmarks, whose
# binaries should be the ones customers get.
CN1_CULL_TRAP: '1'
concurrency:
# Only the latest revision needs validation. PR numbers keep forks isolated;
# event names keep a manual/scheduled run from cancelling a push or PR run.
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build-test:
runs-on: ubuntu-24.04
# Java 8 also runs the full quality reports and packaging checks.
timeout-minutes: ${{ matrix.java-version == 8 && 90 || 60 }}
container: ghcr.io/codenameone/codenameone/pr-ci-container:latest
env:
# Java 8 uses the native locale for class-file names containing Unicode.
LANG: C.UTF-8
LC_ALL: C.UTF-8
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
java-version: [8, 17, 21]
steps:
- uses: actions/checkout@v6
- name: Validate Java 25 markdown docs style (CodenameOne + CLDC11)
run: ./.github/scripts/validate-java25-markdown-docs.sh
- name: Set up Java
run: |
if [ "${{ matrix.java-version }}" = "8" ]; then
echo "JAVA_HOME=${JAVA_HOME_8}" >> $GITHUB_ENV
echo "${JAVA_HOME_8}/bin" >> $GITHUB_PATH
elif [ "${{ matrix.java-version }}" = "17" ]; then
echo "JAVA_HOME=${JAVA_HOME_17}" >> $GITHUB_ENV
echo "${JAVA_HOME_17}/bin" >> $GITHUB_PATH
elif [ "${{ matrix.java-version }}" = "21" ]; then
echo "JAVA_HOME=${JAVA_HOME_21}" >> $GITHUB_ENV
echo "${JAVA_HOME_21}/bin" >> $GITHUB_PATH
fi
- name: Cache Maven dependencies
uses: actions/cache@v5
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-m2
- name: Set up Node
if: ${{ matrix.java-version == 8 }}
uses: actions/setup-node@v6
with:
node-version: '20'
- name: Run Unit Tests
# Maven Central answers 429 from the runner CDN edge often enough to kill
# this step outright -- it dies reading the root POM, before a line is
# compiled, so nothing about the branch is being tested when it happens.
# Retried through the shared helper, but ONLY for that failure shape:
# RETRY_ONLY_MATCHING keeps a failing test failing on the first attempt
# rather than letting a re-run launder a flake into a pass.
env:
RETRY_ONLY_MATCHING: transient
run: |
MVN_GOAL="verify"
MVN_ARGS=""
if [ "${{ matrix.java-version }}" != "8" ]; then
MVN_GOAL="test"
MVN_ARGS="-Dspotbugs.skip=true -Dpmd.skip=true -Dcheckstyle.skip=true -Djacoco.skip=true"
fi
cd maven
bash ../scripts/ci/retry.sh mvn clean "$MVN_GOAL" -DunitTests=true -pl core-unittests -am -Dmaven.javadoc.skip=true -Plocal-dev-javase $MVN_ARGS
cd ..
- name: Run push service-worker contract
if: ${{ matrix.java-version == 8 }}
run: |
node tests/push-e2e/service-worker-contract.mjs
node tests/pwa/service-worker-contract.mjs
- name: Build CSS compiler CLI and smoke native-themes
if: ${{ matrix.java-version == 8 }}
run: |
cd maven
mvn -B -pl css-cli -am install -DskipTests -Dmaven.javadoc.skip=true -Plocal-dev-javase
cd ..
./scripts/build-native-themes.sh
test -f Themes/iOSModernTheme.res || { echo "missing Themes/iOSModernTheme.res"; exit 1; }
test -f Themes/AndroidMaterialTheme.res || { echo "missing Themes/AndroidMaterialTheme.res"; exit 1; }
- name: Prepare Codename One binaries for Maven plugin tests
if: ${{ matrix.java-version == 8 }}
run: |
set -euo pipefail
rm -rf maven/target/cn1-binaries
mkdir -p maven/target
cp -r /opt/cn1-binaries maven/target/cn1-binaries
# The container bakes a cn1-binaries snapshot at image-build time, so
# recently added native libraries lag until the image is rebuilt.
# Overlay a fresh ble/ from master (a small sparse/partial clone) so
# libcn1ble -- required by the JavaSE native-engine integration tests
# -- is present. Best-effort: a network hiccup leaves the baked copy.
rm -rf /tmp/cn1bin-ble
if git clone --no-checkout --depth 1 --filter=blob:none \
https://github.com/codenameone/cn1-binaries /tmp/cn1bin-ble \
&& git -C /tmp/cn1bin-ble sparse-checkout set ble \
&& git -C /tmp/cn1bin-ble checkout \
&& [ -d /tmp/cn1bin-ble/ble ]; then
rm -rf maven/target/cn1-binaries/ble
cp -r /tmp/cn1bin-ble/ble maven/target/cn1-binaries/ble
fi
- name: Run Maven plugin tests
if: ${{ matrix.java-version == 8 }}
working-directory: maven
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
# Central served a Connection reset here and Maven treats that as a
# permanent resolution failure -- the step died at plugin download,
# before a single test ran, and reported the branch red. RETRY_ONLY_
# MATCHING=transient returns anything else on the FIRST attempt, so a
# genuine test failure still fails once and fails fast.
RETRY_ONLY_MATCHING: transient
run: |
bash ../scripts/ci/retry.sh mvn -B -Dmaven.javadoc.skip=true \
-DunitTests=true \
-Dcodename1.platform=javase \
-Dcn1.binaries="${CN1_BINARIES}" \
-pl codenameone-maven-plugin -am -Plocal-dev-javase test
- name: Install native BLE runtime dependency (libdbus)
if: ${{ matrix.java-version == 8 }}
# libcn1ble.so (the JavaSE native Bluetooth backend) links libdbus-1
# for BlueZ, so it must be present for the native-engine integration
# tests to load the library. Also baked into the pr-ci-container image
# (.ci/container/Dockerfile); this step covers running against the
# previously published container before the rebuild propagates.
# Skip the network when installed; otherwise use the shared bounded
# installer so a stalled mirror can recover without hiding install failures.
run: bash scripts/ci/apt-get-install.sh libdbus-1-3
- name: Run JavaSE port unit tests
if: ${{ matrix.java-version == 8 }}
# Surface regressions in the simulator-side helpers (CSSWatcher
# localization, MavenUtils designer-jar resolution, JavaSEPort font
# mapping). Without this step the tests in maven/javase compile but
# never execute on PRs. We install the javase module's transitive
# deps first (sqlite-jdbc, factory, etc. -- earlier steps don't
# publish them to the local repo) so the test invocation can resolve
# them, then run javase's tests in isolation.
working-directory: maven
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
run: |
mvn -B -Dmaven.javadoc.skip=true \
-Dcodename1.platform=javase \
-Dcn1.binaries="${CN1_BINARIES}" \
-pl javase -am -Plocal-dev-javase -DskipTests install
mvn -B -Dmaven.javadoc.skip=true \
-Dcodename1.platform=javase \
-Dcn1.binaries="${CN1_BINARIES}" \
-pl javase -Plocal-dev-javase test
- name: Verify encrypted databases interoperate with reference SQLCipher
if: ${{ matrix.java-version == 8 }}
# The portability claim is that every port writes one on-disk format. A cipher
# misconfiguration produces files each platform reads happily and nothing else can
# touch, which no single-platform test would catch, so check ours against the stock
# sqlcipher client in both directions.
run: |
bash scripts/ci/apt-get-install.sh sqlcipher
scripts/ci/db-cipher-interop.sh
- name: Determine AI/ad cn1libs to build
id: cn1libs
if: ${{ matrix.java-version == 8 }}
env:
BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
python3 scripts/ci/select-cn1lib-checks.py
- name: Build changed/impacted AI and ad cn1libs
if: ${{ matrix.java-version == 8 && steps.cn1libs.outputs.modules != '' }}
# Exercises every cn1-ai-* and ad-provider multi-module project:
# compiles the common module, runs its JUnit 5 tests, and packages
# the .cn1lib archive (including native iOS Obj-C / Android Java
# sources). The detector above limits this to changed cn1libs unless
# shared inputs changed, in which case all impacted cn1libs are rebuilt.
working-directory: maven
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
CN1LIB_LIBS: ${{ steps.cn1libs.outputs.libs }}
CN1LIB_MODULES: ${{ steps.cn1libs.outputs.modules }}
run: |
set -euo pipefail
git config --global --add safe.directory "$GITHUB_WORKSPACE"
python3 ../scripts/gen-ai-cn1libs.py > /tmp/gen-ai.log
# Capture a list of changed files instead of using --exit-code/--quiet,
# which interacted poorly with the surrounding `set -e -o pipefail`.
ai_drift_paths=()
IFS=',' read -r -a libs <<< "$CN1LIB_LIBS"
for lib in "${libs[@]}"; do
case "$lib" in
cn1-ai-*) ai_drift_paths+=("maven/$lib") ;;
esac
done
if [ ${#ai_drift_paths[@]} -gt 0 ]; then
drift=$(git -C .. status --porcelain -- "${ai_drift_paths[@]}" || true)
if [ -n "$drift" ]; then
echo "::error::Checked-in cn1-ai-* tree is out of sync with scripts/gen-ai-cn1libs.py"
echo "$drift"
git -C .. --no-pager diff -- "${ai_drift_paths[@]}" || true
exit 1
fi
fi
# The cn1lib mojo is part of codenameone-maven-plugin and isn't
# in m2 from prior CI steps (those run the plugin's tests but
# don't install it, and -am pulls in transitive deps not yet
# built here -- designer, java-runtime, ports). Install the
# plugin + everything it transitively needs, then run package
# on each cn1lib's common module.
mvn -B -Dmaven.javadoc.skip=true \
-Dcn1.binaries="${CN1_BINARIES}" \
-Plocal-dev-javase \
-pl codenameone-maven-plugin -am -DskipTests install
mvn -B -Dmaven.javadoc.skip=true \
-Dcn1.binaries="${CN1_BINARIES}" \
-Plocal-dev-javase \
-pl "$CN1LIB_MODULES" \
package
# The backend runtime is named explicitly rather than left to -am: the plugin
# reaches it only through a test-scoped dependency, and its verify is where
# its SpotBugs, PMD and Checkstyle run -- the same gates the core has.
# backend-parparvm (activated by -DbackendAnalysis) compiles the production
# impl/parparvm tree that maven/backend never compiles, so PMD can see it.
- name: Run SpotBugs for ports, Maven plugin and backend runtime
if: ${{ matrix.java-version == 8 }}
working-directory: maven
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
run: |
mvn -B -DskipTests=true \
-Dcn1.binaries="${CN1_BINARIES}" \
-Pcompile-android \
-DbackendAnalysis \
-pl android,ios,project-model,build-engine,codenameone-maven-plugin,codenameone-gradle-plugin,backend,backend-test,backend-parparvm,javac,android-res-compiler,android-compat,swing-compat,javafx-compat,compose-compat,fxml-compiler,desktop-compat-runtime -am verify
- name: Type-check the SQLCipher-backed database package
if: ${{ matrix.java-version == 8 }}
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
# That package is excluded from the port build on purpose, so nothing above compiles it
# and a member of com.codename1.impl.android it reaches can stop being public without
# anything noticing until an Android app build forty minutes later. Runs after the port
# is compiled, which is what it type-checks against.
run: scripts/ci/check-android-cipher-package-compiles.sh
- name: Compile the bundled SQLite WebAssembly module
if: ${{ matrix.java-version == 8 }}
# A module no engine accepts does not fail anything on its own: the JavaScript port just
# reports the database as unavailable and its tests skip.
run: scripts/ci/check-js-sqlite-wasm.sh
- name: Run SpotBugs for ByteCodeTranslator
if: ${{ matrix.java-version == 8 }}
run: mvn -B -DskipTests=true -f vm/ByteCodeTranslator/pom.xml verify
# A build hint is a string nothing checks: a misspelled name is accepted,
# never read, and silently does nothing. The catalog in
# maven/build-hint-catalog is what gives every hint a type, a default and a
# value domain, and it is what the @Ios/@Android annotations, the developer
# guide table and the Settings tool are generated from. These two steps keep
# the catalog complete and the generated files in step with it.
- name: Check build hint catalog
if: ${{ matrix.java-version == 8 }}
run: scripts/check-build-hint-catalog.sh
- name: Check the apt source prune keeps Ubuntu's own sources
if: ${{ matrix.java-version == 8 }}
# Cheap, and the rule it covers is only ever exercised on a runner whose
# apt is already broken -- so without this it would be tested by a red
# build and nothing else.
run: bash scripts/ci/tests/apt-get-update-test.sh
- name: Check the build hint data file can be rendered
if: ${{ matrix.java-version == 8 }}
# Not a drift check: nothing is committed to drift from, because every
# module that needs the data file renders it into its own target/classes
# during its build. What can still break is the rendering itself, which
# would otherwise reach a user as an editor with no hints in it.
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
scripts/gen-build-hint-annotations.sh --check
# ParparVM's CHECKCAST is unchecked, so a failed cast does not throw
# ClassCastException on iOS -- code written to catch it silently uses the
# wrong object instead (issue #5531). Scoped to what a translation sees:
# core/ios, which the SpotBugs steps above already compiled, and JavaAPI,
# which they do not, so build it here.
- name: Check cast semantics
if: ${{ matrix.java-version == 8 }}
run: |
mvn -B -q -f vm/pom.xml -pl JavaAPI -am package -DskipTests
scripts/check-cast-semantics.sh --require-all
# ParparVM encodes the whole Java signature in the C function name, so a
# native whose implementation is spelled even slightly differently is NOT a
# link error: nothing references the real symbol, the dead-code pass reads
# that as "unused" and drops the Java method, and the feature ships inert.
# ios/core come from the SpotBugs step and JavaAPI from the cast step; the
# two desktop ports are not built yet, so compile them here.
# A NativeInterface method returning PeerComponent is wrapped by the
# generated stub, so an implementation that returns a peer of its own is
# wrapped twice and blows up with IllegalArgumentException the first time
# the component is shown -- valid Java that no compiler objects to, which
# is how all three ad cn1libs shipped with it.
- name: Check native peer return types
if: ${{ matrix.java-version == 8 }}
run: python3 scripts/check-native-peer-returns.py
# A cn1lib ships its native sources; the customer's build is the first
# compiler that sees them. Two workflows close that gap, but only for the
# libraries their matrices name, so this fails when a library is in
# neither -- the state cn1-admob and cn1-unity-levelplay were in.
- name: Check cn1lib native CI coverage
if: ${{ matrix.java-version == 8 }}
run: python3 scripts/check-cn1lib-native-coverage.py
- name: Install C compilers for the cn1lib native source check
if: ${{ matrix.java-version == 8 && steps.cn1libs.outputs.desktop != '' }}
# gcc for the Linux glue and the mingw-w64 cross compiler for the
# Windows glue, whose _WIN32 half (windows.h, LoadLibraryA,
# GetProcAddress) does not exist for a host target -- compiled as host
# C it parses the #else branch and reports success. Both are baked into
# the pr-ci-container image (.ci/container/Dockerfile); this step
# covers running against the previously published container before the
# rebuild propagates. Reuse the installed-package check and bounded
# mirror recovery used by the other runtime dependencies above.
run: bash scripts/ci/apt-get-install.sh gcc gcc-mingw-w64-x86-64
# The two platforms whose cn1lib sources need no SDK to check: the C
# glue the native win32/Linux ports compile into the app, and the
# JavaScript port implementations, which have no build step at all.
- name: Check cn1lib desktop and JavaScript native sources
if: ${{ matrix.java-version == 8 && steps.cn1libs.outputs.desktop != '' }}
env:
SELECTED_LIBS: ${{ steps.cn1libs.outputs.desktop }}
run: |
IFS=',' read -r -a libs <<< "$SELECTED_LIBS"
python3 scripts/check-cn1lib-native-sources.py --require-all "${libs[@]}"
# The Android half of the same gap: compile every cn1lib's Android
# sources against the artifacts its android.gradleDep pins. Runs on the
# JDK the Android build uses, because the pinned SDKs ship class files
# javac 8 cannot read.
- name: Check cn1lib Android sources against pinned SDKs
if: ${{ matrix.java-version == 8 && steps.cn1libs.outputs.android != '' }}
env:
SELECTED_LIBS: ${{ steps.cn1libs.outputs.android }}
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
run: |
IFS=',' read -r -a libs <<< "$SELECTED_LIBS"
JAVA17_HOME="${JAVA_HOME_17}" \
python3 scripts/check-cn1lib-android-api.py --require-all "${libs[@]}"
- name: Check native method signatures
if: ${{ matrix.java-version == 8 }}
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
run: |
mvn -B -q -f maven/pom.xml -pl windows,linux -am -DskipTests \
-Dcn1.binaries="${CN1_BINARIES}" compile
scripts/check-native-signatures.sh --require-all
# Linkage, which the signature gate above cannot see: it verifies that a
# native's NAME matches its Java method, and a mangled C++ symbol has the
# right name too. Needs no compiler and no build output, so it sits on its
# own step rather than behind the compile above.
- name: Check native C++ linkage
if: ${{ matrix.java-version == 8 }}
run: |
python3 scripts/check-native-cpp-linkage.py --self-test
python3 scripts/check-native-cpp-linkage.py
# A builder switches a port feature by uncommenting its //#define, and related
# defines share a prefix: a String.replace of //#define CN1_INCLUDE_CRYPTO also
# turned on CN1_INCLUDE_CRYPTO_GCM, linking private CommonCrypto calls into every
# app that used any crypto API and getting its App Store upload rejected.
# Executor.replaceMarker matches the whole name; this fails on any raw .replace of
# a #define literal that goes around it. Needs nothing built.
- name: Check builders switch defines by whole name
if: ${{ matrix.java-version == 8 }}
run: |
python3 scripts/check-builder-define-toggles.py --self-test
python3 scripts/check-builder-define-toggles.py
# The native warning gate itself runs on the macOS/Windows/Linux legs that
# actually compile C; what runs HERE is its parser, against a hand-authored
# fixture, plus a structural check on the checked-in baselines. Both need no
# compiler, and both cover the ways this gate goes wrong silently: a parser
# that stops recognising a diagnostic reports zero warnings, which is
# indistinguishable from a clean build, and a baseline edited into a shape
# that no longer matches masks nothing while looking like it does.
- name: Check native warning parser and baselines
if: ${{ matrix.java-version == 8 }}
run: scripts/check-native-warnings.sh --self-test
- name: Run JavaScript Port smoke integration
if: ${{ matrix.java-version == 8 }}
working-directory: vm
# Narrowed to resolution failures, because this step RUNS A TEST: retrying every nonzero
# exit would let an intermittent product failure pass on a later attempt and take the gate
# green with it. What this does cover is the run that died here with
# "Plugin org.apache.maven.plugins:maven-dependency-plugin:3.6.1 or one of its dependencies
# could not be resolved" before a single test had run -- a Maven Central failure, which a
# missing plugin version fails identically on every attempt anyway.
env:
RETRY_ONLY_MATCHING: transient
# Five attempts a minute apart rather than three at thirty seconds: Central
# refused two different jobs on this branch today, and a window of about a
# minute is shorter than the incidents have been. It costs nothing on a real
# failure, which RETRY_ONLY_MATCHING returns on the first attempt.
RETRY_ATTEMPTS: '5'
RETRY_DELAY_SECONDS: '60'
run: bash ../scripts/ci/retry.sh mvn -B test -pl tests -am -DfailIfNoTests=false -Dsurefire.failIfNoSpecifiedTests=false -Dtest=JavaScriptPortSmokeIntegrationTest
- name: Run Codename One Settings tests
if: ${{ matrix.java-version == 8 }}
# The tests are OFF by default because the module's app build needs a
# Codename One project set up, and nothing ran them anywhere -- the two
# workflows that touch the module pass -Dmaven.test.skip=true -- so every
# test written for the POM reader and the hint editor was dead weight and
# the bugs they cover reached review instead of CI.
#
# On the 8 leg rather than the 17 one even though the module is compiled
# with JDK 17: its POM binds codenameone-maven-plugin at process-classes
# and depends on codenameone-javase, and this is the leg that builds both.
# The 17 leg builds neither, so the step died at plugin resolution before
# running a test. JAVA_HOME_17 comes from the CI container image.
#
# LAST among the gates on this leg, and not before them: it reinstalls the
# maven plugin, and a failure here used to skip the SpotBugs steps that
# follow -- so the quality report then failed for a missing
# ByteCodeTranslator report, which said nothing about what actually broke.
env:
CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
RETRY_ONLY_MATCHING: transient
run: |
set -euo pipefail
test -n "${JAVA_HOME_17:-}" && test -d "${JAVA_HOME_17}"
(cd maven && mvn -B -Dmaven.javadoc.skip=true \
-Dcodename1.platform=javase \
-Dcn1.binaries="${CN1_BINARIES}" \
-pl codenameone-maven-plugin -am -Plocal-dev-javase -DskipTests install)
cd scripts/settings
# No xvfb, and DISPLAY cleared: the module's POM binds cn1:css at
# process-classes, the CSS compiler is headless, and none of these
# tests initialises Display. A test that starts needing a window
# should fail here rather than borrow one.
JAVA_HOME="${JAVA_HOME_17}" env -u DISPLAY -u WAYLAND_DISPLAY bash ../../scripts/ci/retry.sh \
mvn -B -pl common test -Dcn1.settings.skipTests=false
- name: Run Certificate Wizard tests
if: ${{ matrix.java-version == 8 }}
# The same arrangement as the Settings step above, and after it for the same
# reason: it needs the maven plugin and codenameone-javase that step has just
# installed. Before this the wizard's tests ran nowhere -- only the release
# workflow built the module, with tests skipped -- so the stylesheet checks, the
# push-capability rules and the signing-install tests were never exercised.
env:
RETRY_ONLY_MATCHING: transient
run: |
set -euo pipefail
cd scripts/certificatewizard
# Under xvfb, unlike the Settings step: CertificateWizardStructureHarness
# calls Display.init and builds real forms on the JavaSE port, which
# needs a display. The cn1:css goal this build also runs does not.
JAVA_HOME="${JAVA_HOME_17}" xvfb-run bash ../../scripts/ci/retry.sh \
mvn -B -pl common test -Dcn1.certificatewizard.skipTests=false
- name: Generate static analysis HTML summaries
if: ${{ !cancelled() && matrix.java-version == 8 }}
env:
QUALITY_REPORT_TARGET_DIRS: maven/core-unittests/target:maven/android/target:maven/ios/target:vm/ByteCodeTranslator/target:maven/codenameone-maven-plugin/target:maven/build-engine/target:maven/project-model/target:maven/codenameone-gradle-plugin/target:maven/build-hint-catalog/target:maven/build-hint-tools/target:maven/backend/target:maven/backend-test/target:maven/backend-parparvm/target:maven/javac/target:maven/android-res-compiler/target:maven/android-compat/target:maven/swing-compat/target:maven/javafx-compat/target:maven/compose-compat/target:maven/fxml-compiler/target:maven/desktop-compat-runtime/target
QUALITY_REPORT_SERVER_URL: ${{ github.server_url }}
QUALITY_REPORT_REPOSITORY: ${{ github.repository }}
QUALITY_REPORT_REF: ${{ github.event.pull_request.head.sha || github.sha }}
QUALITY_REPORT_GENERATE_HTML_ONLY: "1"
run: python3 .github/scripts/generate-quality-report.py
- name: Collect quality artifacts
if: ${{ !cancelled() && matrix.java-version == 8 }}
run: |
set -euo pipefail
mkdir -p quality-artifacts/static-analysis
mkdir -p quality-artifacts/coverage
shopt -s nullglob
for entry in \
"core-unittests:maven/core-unittests/target" \
"android:maven/android/target" \
"ios:maven/ios/target" \
"bytecode-translator:vm/ByteCodeTranslator/target" \
"maven-plugin:maven/codenameone-maven-plugin/target" \
"build-engine:maven/build-engine/target" \
"android-res-compiler:maven/android-res-compiler/target" \
"android-compat:maven/android-compat/target" \
"swing-compat:maven/swing-compat/target" \
"javafx-compat:maven/javafx-compat/target" \
"compose-compat:maven/compose-compat/target" \
"fxml-compiler:maven/fxml-compiler/target" \
"desktop-compat-runtime:maven/desktop-compat-runtime/target" \
"project-model:maven/project-model/target" \
"gradle-plugin:maven/codenameone-gradle-plugin/target" \
"backend:maven/backend/target" \
"backend-test:maven/backend-test/target" \
"javac:maven/javac/target"; do
label="${entry%%:*}"
dir="${entry#*:}"
for filename in spotbugsXml.xml spotbugs.xml; do
if [ -f "${dir}/${filename}" ]; then
cp "${dir}/${filename}" "quality-artifacts/static-analysis/spotbugs-${label}.xml"
break
fi
done
done
if [ -f maven/core-unittests/target/pmd.xml ]; then
cp maven/core-unittests/target/pmd.xml quality-artifacts/static-analysis/
fi
if [ -f maven/core-unittests/target/checkstyle-result.xml ]; then
cp maven/core-unittests/target/checkstyle-result.xml quality-artifacts/static-analysis/
fi
if [ -f maven/backend/target/pmd.xml ]; then
cp maven/backend/target/pmd.xml quality-artifacts/static-analysis/pmd-backend.xml
fi
if [ -f maven/backend-test/target/pmd.xml ]; then
cp maven/backend-test/target/pmd.xml quality-artifacts/static-analysis/pmd-backend-test.xml
fi
if [ -f maven/backend-test/target/checkstyle-result.xml ]; then
cp maven/backend-test/target/checkstyle-result.xml quality-artifacts/static-analysis/checkstyle-backend-test.xml
fi
if [ -f maven/backend-parparvm/target/pmd.xml ]; then
cp maven/backend-parparvm/target/pmd.xml quality-artifacts/static-analysis/pmd-backend-parparvm.xml
fi
if [ -f maven/backend/target/checkstyle-result.xml ]; then
cp maven/backend/target/checkstyle-result.xml quality-artifacts/static-analysis/checkstyle-backend.xml
fi
if [ -d target/quality-report ]; then
mkdir -p quality-artifacts/static-analysis/html
cp -R target/quality-report/. quality-artifacts/static-analysis/html/
fi
if [ -d maven/core-unittests/target/site/jacoco ]; then
cp -R maven/core-unittests/target/site/jacoco quality-artifacts/coverage/
fi
if [ "$(find quality-artifacts -type f | wc -l)" -eq 0 ]; then
echo "No quality artifacts were generated." > quality-artifacts/README.txt
fi
- name: Upload quality artifacts
if: ${{ !cancelled() && matrix.java-version == 8 }}
id: upload-quality-artifacts
uses: actions/upload-artifact@v7
with:
name: quality-artifacts
path: quality-artifacts
- name: Publish quality report previews
if: ${{ !cancelled() && matrix.java-version == 8 && github.server_url == 'https://github.com' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
id: publish-quality-previews
env:
GITHUB_TOKEN: ${{ github.token }}
SERVER_URL: ${{ github.server_url }}
REPOSITORY: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
RUN_ATTEMPT: ${{ github.run_attempt }}
run: |
set -euo pipefail
if [ "${SERVER_URL}" != "https://github.com" ]; then
echo "HTML previews are only published for github.com instances."
exit 0
fi
run_dir="runs/${RUN_ID}-${RUN_ATTEMPT}"
tmp_dir=$(mktemp -d)
dest_dir="${tmp_dir}/${run_dir}"
mkdir -p "${dest_dir}"
has_content=0
if compgen -G "target/quality-report/*.html" > /dev/null; then
mkdir -p "${dest_dir}/static-analysis"
cp target/quality-report/*.html "${dest_dir}/static-analysis/"
has_content=1
fi
if [ -d maven/core-unittests/target/site/jacoco ] && [ -f maven/core-unittests/target/site/jacoco/index.html ]; then
mkdir -p "${dest_dir}/coverage"
cp -R maven/core-unittests/target/site/jacoco/. "${dest_dir}/coverage/"
has_content=1
fi
if [ "${has_content}" -eq 0 ]; then
echo "No HTML outputs detected; skipping preview publishing."
exit 0
fi
printf '%s\n%s\n%s\n' \
'# Quality report previews' \
'' \
'This branch is automatically managed by the PR CI workflow and may be force-pushed.' \
> "${tmp_dir}/README.md"
git -C "${tmp_dir}" init -b previews >/dev/null
git -C "${tmp_dir}" config user.name "github-actions[bot]"
git -C "${tmp_dir}" config user.email "github-actions[bot]@users.noreply.github.com"
git -C "${tmp_dir}" add .
git -C "${tmp_dir}" commit -m "Publish quality report previews for run ${RUN_ID} (attempt ${RUN_ATTEMPT})" >/dev/null
remote_url="${SERVER_URL}/${REPOSITORY}.git"
token_remote_url="${remote_url/https:\/\//https://x-access-token:${GITHUB_TOKEN}@}"
for push_attempt in 1 2 3 4 5; do
if git -C "${tmp_dir}" push --force "${token_remote_url}" previews:quality-report-previews >/dev/null; then
break
fi
if [ "${push_attempt}" -eq 5 ]; then
echo "Failed to publish quality report previews after ${push_attempt} attempts." >&2
exit 1
fi
sleep $((push_attempt * 3))
done
commit_sha=$(git -C "${tmp_dir}" rev-parse HEAD)
raw_base="https://raw.githubusercontent.com/${REPOSITORY}/${commit_sha}/${run_dir}"
preview_base="https://htmlpreview.github.io/?${raw_base}"
{
echo "commit=${commit_sha}"
echo "run_path=${run_dir}"
} >> "$GITHUB_OUTPUT"
if [ -f "${dest_dir}/static-analysis/spotbugs.html" ]; then
echo "spotbugs_url=${preview_base}/static-analysis/spotbugs.html" >> "$GITHUB_OUTPUT"
fi
if [ -f "${dest_dir}/static-analysis/pmd.html" ]; then
echo "pmd_url=${preview_base}/static-analysis/pmd.html" >> "$GITHUB_OUTPUT"
fi
if [ -f "${dest_dir}/static-analysis/checkstyle.html" ]; then
echo "checkstyle_url=${preview_base}/static-analysis/checkstyle.html" >> "$GITHUB_OUTPUT"
fi
if [ -f "${dest_dir}/coverage/index.html" ]; then
echo "jacoco_url=${preview_base}/coverage/index.html" >> "$GITHUB_OUTPUT"
fi
- name: Generate quality report summary
if: ${{ !cancelled() && matrix.java-version == 8 }}
env:
QUALITY_REPORT_TARGET_DIRS: maven/core-unittests/target:maven/android/target:maven/ios/target:vm/ByteCodeTranslator/target:maven/codenameone-maven-plugin/target:maven/build-engine/target:maven/project-model/target:maven/codenameone-gradle-plugin/target:maven/build-hint-catalog/target:maven/build-hint-tools/target:maven/backend/target:maven/backend-test/target:maven/backend-parparvm/target:maven/javac/target:maven/android-res-compiler/target:maven/android-compat/target:maven/swing-compat/target:maven/javafx-compat/target:maven/compose-compat/target:maven/fxml-compiler/target:maven/desktop-compat-runtime/target
# Every project listed here must produce a SpotBugs report and that
# report must be empty. A missing report fails the gate too, so a
# SpotBugs run that silently stops running is not mistaken for clean.
QUALITY_REPORT_REQUIRED_SPOTBUGS: core-unittests:android:ios:ByteCodeTranslator:codenameone-maven-plugin:build-engine:project-model:codenameone-gradle-plugin:build-hint-catalog:build-hint-tools:backend:backend-test:javac:android-res-compiler:android-compat:swing-compat:javafx-compat:compose-compat:fxml-compiler:desktop-compat-runtime
# PMD and Checkstyle run on the core and on the backend runtime, and each
# must produce its report: without one, the PMD gate below it
# has nothing to read and passes.
QUALITY_REPORT_REQUIRED_PMD: core-unittests:backend:backend-test:backend-parparvm
QUALITY_REPORT_REQUIRED_CHECKSTYLE: core-unittests:backend:backend-test
QUALITY_REPORT_SERVER_URL: ${{ github.server_url }}
QUALITY_REPORT_REPOSITORY: ${{ github.repository }}
QUALITY_REPORT_REF: ${{ github.event.pull_request.head.sha || github.sha }}
SPOTBUGS_REPORT_URL: ${{ steps.upload-quality-artifacts.outputs.artifact-url }}
PMD_REPORT_URL: ${{ steps.upload-quality-artifacts.outputs.artifact-url }}
CHECKSTYLE_REPORT_URL: ${{ steps.upload-quality-artifacts.outputs.artifact-url }}
JACOCO_REPORT_URL: ${{ steps.upload-quality-artifacts.outputs.artifact-url }}
SPOTBUGS_HTML_URL: ${{ steps.publish-quality-previews.outputs.spotbugs_url }}
PMD_HTML_URL: ${{ steps.publish-quality-previews.outputs.pmd_url }}
CHECKSTYLE_HTML_URL: ${{ steps.publish-quality-previews.outputs.checkstyle_url }}
JACOCO_HTML_URL: ${{ steps.publish-quality-previews.outputs.jacoco_url }}
run: python3 .github/scripts/generate-quality-report.py
- name: Upload quality report summary
if: ${{ !cancelled() && matrix.java-version == 8 }}
uses: actions/upload-artifact@v7
with:
name: quality-report
path: quality-report.md
# Guards the property that the step below cannot fail this build. It
# could, and did: a 504 publishing a green report failed the job.
- name: Check the quality comment publisher cannot fail a build
if: ${{ !cancelled() && matrix.java-version == 8 }}
run: node .github/scripts/test-publish-quality-comment.mjs
- name: Publish quality report comment
if: ${{ !cancelled() && github.event_name == 'pull_request' && matrix.java-version == 8 && hashFiles('quality-report.md') != '' }}
uses: actions/github-script@v9
with:
# Retried rather than fatal on a transient 5xx. The publisher
# already warns instead of throwing; this is the cheaper half of
# the same fix, so the comment usually still lands. 4xx codes the
# action treats as permanent are not retried.
retries: 3
script: |
const { publishQualityComment } = require('./.github/scripts/publish-quality-comment.js');
await publishQualityComment({ github, context, core });
- name: Link cn1-binaries
if: ${{ matrix.java-version == 8 }}
run: ln -s /opt/cn1-binaries ../cn1-binaries
- name: Use upstream JCEF for the Ant build
if: ${{ matrix.java-version == 8 }}
run: ./scripts/ci-install-upstream-jcef-jar.sh
- name: Build CLDC11 JAR
if: ${{ matrix.java-version == 8 }}
run: ant -noinput -buildfile Ports/CLDC11/build.xml jar
- name: Build with Ant
if: ${{ matrix.java-version == 8 }}
run: |
mkdir -p ~/.codenameone
cp maven/UpdateCodenameOne.jar ~/.codenameone/
xvfb-run ant test-javase
- name: Build Release
if: matrix.java-version == 8
run: ant -noinput -buildfile CodenameOne/build.xml weeklyLibUpdate
- name: Set up Java 25 for JavaDocs
if: matrix.java-version == 8
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
- name: Build JavaDocs
if: matrix.java-version == 8
run: ./.github/scripts/build_javadocs.sh
- name: Restore Java 8 after JavaDocs
if: matrix.java-version == 8
run: |
echo "JAVA_HOME=${JAVA_HOME_8}" >> $GITHUB_ENV
echo "${JAVA_HOME_8}/bin" >> $GITHUB_PATH
- name: Upload JavaDocs artifact
if: matrix.java-version == 8
uses: actions/upload-artifact@v7
with:
name: CodenameOne-javadocs
path: CodenameOne/javadocs.zip
- name: Build iOS Port
if: ${{ matrix.java-version == 8 }}
run: ant -noinput -buildfile Ports/iOSPort/build.xml jar
- name: Build iOS VM API
if: ${{ matrix.java-version == 8 }}
run: mvn -f vm/JavaAPI/pom.xml package
- name: Upload a Build Artifact
if: matrix.java-version == 8
uses: actions/upload-artifact@v7
with:
name: JavaAPI.jar
path: vm/JavaAPI/target/JavaAPI-1.0-SNAPSHOT.jar
- name: Build iOS VM
if: ${{ matrix.java-version == 8 }}
run: mvn -f vm/ByteCodeTranslator/pom.xml package
- name: Upload a Build Artifact
if: matrix.java-version == 8
uses: actions/upload-artifact@v7
with:
name: ByteCodeTranslator.jar
path: vm/ByteCodeTranslator/target/ByteCodeTranslator-1.0-SNAPSHOT.jar
- name: Upload a Build Artifact
if: matrix.java-version == 8
uses: actions/upload-artifact@v7
with:
name: CLDC11.jar
path: Ports/CLDC11/dist/CLDC11.jar
- name: Build Android Port
if: ${{ matrix.java-version == 8 }}
run: ant -noinput -buildfile Ports/Android/build.xml jar
- name: Packaging Everything
if: matrix.java-version == 8
run: zip -j result.zip CodenameOne/javadocs.zip CodenameOne/dist/CodenameOne.jar CodenameOne/updatedLibs.zip Ports/JavaSE/dist/JavaSE.jar build/CodenameOneDist/CodenameOne/demos/CodenameOne_SRC.zip
# Handed to a separate job rather than deployed here. See deploy-dist.
- name: Upload the distribution bundle
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.java-version == 8 }}
uses: actions/upload-artifact@v7
with:
name: result.zip
path: result.zip
retention-days: 1
- name: Upload a Build Artifact
if: matrix.java-version == 8
uses: actions/upload-artifact@v7
with:
name: JavaSE.jar
path: Ports/JavaSE/dist/JavaSE.jar
deploy-dist:
# Gated at the JOB level, deliberately, and this is not a style preference.
# A Docker-based action is BUILT during job setup, before any step's `if` is
# evaluated -- so while this deploy step was inside build-test it made every
# matrix leg, including the Java 17 and 21 legs that could never satisfy its
# condition, pull alpine:latest from Docker Hub to build an action they were
# never going to run. A Docker Hub timeout then failed a pull-request job for
# a deploy that was not happening: exactly what killed build-test (17) with
# "failed to resolve source metadata for docker.io/library/alpine:latest"
# after three retries. A job-level condition skips setup entirely, so on a
# pull request the image is never fetched.
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
needs: build-test
runs-on: ubuntu-24.04
steps:
- name: Download the distribution bundle
uses: actions/download-artifact@v7
with:
name: result.zip
- name: Copying Files to Server
uses: marcodallasanta/ssh-scp-deploy@v1.0.5
with:
host: ${{ secrets.WP_HOST }}
user: ${{ secrets.WP_USER }}
password: ${{ secrets.WP_PASSWORD }}
local: result.zip