mirror of
https://github.com/priyanshujain/margin-calendar.git
synced 2026-10-02 11:07:04 +00:00
Build and sign releases in CI, and install locally with one command
Ported from margin's pipeline, with the platform list this app actually claims. Release is manual: it bumps tauri.conf.json, package.json and Cargo.toml together, tags, and then builds the tag rather than whatever main has drifted to by the time the runners pick it up. Nothing publishes until every platform lands. The last job downloads latest.json and refuses to take the release out of draft unless darwin-aarch64, darwin-x86_64 and linux-x86_64 are all present, because a half-populated manifest is worse than no release at all: the updater would offer an update to the platforms that made it and error on the ones that did not. Linux builds on Ubuntu 22.04 rather than latest. The bundle will not run on anything older than the glibc it was linked against, and 22.04 is the baseline docs/setup.md commits to. Windows is not built, matching the bundle targets and the README; adding it is a matrix entry, msi and nsis in the targets, and windows-x86_64 in the publish gate. The updater had a plugin, a capability and a menu item but no keypair and no endpoint, so releases would have produced artifacts nothing could verify. The public half is now in tauri.release.conf.json and the private half is a repository secret, alongside the Google OAuth client that build.rs embeds. Without that secret the build falls back to the example credentials and warns rather than failing, which yields an app that runs and then says Google Calendar is not set up. CI enforces the gate setup.md already names, the two test suites, and nothing more. cargo fmt --check and cargo clippy -D warnings both fail on the tree as it stands, and adopting either is a cleanup pass to decide on rather than something to bolt onto a new pipeline. justfile is the local equivalent of all this. `just install` builds for the machine it is run on and installs it, and is the same command whether or not the app is already there, so it doubles as the update. On macOS it asks a running copy to quit first, because replacing a bundle under a live process leaves it half old and half new.
This commit is contained in:
1 parent
d4c3a304b5
commit
590506eb92
6 files changed
+458
-5
No files matched your search
@@ -0,0 +1,132 @@
|
||||
# Building and installing Margin Calendar on the machine you are sitting at. The release pipeline
|
||||
# in .github/workflows/release.yml is what builds for everyone else; this is the local equivalent,
|
||||
# and `just install` is deliberately the same command whether or not the app is already installed.
|
||||
|
||||
set shell := ["bash", "-euo", "pipefail", "-c"]
|
||||
|
||||
app := "Margin Calendar"
|
||||
bundle := "src-tauri/target/release/bundle"
|
||||
|
||||
# List the recipes.
|
||||
default:
|
||||
@just --list
|
||||
|
||||
# Run the app against the Vite dev server.
|
||||
dev:
|
||||
pnpm tauri dev
|
||||
|
||||
# The gate: the frontend suites and the Rust suites, both of which must be green.
|
||||
test:
|
||||
pnpm test
|
||||
cd src-tauri && cargo test
|
||||
|
||||
# The browser suite that drives the real UI.
|
||||
test-ui:
|
||||
pnpm test:ui
|
||||
|
||||
# Build the release bundle for this machine.
|
||||
build:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# The .app on macOS, the .deb and AppImage on Linux. No dmg: nothing here needs a disk image
|
||||
# to copy a bundle into place, and building one is the slowest part of a mac bundle.
|
||||
pnpm install
|
||||
case "$(uname -s)" in
|
||||
Darwin) pnpm tauri build --bundles app ;;
|
||||
Linux) pnpm tauri build --bundles deb,appimage ;;
|
||||
*) echo "just: no local build for $(uname -s); macOS and Linux are the desktop targets." >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Build and install, replacing whatever version is already installed.
|
||||
install: build
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
case "$(uname -s)" in
|
||||
Darwin) just _install-macos ;;
|
||||
Linux) just _install-linux ;;
|
||||
*) echo "just: no installer for $(uname -s); macOS and Linux are the desktop targets." >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
_install-macos:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
src="{{bundle}}/macos/{{app}}.app"
|
||||
[ -d "$src" ] || { echo "just: nothing to install, $src does not exist." >&2; exit 1; }
|
||||
|
||||
# /Applications is writable by admin users, so the common case needs no sudo. When it is not,
|
||||
# ~/Applications is a real Launchpad location and beats prompting for a password mid-build.
|
||||
if [ -w /Applications ]; then dir=/Applications; else dir="$HOME/Applications"; mkdir -p "$dir"; fi
|
||||
dest="$dir/{{app}}.app"
|
||||
|
||||
# Which of the two names the executable carries depends on how the bundle was configured, so
|
||||
# ask about both rather than assuming, and replacing a bundle out from under a live process.
|
||||
running() { pgrep -x "{{app}}" > /dev/null || pgrep -x margin-calendar > /dev/null; }
|
||||
|
||||
# Replacing the bundle under a running app leaves it half old and half new, and the running
|
||||
# copy holds the deleted files open. Ask it to quit and wait, rather than killing it.
|
||||
if running; then
|
||||
echo "Quitting the running {{app}}…"
|
||||
osascript -e 'quit app "{{app}}"' 2> /dev/null || true
|
||||
for _ in $(seq 40); do running || break; sleep 0.25; done
|
||||
if running; then echo "just: {{app}} is still running; quit it and try again." >&2; exit 1; fi
|
||||
fi
|
||||
|
||||
rm -rf "$dest"
|
||||
cp -R "$src" "$dest"
|
||||
version=$(defaults read "$dest/Contents/Info.plist" CFBundleShortVersionString 2> /dev/null || echo "?")
|
||||
echo "Installed $version to $dest"
|
||||
|
||||
_install-linux:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
deb=$(ls -t {{bundle}}/deb/*.deb 2> /dev/null | head -1 || true)
|
||||
appimage=$(ls -t {{bundle}}/appimage/*.AppImage 2> /dev/null | head -1 || true)
|
||||
|
||||
# apt over dpkg where it exists: it pulls in the webkit and gtk runtime the package depends on,
|
||||
# and --reinstall makes installing over the same version an update rather than a no-op.
|
||||
if [ -n "$deb" ] && command -v apt-get > /dev/null; then
|
||||
sudo apt-get install -y --reinstall "$PWD/$deb"
|
||||
echo "Installed $deb"
|
||||
elif [ -n "$deb" ] && command -v dpkg > /dev/null; then
|
||||
sudo dpkg -i "$deb"
|
||||
echo "Installed $deb"
|
||||
elif [ -n "$appimage" ]; then
|
||||
install -Dm755 "$appimage" "$HOME/.local/bin/margin-calendar"
|
||||
install -Dm644 src-tauri/icons/128x128.png "$HOME/.local/share/icons/margin-calendar.png"
|
||||
mkdir -p "$HOME/.local/share/applications"
|
||||
printf '%s\n' \
|
||||
'[Desktop Entry]' \
|
||||
'Type=Application' \
|
||||
'Name=Margin Calendar' \
|
||||
'Comment=A calendar for Google Calendar' \
|
||||
'Exec=margin-calendar' \
|
||||
'Icon=margin-calendar' \
|
||||
'Categories=Office;Calendar;' \
|
||||
> "$HOME/.local/share/applications/margin-calendar.desktop"
|
||||
echo "Installed $appimage to ~/.local/bin/margin-calendar"
|
||||
echo "Make sure ~/.local/bin is on your PATH."
|
||||
else
|
||||
echo "just: nothing to install, no .deb or AppImage under {{bundle}}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove the installed app, leaving its data directory alone.
|
||||
uninstall:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# What the data directory is and what deleting it costs you is in docs/setup.md.
|
||||
case "$(uname -s)" in
|
||||
Darwin)
|
||||
for dest in "/Applications/{{app}}.app" "$HOME/Applications/{{app}}.app"; do
|
||||
if [ -d "$dest" ]; then rm -rf "$dest"; echo "Removed $dest"; fi
|
||||
done
|
||||
;;
|
||||
Linux)
|
||||
if dpkg -s margin-calendar > /dev/null 2>&1; then sudo apt-get remove -y margin-calendar; fi
|
||||
rm -f "$HOME/.local/bin/margin-calendar" \
|
||||
"$HOME/.local/share/icons/margin-calendar.png" \
|
||||
"$HOME/.local/share/applications/margin-calendar.desktop"
|
||||
echo "Removed the AppImage install, if there was one."
|
||||
;;
|
||||
*) echo "just: nothing to uninstall on $(uname -s)." >&2; exit 1 ;;
|
||||
esac
|
||||
Reference in new issue
Block a user