Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pipeline Plan 16

Seth Ford edited this page Feb 11, 2026 · 4 revisions

Let me write the plan to a non-sensitive location and present it directly.

Here is the implementation plan:


Plan: Add Linux systemd Support for Process Supervision

Summary

Refactor sw-launchd.sh to detect the OS at runtime and generate either macOS launchd plist files or Linux systemd unit files accordingly. Add a new test suite to validate unit file generation on both platforms.

Files to Modify

File Action Purpose
scripts/sw-launchd.sh Modify Add OS detection, systemd unit generation, systemd status/uninstall
scripts/sw-launchd-test.sh Create Test suite for service file generation on both platforms
package.json Modify Register sw-launchd-test.sh in the test script
.github/workflows/test.yml Modify Add sw-launchd-test.sh step

Implementation Steps

Step 1: Add systemd constants alongside launchd constants

Add to the constants section (after the existing launchd paths):

# Linux systemd paths (user units)
SYSTEMD_DIR="$HOME/.config/systemd/user"
DAEMON_UNIT="$SYSTEMD_DIR/shipwright-daemon.service"
DASHBOARD_UNIT="$SYSTEMD_DIR/shipwright-dashboard.service"
CONNECT_UNIT="$SYSTEMD_DIR/shipwright-connect.service"

Step 2: Extract macOS logic into platform-specific functions

Rename existing cmd_install -> cmd_install_launchd, cmd_uninstall -> cmd_uninstall_launchd, cmd_status -> cmd_status_launchd. Remove the check_macos() calls inside them (the dispatcher handles it).

Step 3: Implement cmd_install_systemd

Generate three systemd user service units. Key properties:

  • Type=simple, Restart=on-failure, RestartSec=10
  • KillSignal=SIGTERM, TimeoutStopSec=30 (daemon) / 15 (dashboard, connect)
  • StandardOutput=journal + SyslogIdentifier=shipwright-* (log rotation via journald)
  • WantedBy=default.target
  • Connect service: After=shipwright-daemon.service, only generated if $TEAM_CONFIG exists

After writing files: systemctl --user daemon-reload, then systemctl --user enable --now each service.

Step 4: Implement cmd_uninstall_systemd

systemctl --user disable --now each service, remove unit files, systemctl --user daemon-reload.

Step 5: Implement cmd_status_systemd

systemctl --user is-active each service with colored indicators. Show recent journal lines via journalctl --user -u shipwright-daemon -n 3 --no-pager.

Step 6: Add OS-dispatch wrappers

cmd_install() {
 if is_macos; then cmd_install_launchd
 elif is_linux; then cmd_install_systemd
 else error "Unsupported platform"; exit 1; fi
}

Same pattern for cmd_uninstall and cmd_status.

Step 7: Update help text

Change header from "Process supervision on macOS" to "Process supervision (macOS launchd / Linux systemd)". Update the install/status/uninstall descriptions to reflect cross-platform support.

Step 8: Create scripts/sw-launchd-test.sh (13 tests)

Mock strategy: Override _COMPAT_UNAME env var to control is_macos/is_linux from compat.sh. Create mock systemctl/launchctl in $TEMP_DIR/bin prepended to PATH.

Tests:

  1. OS detection routes to systemd on Linux
  2. Systemd unit content (ExecStart, WorkingDirectory, KillSignal=SIGTERM, Restart=on-failure)
  3. Systemd unit permissions (644)
  4. Connect service only generated when $TEAM_CONFIG exists
  5. macOS plist generation with mocked launchctl
  6. Plist content (KeepAlive, RunAtLoad, ProgramArguments)
  7. Uninstall systemd removes unit files
  8. Uninstall launchd removes plist files
  9. Status systemd — mock systemctl, verify colored output
  10. Status launchd — mock launchctl, verify colored output
  11. Unsupported OS exits with error
  12. SIGTERM + TimeoutStopSec present in systemd units
  13. StandardOutput=journal in all systemd units

Step 9: Register test in CI

Add && bash scripts/sw-launchd-test.sh to package.json test script. Add step in .github/workflows/test.yml.

Task Checklist

  • Task 1: Add systemd path constants to sw-launchd.sh
  • Task 2: Extract macOS install logic into cmd_install_launchd
  • Task 3: Implement cmd_install_systemd with 3 unit files
  • Task 4: Extract macOS uninstall logic into cmd_uninstall_launchd
  • Task 5: Implement cmd_uninstall_systemd
  • Task 6: Extract macOS status logic into cmd_status_launchd
  • Task 7: Implement cmd_status_systemd
  • Task 8: Add OS-dispatch wrappers for install/uninstall/status
  • Task 9: Update help text and script header
  • Task 10: Create sw-launchd-test.sh with 13 test cases
  • Task 11: Register test in package.json and test.yml
  • Task 12: Run tests locally, fix failures
  • Task 13: Sync docs

Testing Approach

  1. Unit tests (sw-launchd-test.sh): Mock _COMPAT_UNAME, systemctl, launchctl in temp dir. Verify file content, permissions, conditionals, error paths.
  2. CI matrix: Already runs on [macos-latest, ubuntu-latest] — the new suite exercises the native codepath on each runner.
  3. Manual: On Linux, shipwright launchd install and verify with systemctl --user list-units.

Definition of Done

  • shipwright launchd install detects OS and generates appropriate service files
  • systemd unit files for daemon, dashboard, connect
  • shipwright launchd status works on both macOS and Linux
  • Graceful shutdown via KillSignal=SIGTERM + TimeoutStopSec
  • Log rotation via journald (StandardOutput=journal)
  • macOS behavior unchanged
  • 13-test suite passes on macOS and Ubuntu CI
  • No Bash 3.2 compatibility violations

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /