CI on dev, the app started on X11 and Wayland; no silent re-release

ci.yml runs on dev too, adds the hygiene check, check-ui.sh (the modules parsed
as modules; nothing sets HTML) and the vendor pin, and a start job: a debug
build with the bundled page, started under Xvfb and under a headless Weston with
GTK's Wayland backend, which must still be running after 25 seconds.
release.yml refuses a tag that already has a release unless run by hand with
replace, marks betas as pre-releases, and gives a beta's .deb a ~beta version
so it sorts below its release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HomerandClaude Opus 5.5 committed 2026-10-28 04:55:03 +00:00
1 parent 4b4e63f622
commit 7f54d18375
5 files changed
+200 -14

No files matched your search

+40 -7
View File
@@ -1,9 +1,11 @@
# Checks on every push to main and every pull request: formatting, lints, tests, and the page's
# JavaScript. The app is built for real only by release.yml, from a tag.
# Checks on every push to main and dev and every pull request: formatting, lints, tests, the
# page's scripts, the pins (tokens, CodeMirror), the public-repository hygiene -- and the app
# started for real, on X11 and on Wayland, to prove it gets as far as its window. The packages
# are built only by release.yml, from a tag.
name: ci
on:
push:
branches: [main]
branches: [main, dev]
pull_request:
permissions:
@@ -23,6 +25,8 @@ jobs:
with:
components: rustfmt, clippy
cache-workspaces: src-tauri
- name: Nothing private in a public repository
run: scripts/hygiene.sh
- name: The bundled LLeMbas CLI, verified
run: scripts/fetch-cli.sh
- name: Formatting
@@ -34,8 +38,37 @@ jobs:
- name: Tests
working-directory: src-tauri
run: cargo test --locked
- name: The pages' JavaScript, and the script the content view runs
- name: The page's scripts parse, and none sets HTML
run: scripts/check-ui.sh
- name: The design tokens and CodeMirror are the server's, as pinned
run: |
for f in ui/*.js src-tauri/src/*.js; do node --check "$f"; done
- name: The design tokens are the server's, as pinned
run: scripts/fetch-tokens.sh
scripts/fetch-tokens.sh
scripts/fetch-vendor.sh
# The app started for real: it must still be running after 25 seconds (timeout's 124), and its
# log must not say it stopped. Once under Xvfb (X11) and once under a headless Weston (Wayland,
# GTK's Wayland backend forced), each with a session bus (the tray and the notifications want
# one) and an empty home, so it starts at its first-run page. Built with the custom protocol on,
# as a release is, so the page is the bundled ui/ and not a development server.
start:
runs-on: ubuntu-22.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v5
- name: System libraries, and an X server and a Wayland compositor without a screen
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libxdo-dev \
xvfb weston dbus libgl1-mesa-dri
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: src-tauri
- name: The bundled LLeMbas CLI, verified
run: scripts/fetch-cli.sh
- name: Build (debug, with the bundled page)
working-directory: src-tauri
run: cargo build --locked --features tauri/custom-protocol
- name: Starts on X11
run: scripts/ci-start.sh x11
- name: Starts on Wayland
run: scripts/ci-start.sh wayland
+41 -7
View File
@@ -1,6 +1,6 @@
# A release, from a signed tag vX.Y.Z on main: the Linux packages (.deb and AppImage) built with
# the LLeMbas CLI inside, SHA256SUMS over them, and the GitHub Release with the tag message as its
# notes. LLeMbas Desktop is developed on Gitea, which mirrors its commits and tags here; the builds
# A release, from a signed tag vX.Y.Z (stable, main) or vX.Y.Z-beta.N (a beta, marked as a
# pre-release): the Linux packages (.deb and AppImage) built with the LLeMbas CLI inside,
# SHA256SUMS over them, and the GitHub Release with the tag message as its notes. LLeMbas Desktop is developed on Gitea, which mirrors its commits and tags here; the builds
# happen here because they need a full Rust and WebKitGTK toolchain.
name: release
on:
@@ -11,6 +11,10 @@ on:
tag:
description: "The tag, e.g. v0.1.0"
required: true
replace:
description: "Replace a release that already exists for this tag (people who installed it get no update)"
type: boolean
default: false
permissions:
contents: write
@@ -48,6 +52,26 @@ jobs:
run: cargo install tauri-cli --version "^2" --locked
- name: Build
run: cargo tauri build --bundles deb,appimage
# Debian sorts 1.0.0-beta.1 *above* 1.0.0 (what follows the dash is a package revision), so a
# beta's package would make the release after it look like a downgrade, and apt would keep the
# beta. A beta's package version says ~beta, which sorts below.
- name: A beta's .deb sorts below its release
run: |
deb="$(ls src-tauri/target/release/bundle/deb/*.deb)"
have="$(dpkg-deb -f "$deb" Version)"
want="${VERSION/-/\~}"
if [ "$have" != "$want" ]; then
echo "repacking $deb: Version $have -> $want"
work="$(mktemp -d)"
dpkg-deb -R "$deb" "$work/pkg"
sed -i "s/^Version: .*/Version: $want/" "$work/pkg/DEBIAN/control"
dpkg-deb --root-owner-group -b "$work/pkg" "$deb"
fi
base="${VERSION%%-*}"
if [ "$VERSION" != "$base" ]; then
dpkg --compare-versions "$(dpkg-deb -f "$deb" Version)" lt "$base" \
|| { echo "the beta's package does not sort below $base" >&2; exit 1; }
fi
- name: Collect the files and SHA256SUMS
run: |
mkdir dist
@@ -62,8 +86,18 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
git tag -l --format='%(contents)' "$TAG" | sed '/-----BEGIN SSH SIGNATURE-----/,$d' > notes.md
# A tag moved to a fixed commit and pushed again replaces its release:
# the old one, and the files built from the old commit, go first.
gh release delete "$TAG" --repo "$GITHUB_REPOSITORY" --yes 2>/dev/null || true
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --verify-tag \
# A version is released once. Installing the same version again over a broken one is a
# no-op for apt ("already the newest version") and the updater offers nothing, so a fix
# is a new version -- never the old one re-released. Replacing is a deliberate act: a
# run by hand with `replace`.
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
if [ "${{ inputs.replace || false }}" != "true" ]; then
echo "A release for $TAG exists already. Release the fix as a new version." >&2
exit 1
fi
gh release delete "$TAG" --repo "$GITHUB_REPOSITORY" --yes
fi
pre=()
case "$VERSION" in *-*) pre=(--prerelease) ;; esac
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --verify-tag "${pre[@]}" \
--title "LLeMbas Desktop $VERSION" --notes-file notes.md dist/*