🏗️ Build and Test JellyTau / Run Tests (pull_request) Successful in 15m1s
🏗️ Build and Test JellyTau / Supply Chain (pull_request) Successful in 42s
Traceability Validation / Check Requirement Traces (pull_request) Successful in 10s
🏗️ Build and Test JellyTau / Android Compile Check (pull_request) Successful in 4m6s
Two defects found while preparing v0.9.2, both of which had been shipping for months without anything to notice them by. **Every release note was the same 1,050 bytes.** All 35 releases from v0.0.1 to v0.9.1 published identical generic install instructions whose "What's New" section read "See CHANGELOG.md" -- a link that does not resolve from a release page. A reader learned nothing about what changed in any release the project has ever made. The body now comes from the `## <version>` section of CHANGELOG.md, and a missing section fails the release: notes that say nothing are worse than a build that waits for a maintainer to write two sentences. The 35 published bodies have been backfilled from the changelog via the tea CLI. This also corrects something introduced two commits ago. That change generated the body from `bun run release:notes`, which CLAUDE.md is explicit about -- its output is "a reviewed draft, not a final changelog". Publishing it unreviewed proved the point immediately: the v0.9.1..HEAD range contains a repo-wide prettier sweep, so every file in src/ counted as changed, their TRACES resolved to nearly the whole matrix, and the draft claimed the release had added the entire application. The script now skips cosmetic commits (chore(format), chore(deps), style) and reports how many rather than silently returning a smaller set, but it stays a local drafting tool. **Every release from v0.1.0 to v0.8.2 shipped every Windows installer ever built.** src-tauri/target/*/release/bundle/ is not versioned, cargo never cleans it, and the runner reuses the target directory -- so the copy step's bundle/**/*-setup.exe glob collected the lot. v0.8.2 carried sixteen installers, thirteen of them stale; v0.5.0 offered users a download list going back to 0.1.0. Eight months, and nothing to notice it by: the upload loop reported success, the files were real, and the page looked busy rather than wrong. It stopped only because an unrelated cargo cache change wiped the runner's target dir, so it was dormant, not fixed. Both desktop builds now remove the bundle directory before building, so a stale file cannot exist to be copied. Filtering the copy by version would have hidden it instead. The Linux job gets the same treatment: it was never hit only because Linux packaging is newer, and the glob is identical. scripts/check-release-artifacts.sh is the backstop for whatever reintroduces one by a route nobody predicted. It runs before the SBOM, the checksums and the upload -- all of which describe the file set, so a stale artifact has to be caught before it is hashed and published as part of the release. Verified against a reconstruction of the real v0.8.2 accumulation. DR-219, DR-220, UT-210.
100 lines
4.5 KiB
Bash
Executable File
100 lines
4.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Cross-compile JellyTau for Windows from Linux, producing an NSIS installer.
|
|
#
|
|
# Uses the OFFICIAL Tauri cross-compile path (https://v2.tauri.app/distribute/
|
|
# windows-installer/): the MSVC target driven by cargo-xwin, which downloads the
|
|
# MSVC CRT/Windows SDK headers and links with lld. This is the target Tauri
|
|
# officially supports for Windows (the mingw/GNU target is not), and unlike GNU
|
|
# it can bundle the NSIS installer from a Linux host.
|
|
#
|
|
# Playback on Windows: video renders via WebView2 and audio via the webview
|
|
# <audio> backend (WebviewAudioBackend) — see docs/build/build-windows.md.
|
|
#
|
|
# Requirements (present in the Docker windows-cross target / unified builder):
|
|
# - rustup target x86_64-pc-windows-msvc
|
|
# - cargo-xwin (cargo install --locked cargo-xwin)
|
|
# - lld, llvm (linker + llvm-lib used by cargo-xwin)
|
|
# - nsis (makensis) (installer generator)
|
|
#
|
|
# Usage:
|
|
# scripts/build-windows-cross.sh # exe + NSIS installer
|
|
# WIN_BUNDLES=none scripts/build-windows-cross.sh # exe only, skip bundling
|
|
# OUTPUT_DIR=/app/dist scripts/build-windows-cross.sh
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
TARGET="x86_64-pc-windows-msvc"
|
|
WIN_BUNDLES="${WIN_BUNDLES:-nsis}"
|
|
|
|
echo "🪟 Cross-compiling JellyTau for Windows ($TARGET, via cargo-xwin)"
|
|
echo "================================================================"
|
|
echo "Video plays via WebView2; audio via the webview <audio> backend."
|
|
echo "Bundles: $WIN_BUNDLES"
|
|
echo ""
|
|
|
|
bun install --frozen-lockfile 2>/dev/null || bun install
|
|
bun run build
|
|
|
|
# --runner cargo-xwin + the MSVC target is what makes the Tauri CLI treat this as
|
|
# a real Windows build and enable the nsis/msi bundlers on a Linux host.
|
|
#
|
|
# IMPORTANT: do NOT pass `--bundles nsis` here. tauri-cli 2.9.x validates the
|
|
# `--bundles` flag against a static clap enum gated by the HOST OS (Linux allows
|
|
# only deb/rpm/appimage) *before* it considers --target/--runner, so `--bundles
|
|
# nsis` is rejected at arg-parse time. Instead the Windows bundle targets come
|
|
# from tauri.conf.json (bundle.targets includes "nsis"), which is not subject to
|
|
# that CLI validation — the bundler then picks nsis once it knows the target is
|
|
# Windows.
|
|
# 🔴 Clear the bundle output before building.
|
|
#
|
|
# The bundle directory is not versioned and is never cleaned by cargo, and the
|
|
# CI runner reuses src-tauri/target between builds. The copy step below globs
|
|
# `bundle/**/*-setup.exe`, so every stale installer left there was picked up and
|
|
# attached to the release: v0.8.2 shipped sixteen Windows installers, thirteen
|
|
# of them from earlier versions, and v0.5.0 offered users a download list going
|
|
# back to 0.1.0. Every release from v0.1.0 to v0.8.2 did this. It stopped only
|
|
# because an unrelated change wiped the runner's target dir, so it is dormant
|
|
# rather than fixed.
|
|
#
|
|
# Filtering the copy by version would hide it; removing the directory means a
|
|
# stale file cannot exist to be copied. scripts/check-release-artifacts.sh is
|
|
# the backstop if some other path reintroduces one.
|
|
BUNDLE_DIR="src-tauri/target/$TARGET/release/bundle"
|
|
if [[ -d "$BUNDLE_DIR" ]]; then
|
|
echo "🧹 Clearing previous bundle output at $BUNDLE_DIR"
|
|
rm -rf "$BUNDLE_DIR"
|
|
fi
|
|
|
|
if [[ "$WIN_BUNDLES" == "none" ]]; then
|
|
bun run tauri build --runner cargo-xwin --target "$TARGET" --no-bundle
|
|
else
|
|
bun run tauri build --runner cargo-xwin --target "$TARGET"
|
|
fi
|
|
|
|
BIN_DIR="src-tauri/target/$TARGET/release"
|
|
echo ""
|
|
echo "✅ Built Windows artifacts:"
|
|
find "$BIN_DIR" -maxdepth 1 -name '*.exe' -print
|
|
find "$BIN_DIR/bundle" -type f \( -name '*.exe' -o -name '*.msi' \) -print 2>/dev/null || true
|
|
|
|
if [[ -n "${OUTPUT_DIR:-}" ]]; then
|
|
mkdir -p "$OUTPUT_DIR"
|
|
find "$BIN_DIR" -maxdepth 1 -name 'jellytau.exe' -exec cp -v {} "$OUTPUT_DIR/" \;
|
|
# NSIS setup installers land in bundle/nsis/*-setup.exe; MSI in bundle/msi/*.msi.
|
|
#
|
|
# The .sig files come along too: when TAURI_SIGNING_PRIVATE_KEY is set the
|
|
# bundler writes `<installer>.sig` beside each installer, and that signature is
|
|
# what the updater verifies before installing anything. Leaving it behind
|
|
# produces a release whose manifest references a signature that was never
|
|
# published, which fails only on the user's machine.
|
|
find "$BIN_DIR/bundle" -type f \( -name '*-setup.exe' -o -name '*.msi' -o -name '*.sig' \) \
|
|
-exec cp -v {} "$OUTPUT_DIR/" \; 2>/dev/null || true
|
|
echo ""
|
|
echo "📦 Copied Windows artifacts to $OUTPUT_DIR"
|
|
fi
|
|
|
|
# Containerised builds run as root against a bind-mounted tree; hand the
|
|
# artifacts back to the host user. No-op when not root. See DR-213.
|
|
"$(dirname "$0")/restore-ownership.sh"
|