feat: one-command install as a per-user service, release workflow (0.3.0) #3
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/install-as-service"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
This makes
rkd-terminala one-command install (RKD #1084, #968's open question 3), and releases 0.3.0.rkd-terminal install/uninstallregister the plugin as a per-user background service: a launchd agentbiz.nanoya.rkd-terminalon macOS, a systemd user unit on Linux.PATH, so presets such asclaudein~/.local/binare found.--force.--no-startwrites the file without starting anything.statusreports the service.install.sh(POSIX sh):~/.local/bin, never with sudo, and refuses to run as root.main(), so a truncated download does nothing.scripts/test-install.shruns 32 checks against a fake release; CI runs it under dash with shellcheck.v*tags:.tar.gz+.sha256to a draft release, and publishes it only after every build is attached.cargo installor unsupported.Tests
cargo fmt --check, clippy-D warnings,cargo test --workspace(69 rkd-terminal lib tests).shand dash, plus shellcheck.launchctl bootstrap/systemctl --usercalls (no background agent was registered on the dev Mac), and the release workflow itself: the zigbuild builds, the Mac runner, and whether the Actions token can write releases. If the first tag fails with 401/403, aRELEASE_TOKENrepo secret is needed.https://claude.ai/code/session_01P4hUduqyzHTYckP7dX5fXV
`rkd-terminal install [--no-start] [--force]` writes a launchd agent (~/Library/LaunchAgents/biz.nanoya.rkd-terminal.plist) or a systemd user unit ($XDG_CONFIG_HOME/systemd/user/rkd-terminal.service) that runs this binary's canonical path with `serve`, and loads it. Reinstalling boots the old agent out first (retrying the bootstrap while launchd tears it down) or restarts the unit, so an upgraded binary takes over at once. `uninstall` stops it and removes the file; `status` says whether the file exists. A binary in a temp dir or a cargo build dir (target/{debug,release} or any folder with cargo's .fingerprint) is refused unless --force. The installing shell's absolute PATH entries go into the service so presets resolve as they do by hand. Commands run as argv through an injectable runner; the tests assert the exact launchctl/systemctl sequences. Refs rkd#1084. Claude-Session: https://claude.ai/code/session_01P4hUduqyzHTYckP7dX5fXVReview fixes for the release workflow: - Only commits of main are released: create-release fetches main (full history) and scripts/release-guard.sh requires the tagged commit to be an ancestor of origin/main, before anything is built. - No ${{ }} of untrusted input inside run: scripts. The tag, target and release id reach scripts via env and quoted "$VARS"; the tag is checked (v<digit>, then only [A-Za-z0-9._-]) before it is used for anything. - The Forgejo token never appears in curl's argv, where other users of the shared host-mode Mac runner could read it with ps: api_curl in scripts/release-lib.sh feeds the header as curl config on stdin. - A release of the tag that is already published fails the run (release-find-or-create.sh), and release-upload.sh refuses a non-draft release before deleting or uploading anything. Re-runs and re-pushed tags only ever fill a draft. - actions/checkout pinned to the v4.2.2 commit. Linux jobs install rustup from a pinned rustup-init checked against its SHA-256 (scripts/install-rustup.sh) instead of curl | sh; the Mac job uses the runner's own rustup and fails with a clear message without it. ci.yml gets the same pin and rustup install. scripts/test-release.sh (run in CI next to test-install.sh) covers the scripts against a fake curl and a throwaway git repo: tag validation, off-main commits, version mismatch, published vs draft releases, token only on stdin, rustup-init checksum refusal, plus a lint of both workflows (no ${{ }} in run:, actions pinned to a SHA, no sh.rustup.rs, no Authorization header on a command line). Each guard was hand-broken and the matching checks went red. Not testable here: the runner's own git fetch of main and the Mac host probe; both are plain workflow steps. Claude-Session: https://claude.ai/code/session_01P4hUduqyzHTYckP7dX5fXV