ci(release): publish desktop releases directly to OSS #3995
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
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| # A newer PR head supersedes its older checks. Keep main runs complete so every | |
| # merged commit still receives a full CI result. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| check: | |
| name: check (${{ matrix.moonbit-channel }}, ${{ matrix.target }}) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| # Run pre-release targets independently (fail-fast: false), while the | |
| # native/JS split lets the two test suites run in parallel. | |
| fail-fast: false | |
| matrix: | |
| moonbit-channel: [pre-release] | |
| target: [native, js] | |
| include: | |
| - moonbit-channel: pre-release | |
| moonbit-version: pre-release | |
| deny-warn: "--deny-warn" | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up MoonBit (${{ matrix.moonbit-channel }}) | |
| run: | | |
| curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s -- "${{ matrix.moonbit-version }}" | |
| echo "$HOME/.moon/bin" >> $GITHUB_PATH | |
| - name: Show MoonBit version | |
| run: | | |
| moon version --all | |
| - name: Update MoonBit package registry | |
| run: moon update | |
| # Proton comes from the registry, so the version it is pinned to lives in | |
| # desktop/moon.mod and nowhere else. Read it back here rather than | |
| # repeating it, and reuse it for both the CEF cache key and the CLI. | |
| - name: Resolve pinned Proton version | |
| id: proton | |
| run: | | |
| version="$(sed -n 's/.*"moonbit-community\/proton@\([^"]*\)".*/\1/p' desktop/moon.mod)" | |
| test -n "$version" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| # Pull requests may restore the default branch's cache, but their own | |
| # merge-ref caches are private to that PR and cannot warm other branches. | |
| - name: Restore CEF distribution | |
| if: matrix.target == 'native' | |
| id: cef-cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| # Proton shares downloaded CEF distributions between projects here, | |
| # then copies the selected version into the project-local runtime. | |
| path: ~/.proton/cache/cef | |
| key: cef-${{ runner.os }}-${{ runner.arch }}-proton-${{ steps.proton.outputs.version }} | |
| - name: Check formatting | |
| # Pre-release only, for the same reason as `--deny-warn` below. `moon fmt` is | |
| # a moving target on nightly: its output for markdown `mbt` blocks | |
| # changed between 2026-07-15 and 2026-07-25, which red-lined this step | |
| # for a file no one had touched. And because the step ran on both | |
| # channels, the repo could only ever satisfy it while the two | |
| # formatters agreed — once they disagree there is no committed form | |
| # that passes, which is not a state CI should be able to reach. | |
| if: matrix.moonbit-channel == 'pre-release' && matrix.target == 'native' | |
| run: moon fmt --check | |
| - name: Check ${{ matrix.target }} target | |
| # This is the local-dependency integration check: desktop must compile | |
| # against the editor member from this checkout. Keeping the target | |
| # explicit also makes each matrix row own one complete check/test pair; | |
| # pre-release denies warnings across the complete integrated workspace. | |
| run: moon check --target ${{ matrix.target }} ${{ matrix.deny-warn }} | |
| - name: Check generated interfaces | |
| # `moon info` formats abstract types differently across toolchain | |
| # versions (`type X` on pre-release vs `pub struct X { // private fields }` | |
| # on stable), and the committed `.mbti` are pre-release-generated — so | |
| # this consistency check is only meaningful on pre-release. This covers | |
| # the editor's public interfaces from the same checkout too. Ignore | |
| # blank-only formatter drift, but still reject content changes and new | |
| # `.mbti`. | |
| if: matrix.target == 'native' | |
| run: | | |
| moon info | |
| untracked_mbti="$(git ls-files --others --exclude-standard -- '*.mbti')" | |
| if [ -n "$untracked_mbti" ] || | |
| ! git diff --quiet --ignore-blank-lines -- '*.mbti'; then | |
| git status --short -- '*.mbti' | |
| git diff --ignore-blank-lines -- '*.mbti' | |
| exit 1 | |
| fi | |
| # Only now: `cef setup` reads the Proton package's platform prebuilt out | |
| # of .mooncakes, and nothing before the check steps above materializes | |
| # it — `moon update` only refreshes the registry index. The checks | |
| # themselves need no runtime because they never link. Setup runs at the | |
| # repository root, which is both where Moon resolves .mooncakes and | |
| # where Proton's link config looks for the .proton/runtime.json it | |
| # writes; `moonx` runs the published CLI straight from the registry | |
| # cache, so there is nothing to install. | |
| # | |
| # The test binaries below do link libproton.so, whose DT_NEEDED names | |
| # libcef.so, libgtk-3.so.0 and libX11.so.6 — the loader resolves all | |
| # three before main runs, so even a test that never opens a window | |
| # cannot start without them. GTK and X11 are already on the runner | |
| # image; libcef.so is the one the Proton package does not ship, and is | |
| # what this step assembles beside libproton.so. | |
| - name: Assemble Proton CEF runtime | |
| if: matrix.target == 'native' | |
| run: | | |
| moonx "moonbit-community/proton_cli@${{ steps.proton.outputs.version }}" \ | |
| -C "$PWD" cef setup | |
| test -f .proton/runtime.json | |
| # The pre-release/native main job is the sole Linux writer. PR jobs remain | |
| # restore-only, and no second channel races to reserve the same key. | |
| - name: Save CEF distribution | |
| if: >- | |
| github.event_name == 'push' && | |
| matrix.moonbit-channel == 'pre-release' && | |
| matrix.target == 'native' && | |
| steps.cef-cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: ~/.proton/cache/cef | |
| key: ${{ steps.cef-cache.outputs.cache-primary-key }} | |
| - name: Test native target | |
| # No Xvfb: nothing here initializes CEF or opens a window. That was | |
| # Proton's own windowed test suite, which left this workspace when | |
| # Proton became a registry dependency; loading libproton needs the | |
| # libraries above, not a display. | |
| if: matrix.target == 'native' | |
| run: moon test --target native | |
| - name: Test JS target | |
| # Run JS-only package tests from the same root workspace. These do not | |
| # create Proton windows and therefore do not need Xvfb. | |
| if: matrix.target == 'js' | |
| run: moon test --target js | |
| - name: Cram (offline CLI docs) | |
| if: matrix.target == 'native' | |
| run: moon cram test tests/cram |