Repository navigation
JSON mapping: codecs, creators, generics, arrays and null semantics #6294
Workflow file for this run
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
| # Real-life Windows build pipeline: CROSS-COMPILE the native Windows port's full | |
| # hellocodenameone screenshot-suite .exe on a *Linux* runner (clang-cl + lld-link | |
| # + llvm-rc against an xwin-laid-out Windows SDK, with the WebView2 SDK fetched so | |
| # the BrowserComponent peer is linked), then RUN that exact Linux-built binary on | |
| # a real Windows runner and capture the screenshot suite over the cn1ss WebSocket. | |
| # | |
| # This mirrors how a Codename One app is actually shipped for Windows -- compiled | |
| # on a (Linux) build host, executed on the user's Windows machine -- which neither | |
| # of the other two Windows workflows does on its own: windows-cross-compile.yml | |
| # builds on Linux but only *links* (never runs), and parparvm-tests-windows.yml | |
| # builds *natively on Windows* and runs. Here the binary that renders on Windows | |
| # is the one cross-compiled on Linux, browser included. | |
| # | |
| # Three jobs, artifact-chained within the run: | |
| # cross-build (ubuntu) -> uploads WinHelloMain.exe (Linux-cross-compiled, x64) | |
| # run-on-windows (x64) -> downloads + runs it, captures the suite PNGs | |
| # compare-comment (ubuntu)-> diffs the PNGs vs the in-repo baseline, posts the PR | |
| name: Windows cross-build + run (Linux build -> Windows run) | |
| on: | |
| # Manual dispatch: this PR's changed-file count exceeds GitHub's paths-filter | |
| # diff limit, so pull_request triggers stopped firing -- dispatch with | |
| # gh workflow run <file> --ref <branch> | |
| workflow_dispatch: | |
| schedule: | |
| - cron: '55 1 * * *' | |
| pull_request: | |
| paths: | |
| # The application these jobs build compiles a Unity project, from an | |
| # archive that unity-gallery-prebuilt.yml makes out of these. | |
| - 'scripts/unity-compat-samples/gallery/**' | |
| - 'maven/cil-translator/**' | |
| - 'maven/unity-compat/**' | |
| - 'maven/build-engine/src/main/java/com/codename1/maven/Unity*' | |
| - 'maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/*Unity*' | |
| - 'scripts/unity-gallery-prebuilt.sh' | |
| - '.github/workflows/unity-gallery-prebuilt.yml' | |
| - '.github/actions/unity-gallery-prebuilt/**' | |
| - '.github/workflows/windows-cross-build-run.yml' | |
| - 'vm/**' | |
| - 'Ports/WindowsPort/**' | |
| - 'maven/windows/**' | |
| - 'scripts/windows/**' | |
| - 'scripts/hellocodenameone/**' | |
| # This job's first step runs through both CI shell helpers, so a change to either has | |
| # to be exercised here rather than merged untested -- the same reason every other | |
| # consumer lists them. | |
| - 'scripts/ci/apt-get-install.sh' | |
| - 'scripts/ci/apt-get-update.sh' | |
| - 'scripts/ci/retry.sh' | |
| - '!vm/**/README.md' | |
| - '!vm/**/readme.md' | |
| - '!vm/**/docs/**' | |
| push: | |
| branches: [ master, main ] | |
| paths: | |
| # The application these jobs build compiles a Unity project, from an | |
| # archive that unity-gallery-prebuilt.yml makes out of these. | |
| - 'scripts/unity-compat-samples/gallery/**' | |
| - 'maven/cil-translator/**' | |
| - 'maven/unity-compat/**' | |
| - 'maven/build-engine/src/main/java/com/codename1/maven/Unity*' | |
| - 'maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/*Unity*' | |
| - 'scripts/unity-gallery-prebuilt.sh' | |
| - '.github/workflows/unity-gallery-prebuilt.yml' | |
| - '.github/actions/unity-gallery-prebuilt/**' | |
| - '.github/workflows/windows-cross-build-run.yml' | |
| - 'vm/**' | |
| - 'Ports/WindowsPort/**' | |
| - 'maven/windows/**' | |
| - 'scripts/ci/apt-get-install.sh' | |
| - 'scripts/ci/apt-get-update.sh' | |
| - 'scripts/ci/retry.sh' | |
| 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 | |
| env: | |
| # 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' | |
| jobs: | |
| # The application has a Unity project in it. One Linux job compiles it and | |
| # hands the result to the jobs below as an artifact; none of them installs | |
| # the .NET SDK or builds the Unity modules. | |
| unity-gallery: | |
| uses: ./.github/workflows/unity-gallery-prebuilt.yml | |
| cross-build: | |
| needs: unity-gallery | |
| name: cross-build suite exe (Linux, x64 + WebView2) | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| # The native BrowserComponent peer (cn1_windows_browser.cpp) is C++ that | |
| # uses the MSVC STL via the xwin headers; the MSVC STL gates on a recent | |
| # clang (older clang-cl trips STL1000 "Unexpected compiler version"), so | |
| # pin LLVM 19 for the cross-build rather than the distro default. | |
| - name: Install LLVM 19 + CMake/Ninja | |
| # Capped well inside the job's 60 minutes. The inner bounds give a stalled mirror a | |
| # second chance; this one guarantees that however they compound, the step cannot eat | |
| # the budget the build itself needs -- which is what happened twice on 2026-08-19, | |
| # each time surfacing as "Artifact not found" in a different job. | |
| timeout-minutes: 20 | |
| run: | | |
| set -e | |
| # No explicit index refresh here: apt-get-install.sh does one itself, and doing it | |
| # twice doubles the time a stalling mirror can take before anything is installed. | |
| # No xvfb: nothing in this job opens a window. The sample build's css | |
| # goal compiles theme.css headless, and the PE this job produces is | |
| # run by the Windows jobs downstream, not here. | |
| # Every network call here is bounded and retried. On 2026-08-19 this step sat in | |
| # its first line for a full hour and was cancelled having installed nothing, which | |
| # then failed the screenshot-comment job downstream for a missing artifact. That is | |
| # the same hang apt-get-install.sh was written for -- a hung mirror should cost one | |
| # attempt, not the job -- and this workflow had never adopted it. | |
| bash scripts/ci/apt-get-install.sh cmake ninja-build unzip | |
| # apt.llvm.org is a single host with no mirror, and llvm.sh both adds its repo and | |
| # installs from it, so it is the likeliest thing in this step to stall forever. | |
| RETRY_ATTEMPTS=3 bash scripts/ci/retry.sh \ | |
| wget -q --timeout=30 --tries=3 -O llvm.sh https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| # Two attempts of ten minutes, not three of fifteen: the point of a bound is to | |
| # leave the job enough budget to do its actual work afterwards, and 3x900s is | |
| # three quarters of the runner's hour. | |
| RETRY_ATTEMPTS=2 bash scripts/ci/retry.sh timeout 600 sudo ./llvm.sh 19 | |
| bash scripts/ci/apt-get-install.sh clang-19 lld-19 llvm-19 | |
| echo "/usr/lib/llvm-19/bin" >> "$GITHUB_PATH" | |
| /usr/lib/llvm-19/bin/clang-cl --version | |
| /usr/lib/llvm-19/bin/lld-link --version 2>&1 | head -1 || true | |
| /usr/lib/llvm-19/bin/llvm-rc --version 2>&1 | head -1 || true | |
| # JDK matrix the translator harness auto-discovers (JDK_*_HOME). JDK 8 is | |
| # restored last so it is the active JAVA_HOME (it builds codename1-core and | |
| # is what CompilerHelper translates with). JDK 17 builds the sample app. | |
| - name: Set up JDK 8 | |
| uses: actions/setup-java@v5 | |
| with: { distribution: 'temurin', java-version: '8' } | |
| - run: echo "JDK_8_HOME=$JAVA_HOME" >> $GITHUB_ENV | |
| - name: Set up JDK 11 | |
| uses: actions/setup-java@v5 | |
| with: { distribution: 'temurin', java-version: '11' } | |
| - run: echo "JDK_11_HOME=$JAVA_HOME" >> $GITHUB_ENV | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v5 | |
| with: { distribution: 'temurin', java-version: '17' } | |
| - run: echo "JDK_17_HOME=$JAVA_HOME" >> $GITHUB_ENV | |
| - name: Restore JDK 8 as the active JDK | |
| uses: actions/setup-java@v5 | |
| with: { distribution: 'temurin', java-version: '8' } | |
| - name: Install xwin + lay out the Windows SDK (x64) | |
| env: | |
| # `cargo install xwin` and `xwin splat` flake on transient crates.io / | |
| # download errors ("curl [16] HTTP2 framing layer", "[55] OpenSSL | |
| # SSL_read unexpected eof"). Disable HTTP/2 multiplexing (forces | |
| # HTTP/1.1, which avoids the framing errors) and let cargo retry. | |
| CARGO_NET_RETRY: "10" | |
| CARGO_HTTP_MULTIPLEXING: "false" | |
| run: | | |
| set -e | |
| # Retry the whole install/splat a few times for non-cargo download | |
| # hiccups (the xwin SDK fetch from Microsoft). | |
| n=0 | |
| until [ "$n" -ge 3 ]; do | |
| cargo install xwin --version 0.9.0 --locked \ | |
| && xwin --accept-license --arch x86_64 splat --output "$RUNNER_TEMP/xwin-sdk" \ | |
| && break | |
| n=$((n+1)) | |
| echo "xwin install/splat attempt $n failed; retrying after backoff..." | |
| rm -rf "$RUNNER_TEMP/xwin-sdk" | |
| sleep $((n*15)) | |
| done | |
| test -d "$RUNNER_TEMP/xwin-sdk/crt/include" | |
| test -f "$RUNNER_TEMP/xwin-sdk/sdk/include/um/d2d1.h" | |
| # Fetch the WebView2 NuGet SDK on Linux (portable bash counterpart of the | |
| # Windows fetch script). It is a plain zip of headers + the x64/arm64 static | |
| # loader libs, so the cross-build links the BrowserComponent peer exactly | |
| # like the Windows runners do. Non-fatal: if the download fails the browser | |
| # natives compile as stubs (WEBVIEW2_SDK_DIR stays unset) and the suite runs | |
| # without the BrowserComponent tile rather than failing the whole pipeline. | |
| - name: Fetch WebView2 SDK (Linux) | |
| continue-on-error: true | |
| run: | | |
| set -e | |
| LINE="$(bash scripts/windows/fetch-webview2-sdk.sh "$RUNNER_TEMP/webview2sdk" | tail -1)" | |
| echo "Resolved: $LINE" | |
| case "$LINE" in | |
| WEBVIEW2_SDK_DIR=*) echo "$LINE" >> "$GITHUB_ENV" ;; | |
| *) echo "WebView2 fetch did not yield a dir; browser will be stubbed" ;; | |
| esac | |
| # Build codename1-core + the Windows port, the codenameone maven plugin | |
| # (runs transcode-svg / css / annotation processing during the sample build) | |
| # and cn1-ads-mock (a sample dependency) -- the same inputs the native | |
| # Windows screenshot job installs. JDK 8: core is source/target 1.5. | |
| - name: Build core + Windows port + CN1 maven plugin (JDK 8) | |
| env: | |
| # A build-only step: it compiles and then asserts two class files | |
| # exist, so there is no test for a blanket retry to launder. Narrowed | |
| # to resolution failures anyway, on the same principle the steps below | |
| # apply -- this died on `Connection reset` pulling maven-plugin-api | |
| # from Central, which is the canonical set's business and not this | |
| # branch's. | |
| RETRY_ONLY_MATCHING: transient | |
| run: | | |
| cd maven | |
| JAVA_HOME="$JDK_8_HOME" bash ../scripts/ci/retry.sh \ | |
| mvn -B -pl windows,codenameone-maven-plugin,cn1-ads-mock -am \ | |
| -DskipTests '-Dmaven.javadoc.skip=true' '-Plocal-dev-javase' install | |
| test -f core/target/classes/com/codename1/ui/Form.class | |
| test -f windows/target/classes/com/codename1/impl/windows/WindowsImplementation.class | |
| # After everything that fills the local Maven repository and before the | |
| # application is built; this job has no .NET SDK (see the action). | |
| - name: Unpack the Unity gallery prebuilt | |
| uses: ./.github/actions/unity-gallery-prebuilt | |
| # Build the hellocodenameone screenshot app into common/target/classes (the | |
| # suite the cross-build translates). Plain Maven build of the sample on JDK | |
| # 17 -- exactly what a fresh initializr project does; the plugin runs | |
| # transcode-svg/css/annotation processing. Kotlin 1.6.0 compiles on JDK 17. | |
| # Seed an empty guibuilder.jar marker to skip the codenameone install | |
| # bootstrap's network step (artifacts are already in the local repo). | |
| - name: Build hellocodenameone-common (Maven, JDK 17) | |
| env: | |
| JDK_17_HOME: ${{ env.JDK_17_HOME }} | |
| run: | | |
| set -e | |
| export JAVA_HOME="$JDK_17_HOME" | |
| mkdir -p "$HOME/.codenameone" | |
| [ -f "$HOME/.codenameone/guibuilder.jar" ] || : > "$HOME/.codenameone/guibuilder.jar" | |
| RETRY_ONLY_MATCHING=transient bash scripts/ci/retry.sh \ | |
| mvn -B -f scripts/hellocodenameone/pom.xml -pl common -am install \ | |
| -DskipTests '-Dmaven.javadoc.skip=true' | |
| test -f scripts/hellocodenameone/common/target/classes/com/codenameone/examples/hellocodenameone/tests/Cn1ssDeviceRunner.class | |
| test -f scripts/hellocodenameone/common/target/classes/com/codename1/generated/svg/SVGRegistry.class | |
| # Translate the full suite and cross-compile it to a Windows x64 PE with | |
| # clang-cl + xwin. WEBVIEW2_SDK_DIR (exported above when the fetch worked) | |
| # flows into the generated CMake and links the BrowserComponent peer. The | |
| # exe is written to CN1_CROSS_EXE_OUT for the upload below. | |
| - name: Cross-build the full suite exe (clang-cl + xwin + WebView2) | |
| env: | |
| CN1_XWIN_SYSROOT: ${{ runner.temp }}/xwin-sdk | |
| CN1_CLANG_CL: clang-cl | |
| CN1_LLVM_RC: llvm-rc | |
| CN1_CROSS_EXE_OUT: ${{ github.workspace }}/artifacts/WinHelloMain.exe | |
| # Narrowed to resolution failures, because this step RUNS A TEST. The wrapper | |
| # retries every nonzero exit unless it is told what to look for, so a cross-build or | |
| # translation failure that came and went would have passed on attempt two and taken | |
| # the gate green with it -- laundering exactly the kind of intermittent product bug | |
| # this job exists to catch. The unit test workflow narrows it for the same reason. | |
| RETRY_ONLY_MATCHING: transient | |
| run: | | |
| cd vm | |
| # Through the retry wrapper: this resolves plugins from Maven Central and the runner | |
| # edge intermittently resets the connection mid-download, which Maven treats as a | |
| # permanent resolution failure -- this run died on a truncated plexus-utils with nothing | |
| # compiled yet. A real failure fails the same way on every attempt. | |
| JAVA_HOME="$JDK_8_HOME" bash ../scripts/ci/retry.sh mvn -B -pl tests -am test \ | |
| '-Dtest=CleanTargetIntegrationTest#crossBuildsHelloSuiteExe' \ | |
| '-Dsurefire.failIfNoSpecifiedTests=false' | |
| test -f "$CN1_CROSS_EXE_OUT" | |
| ls -l "$CN1_CROSS_EXE_OUT" | |
| # The CI test server (scripts/hellocodenameone/backend) the suite streams its | |
| # screenshots to and drives its networking tests against, as a runnable copy | |
| # the Windows job runs with plain java: that job has a JDK and no Maven | |
| # repository with the backend in it. Built here, where the plugin and the | |
| # backend runtime are a Maven install away. | |
| - name: Build the test server | |
| env: | |
| JAVA17_HOME: ${{ env.JDK_17_HOME }} | |
| RETRY_ONLY_MATCHING: transient | |
| run: | | |
| bash scripts/ci/retry.sh scripts/hellocodenameone/backend/server.sh dist "$GITHUB_WORKSPACE/artifacts/cn1ss-server" | |
| test -f "$GITHUB_WORKSPACE/artifacts/cn1ss-server/classes/META-INF/cn1-backend-main" | |
| - name: Upload cross-built suite exe | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-cross-suite-exe | |
| # The .exe plus its separate .pdb symbol companion (for crash symbolication). | |
| path: | | |
| artifacts/WinHelloMain.exe | |
| artifacts/WinHelloMain.pdb | |
| artifacts/cn1ss-server/** | |
| if-no-files-found: error | |
| retention-days: 1 | |
| run-on-windows: | |
| name: run cross-built exe + capture (Windows x64) | |
| needs: cross-build | |
| runs-on: windows-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| # Only a JDK is needed here: with CN1_PREBUILT_EXE set the capture test | |
| # neither translates nor builds -- it runs the test server the cross-build | |
| # job built (CN1SS_SERVER_DIST), launches the prebuilt exe and collects the | |
| # PNGs it streams. No MSVC / | |
| # Ninja / clang. windows-latest ships the WebView2 Evergreen runtime the | |
| # BrowserComponent peer loads at activation. | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| cache: 'maven' | |
| - name: Download cross-built suite exe | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: windows-cross-suite-exe | |
| path: artifacts | |
| - name: Verify the downloaded exe | |
| shell: pwsh | |
| run: | | |
| $exe = "artifacts/WinHelloMain.exe" | |
| if (!(Test-Path $exe)) { Write-Error "cross-built exe missing: $exe"; exit 1 } | |
| Write-Host "Cross-built exe: $((Get-Item $exe).Length) bytes" | |
| # Run the Linux-cross-compiled exe and capture the screenshot suite over the | |
| # cn1ss WebSocket. CN1_PREBUILT_EXE makes the capture test run this exact | |
| # binary instead of building one. ~112 PNGs land in CN1_SHOT_OUTPUT_DIR. | |
| - name: Run cross-built suite + capture screenshots | |
| working-directory: vm | |
| shell: pwsh | |
| env: | |
| CN1_PREBUILT_EXE: ${{ github.workspace }}\artifacts\WinHelloMain.exe | |
| CN1SS_SERVER_DIST: ${{ github.workspace }}\artifacts\cn1ss-server | |
| CN1_PERFORMANCE_BINARY_OUT: ${{ github.workspace }}\artifacts\windows-port\raw\benchmark-app.exe | |
| CN1_REQUIRE_PERFORMANCE: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} | |
| CN1_SHOT_OUTPUT_DIR: ${{ github.workspace }}\artifacts\windows-port\raw | |
| run: | | |
| mvn -B clean package -pl JavaAPI -am -DskipTests | |
| mvn -B test -pl tests -am '-Dtest=CleanTargetIntegrationTest#capturesHelloSuiteOverWebSocket' '-Dsurefire.failIfNoSpecifiedTests=false' | |
| - name: Upload screenshot artifact (cross-compiled, x64) | |
| if: ${{ !cancelled() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-cross-screenshot-raw | |
| path: artifacts/windows-port/raw | |
| if-no-files-found: warn | |
| retention-days: 14 | |
| # Diffs the screenshots produced by the Linux-cross-compiled binary against the | |
| # in-repo baseline (scripts/windows/screenshots) and posts them to the PR, with | |
| # a marker distinct from the native-Windows screenshot comment so both coexist. | |
| compare-comment: | |
| name: cross-compiled screenshot-comment | |
| needs: run-on-windows | |
| # !cancelled(), for the same reason as linux-build-run.yml: without it GitHub | |
| # skips this job whenever run-on-windows fails, so the run that most needs | |
| # reporting uploads raw evidence but no port-status artifact. The nightly | |
| # sweep then falls back to an older run, and while that one is still inside | |
| # the freshness window the public table keeps showing it -- the current | |
| # Windows failure masked by a stale pass. The workflow still goes red because | |
| # run-on-windows itself failed. | |
| if: >- | |
| !cancelled() && | |
| (github.event_name == 'pull_request' || github.event_name == 'push' || | |
| github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| # write, because this job publishes the normalized report to the | |
| # port-status-data branch itself (see the publish step below). | |
| contents: write | |
| # write, to dispatch website-docs.yml -- the Port Status page is static, | |
| # so a published report is invisible until Hugo rebuilds. | |
| actions: write | |
| pull-requests: write | |
| issues: write | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.CN1SS_GH_TOKEN }} | |
| GH_TOKEN: ${{ secrets.CN1SS_GH_TOKEN }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| - name: Download cross-compiled screenshot artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: windows-cross-screenshot-raw | |
| path: artifacts/windows-port/raw-x64 | |
| - name: Post screenshots to PR | |
| shell: bash | |
| env: | |
| CN1SS_COMMENT_MARKER: '<!-- CN1SS_WINDOWS_CROSS_COMPILED_COMMENT -->' | |
| CN1SS_COMMENT_LOG_PREFIX: '[windows-cross-compiled]' | |
| CN1SS_PREVIEW_SUBDIR: 'windows-cross' | |
| CN1SS_SUCCESS_MESSAGE: 'Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.' | |
| run: | | |
| set -e | |
| ART="artifacts/windows-port" | |
| entries=() | |
| if [ -d "$ART/raw-x64" ]; then | |
| for f in "$ART"/raw-x64/*.png; do | |
| [ -f "$f" ] || continue | |
| name=$(basename "$f" .png) | |
| entries+=("$name=$f") | |
| done | |
| fi | |
| if [ ${#entries[@]} -eq 0 ]; then | |
| # A run that died before its first PNG still persists app-output.log, | |
| # and that log is what normalization reads to produce the fail / | |
| # not-run counts. Bailing out here left the failed capture with no | |
| # port-status artifact at all, so the nightly sweep fell back to an | |
| # older report and the table kept showing it. Carry on with an empty | |
| # entry list when there is a log; only a run with neither has nothing | |
| # to say. (Same handling as linux-build-run.yml.) | |
| if [ ! -f "$ART/raw-x64/app-output.log" ]; then | |
| echo "No screenshots and no app log; nothing to normalize." | |
| exit 0 | |
| fi | |
| echo "No screenshots were produced; normalizing from the app log so the failure reaches the table." | |
| fi | |
| echo "Posting ${#entries[@]} screenshot(s)" | |
| mkdir -p "$ART/previews" | |
| # Lift the SIMD benchmark tally (captured next to the PNGs) to the dir | |
| # cn1ss scans for --extra-stats, so it renders in the comment. | |
| cp -f "$ART"/raw-x64/windows-benchmark-stats.txt "$ART/" 2>/dev/null || true | |
| source scripts/lib/cn1ss.sh | |
| cn1ss_setup "$JAVA_HOME/bin/java" "$(pwd)/scripts/common/java" | |
| # Gate for real: differing or missing screenshots FAIL the job (the | |
| # comparison previously only posted diffs to the PR and exited green, | |
| # which let 100+ render changes land unreviewed). | |
| export CN1SS_FAIL_ON_MISMATCH=1 | |
| REF_DIR="$(pwd)/scripts/windows/screenshots" | |
| # Gate like the Linux port: fail on any mismatch/error or a new | |
| # screenshot with no committed golden. Previously this job only | |
| # posted the comparison as a PR comment, so stale goldens sailed | |
| # through green CI. | |
| export CN1SS_FAIL_ON_MISMATCH=1 | |
| export CN1SS_ALLOWED_MISSING=0 | |
| export CN1SS_PORT_ID=windows-x64 | |
| export CN1SS_SUITE_LOG="$ART/raw-x64/app-output.log" | |
| export CN1SS_BINARY_PATH="$ART/raw-x64/benchmark-app.exe" | |
| if [ "${{ github.event_name }}" != "pull_request" ]; then export CN1SS_SKIP_COMMENT=1; fi | |
| # Assertion-only failures count here as they do on every other producer. | |
| # A test like CryptoApiTest can fail while the suite still emits its | |
| # completion marker and every screenshot matches, and without this the | |
| # step exited zero: the workflow stayed green and published a report | |
| # containing failed tests. Linux, Android, JavaScript, iOS and Mac all | |
| # set this; Windows was the one producer that did not. | |
| export CN1SS_FAIL_ON_TEST_PROBLEMS=1 | |
| set +e | |
| cn1ss_process_and_report \ | |
| "Native Windows port (cross-compiled)" \ | |
| "$ART/compare.json" "$ART/summary.txt" "$ART/comment.md" \ | |
| "$REF_DIR" "$ART/previews" "$ART" \ | |
| ${entries[@]+"${entries[@]}"} | |
| gate_rc=$? | |
| set -e | |
| fail=0 | |
| if [ "$gate_rc" -ne 0 ]; then | |
| echo "[windows-cross] FATAL: screenshot gate failed (rc=$gate_rc)"; fail=1 | |
| fi | |
| if [ -f "$ART/summary.txt" ] && grep -q "^missing_expected|" "$ART/summary.txt"; then | |
| me="$(grep -c "^missing_expected|" "$ART/summary.txt" || echo 0)" | |
| echo "[windows-cross] FATAL: $me screenshot(s) streamed with no stored golden (missing_expected) -- add them to $REF_DIR."; fail=1 | |
| fi | |
| if [ "$fail" -ne 0 ]; then echo "Windows cross screenshot gate failed."; exit 1; fi | |
| - name: Upload Windows port status | |
| if: ${{ !cancelled() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: port-status-windows-x64 | |
| path: artifacts/windows-port/port-status-windows-x64.json | |
| if-no-files-found: warn | |
| retention-days: 14 | |
| # Publish from here rather than waiting for port-status-publish.yml. | |
| # That workflow reacts to a workflow_run "completed" event, and GitHub has | |
| # never delivered one for this workflow: ports/windows-x64.json had never | |
| # existed on the data branch, so the public table served the checked-in | |
| # fallback for the Windows x64 column. The report is already on disk in | |
| # this job, so publish it directly and depend on no event. | |
| # | |
| # if: ${{ !cancelled() }} for the same reason the job itself runs on failure -- a | |
| # report recording real failures is the one the table most needs. | |
| - name: Publish the Windows report to the data branch | |
| if: >- | |
| !cancelled() && github.ref == 'refs/heads/master' && | |
| (github.event_name == 'push' || github.event_name == 'schedule' || | |
| github.event_name == 'workflow_dispatch') | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PORT_STATUS_PUBLISH: '1' | |
| run: | | |
| set -euo pipefail | |
| report=artifacts/windows-port/port-status-windows-x64.json | |
| if [ ! -f "$report" ]; then | |
| echo "No normalized Windows report to publish." >&2 | |
| exit 1 | |
| fi | |
| ./scripts/hellocodenameone/conformance/publish_port_status.sh "$report" | |
| # Publishing to the data branch is only half the job. The Port Status | |
| # page is STATIC -- Hugo reads the reports at build time -- and | |
| # website-docs.yml is triggered by pushes to master, not by the data | |
| # branch, so a report published here would sit unseen until the next | |
| # daily rebuild. That is the same stale window this whole change | |
| # exists to close. port-status-publish.yml dispatches the rebuild for | |
| # the producers it handles; do the same for the ones that publish | |
| # themselves. In the same step as the publish, so it runs only when | |
| # the publish actually succeeded. | |
| gh workflow run website-docs.yml --ref master -f deploy_production=true |