Commit native theme .res files; add native-themes-sync workflow#4976
Merged
Conversation
iOSModernTheme.res and AndroidMaterialTheme.res used to be regenerated
on every iOS / Android / website build from native-themes/*/theme.css
via scripts/build-native-themes.sh, but the .res files themselves were
gitignored. That meant the released codenameone-ios artifact, the
BuildDaemon's sibling cn1 checkout, and every local build could each be
producing slightly different bytes depending on when they last ran the
CSS compiler and which compiler revision was in their ~/.m2.
Commit the six shipping copies (Themes/, JS webapp assets, iOS port
nativeSources, Android port src) and add a workflow that regenerates
them on master whenever native-themes/, the CSS compiler, or the
build-native-themes.sh script changes, committing the result back
directly (no PR). Pushes via GITHUB_TOKEN do not retrigger workflows
so the commit-back step cannot loop.
Downstream pipelines stop invoking build-native-themes.sh and just use
the committed .res file:
- scripts/build-ios-port.sh, scripts/build-android-port.sh drop the
compile + cp staging step
- scripts/website/build.sh drops ensure_native_themes()
- cn1playground / initializr poms drop failonerror=false on the
Themes/ copy
- maven/javase/pom.xml drops failonerror=false on the simulator
fat-jar copy
- Ports/iOSPort/build.xml, Ports/Android/build.xml drop failonerror
on the modern-theme copy step
scripts/build-native-themes.sh now also mirrors directly into the iOS
and Android port staging dirs so the workflow only has to git-add the
fixed list.
Run scripts/build-native-themes.sh manually for local iteration on
theme.css; otherwise pull master and the .res is already in place.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Compared 20 screenshots: 20 matched. |
Contributor
Cloudflare Preview
|
Collaborator
Author
|
Compared 110 screenshots: 110 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
Collaborator
Author
|
Compared 110 screenshots: 110 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Collaborator
Author
|
Compared 110 screenshots: 110 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Contributor
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
testRoundBorderShadowSpreadAndPaintingCaches was scanning client property keys "cn1$$-rbcache1".."cn1$$-rbcache50" to locate the cache RoundBorder.paintBorderBackground stores under the border's instanceVal suffix. Since instanceVal comes off a static counter shared across the entire JVM, the scan would miss whenever earlier tests in the same surefire run created more than 50 RoundBorder instances. The committed iOSModernTheme.res in this PR unblocks NativeThemeBindingsTest (it used to silently skip when the .res was a gitignored build artifact). That test now loads the iOS Modern theme before BorderAndPlafTest runs, parsing many border definitions and pushing instanceCounter past 50. Read instanceVal off the border under test reflectively and look up exactly that key, so the assertion no longer depends on how many other RoundBorders earlier tests minted in the same JVM. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
The previous commit on this branch committed the modern .res files in
six places (Themes/, JS webapp assets, iOSPort/nativeSources,
Android/src). That's exactly the duplication problem this PR is trying
to remove - each port carried its own copy in git, and they could drift.
Drop the four port-side committed copies and have the port poms read
Themes/*.res directly at build time:
- maven/ios/pom.xml: nativeios.jar zip step gets a second fileset
that pulls Themes/iOSModernTheme.res in, plus an explicit exclude
on iOSModernTheme.res from the nativeSources fileset so a stale
local copy can't shadow the canonical one.
- maven/android/pom.xml: compile-android profile gets a second
<resource> entry pointing at Themes/ filtered to
AndroidMaterialTheme.res.
JavaScriptPort/src/main/webapp/assets is gitignored again for the two
modern .res files; scripts/build-native-themes.sh still mirrors there
for local JS port runs, treating the directory as a build artifact.
scripts/build-native-themes.sh reverts the IOS_NATIVE_DIR /
ANDROID_SRC_DIR mirroring I added in the previous commit, since those
staging copies are no longer needed.
The native-themes-sync workflow now only commits Themes/iOSModernTheme.res
and Themes/AndroidMaterialTheme.res - the two canonical files.
Verified locally: `mvn -pl ios -am install` produces a nativeios.jar
containing iOSModernTheme.res sourced from Themes/, with no staged copy
under Ports/iOSPort/nativeSources/.
Note: a fuller redesign would have the iOS / Android builders DELETE
the .res based on a build hint (e.g. nativeTheme=legacy) rather than
the current "include the .res unconditionally and pick at runtime"
model. That's a larger change left for a follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nativeios.jar / the Android port jar now always ship all three native themes (modern + flat + legacy on each platform). The runtime installNativeTheme picks one based on the user's theme-mode build hint and the other two ride along as dead bytes in the .ipa / .apk. Resolve the effective mode in IPhoneBuilder and AndroidGradleBuilder right after the port jar is unzipped, and delete the .res files that won't be loaded. The mapping mirrors the runtime exactly: iOS (IOSImplementation.installNativeTheme): modern / liquid -> iOSModernTheme.res ios7 / flat / auto -> iOS7Theme.res anything else -> iPhoneTheme.res Android (AndroidImplementation.installNativeTheme): material / modern / auto -> AndroidMaterialTheme.res hololight / holo -> android_holo_light.res anything else (incl. legacy) -> androidTheme.res Drive-by fixes in the noExtraResources branches: extend the iOS list to include iOSModernTheme.res (previously missed) and correct the mis-cased "IPhoneTheme.res" to "iPhoneTheme.res" so the delete actually fires on case-sensitive file systems. Add AndroidMaterialTheme.res to the Android list for the same reason. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-res-files # Conflicts: # scripts/build-android-port.sh # scripts/build-ios-port.sh
Reverts 19c124f. The mode-driven delete in IPhoneBuilder / AndroidGradleBuilder assumed apps only ever load the .res that matches the build-hint-derived mode, but apps (e.g. DualAppearanceBaseTest in the screenshot suite) load other themes via Resources.open at runtime to render side-by-side comparisons. Deleting the inactive .res files from the .ipa / .apk made those loads fail and broke the on-device screenshot tests. Smaller-bundle minimization can come back later as an opt-in build hint (only delete when the user explicitly says they don't dynamically load themes), but the default has to keep all three themes shipped so runtime Resources.open lookups work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The .res files I committed initially were produced against the pre-#4957 CSS compiler (MINOR_VERSION=12). After merging master, #4957 bumped the resource format to MINOR_VERSION=14, but I hadn't rebuilt the .res, so what was committed at offset 0x0B was 0x0c (12) while every fresh CI build produces 0x0e (14). The screenshot baselines on master were captured against the v14 bytes, so the v12 bytes I committed caused pixel diffs across every theme test in scripts-android.yml (ButtonTheme_*, ListTheme_*, DialogTheme_*, ...). Regen Themes/{iOSModernTheme,AndroidMaterialTheme}.res with the post-merge css-compiler under JDK 8 (matching the pr-ci-container's toolchain) so the committed bytes match what scripts-android.yml's emulator renders against the existing baselines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_sources.jar
My earlier maven/android/pom.xml change put AndroidMaterialTheme.res in
the outer codenameone-android.jar's outputDirectory via a <resource>
entry, but the runtime delivery path for the Android port is the
INNER android_port_sources.jar inside that outer jar:
AndroidGradleBuilder unzips that inner jar into the user app's APK
assets/, and AndroidImplementation.installNativeTheme then reads
/AndroidMaterialTheme.res from AssetManager.
The inner jar is built by the bundle-android profile's <zip> step from
${real.src.dir} (= Ports/Android/src/), which doesn't contain the .res
once I un-staged the Ports/Android/src/AndroidMaterialTheme.res copy.
So the .res never reached the APK, the runtime fell back to
android_holo_light.res, and the *Theme_light/_dark screenshot tests
diffed against the material baselines.
Add a second fileset on Themes/ to the bundle-android <zip> step so
android_port_sources.jar carries AndroidMaterialTheme.res, with
Themes/ still as the single source of truth (no Ports/Android/src/
staging copy needed).
Verified locally: the rebuilt android_port_sources.jar now lists
AndroidMaterialTheme.res alongside androidTheme.res /
android_holo_light.res.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The CSS-compiled native theme
.resfiles (iOSModernTheme.res,AndroidMaterialTheme.res) used to be gitignored build artifacts regenerated on every iOS / Android / website build fromnative-themes/*/theme.cssviascripts/build-native-themes.sh. The releasedcodenameone-iosartifact, the BuildDaemon's siblingcn1checkout, and every local build could each be producing slightly different bytes depending on when they last ran the CSS compiler and which compiler revision was in their~/.m2— the source of the drift report in discussion #4968.This PR commits the six shipping
.rescopies and adds a workflow that keeps master coherent:Themes/,Ports/JavaScriptPort/src/main/webapp/assets/,Ports/iOSPort/nativeSources/,Ports/Android/src/. Same pattern as the legacyiOS7Theme.res/iPhoneTheme.res..github/workflows/native-themes-sync.yml: on push to master with paths-filter fornative-themes/**,maven/css-compiler/**, or the build script itself, rebuilds the.resand commits the diff directly back to master (no PR). Pushes viaGITHUB_TOKENdo not retrigger workflows, so the commit-back step cannot loop..res:scripts/build-ios-port.sh,scripts/build-android-port.shdrop thebuild-native-themes.shinvocation and thecpstaging stepscripts/website/build.shdropsensure_native_themes()cn1playground/initializrpoms dropfailonerror="false"on theThemes/copymaven/javase/pom.xmldropsfailonerror="false"on the simulator fat-jar copyPorts/iOSPort/build.xml,Ports/Android/build.xmldropfailonerror="false"on the modern-theme copyscripts/build-native-themes.shnow also mirrors directly into the iOS / Android port staging dirs, so the workflow only has togit addthe fixed list.Companion PR for the BuildDaemon (drops the matching
failonerror="false"on the sibling cn1 copy) will follow.Heads up before merge
The workflow's commit-back step needs
contents:writeonGITHUB_TOKENplus permission to push to master. If branch protection onmasterrequires PR + review and doesn't include GitHub Actions in the bypass list, that push will fail. Addinggithub-actions[bot]to the "Allow specified actors to bypass required pull requests" list (or switching to a fine-grained PAT) fixes it.Test plan
.github/workflows/native-themes-sync.ymlis allowed to push tomaster(branch protection bypass / token scope).reschange) since the.resfiles in this PR are already currentnative-themes/ios-modern/theme.cssin a follow-up PR, merge, and verify the workflow regenerates + commitsThemes/iOSModernTheme.resand the five mirror copies./scripts/build-ios-port.shstill produces an iOS port jar withiOSModernTheme.resinsidenativeios.jar./scripts/build-android-port.shstill bundlesAndroidMaterialTheme.resinto the Android port jar🤖 Generated with Claude Code