mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 23:41:48 +01:00
Implements a comprehensive script improvement infrastructure to reduce code duplication, improve maintainability, and enable easier testing of installer scripts. ## New Infrastructure ### Shared Library System (scripts/lib/) - common.sh: Core utilities (logging, sudo, dry-run, cleanup management) - systemd.sh: Service management helpers with container-safe systemctl - http.sh: HTTP/download helpers with curl/wget fallback and retry logic - README.md: Complete API documentation for all library functions ### Bundler System - scripts/bundle.sh: Concatenates library modules into single-file installers - scripts/bundle.manifest: Defines bundling configuration for distributables - Enables both modular development and curl|bash distribution ### Test Infrastructure - scripts/tests/run.sh: Test harness for running all smoke tests - scripts/tests/test-common-lib.sh: Common library validation (5 tests) - scripts/tests/test-docker-agent-v2.sh: Installer smoke tests (4 tests) - scripts/tests/integration/: Container-based integration tests (5 scenarios) - All tests passing ✓ ## Refactored Installer ### install-docker-agent-v2.sh - Reduced from 1098 to 563 lines (48% code reduction) - Uses shared libraries for all common operations - NEW: --dry-run flag support - Maintains 100% backward compatibility with original - Fully tested with smoke and integration tests ### Key Improvements - Sudo escalation: 100+ lines → 1 function call - Download logic: 51 lines → 1 function call - Service creation: 33 lines → 2 function calls - Logging: Standardized across all operations - Error handling: Improved with common library ## Documentation ### Rollout Strategy (docs/installer-v2-rollout.md) - 3-phase rollout plan (Alpha → Beta → GA) - Feature flag mechanism for gradual deployment - Testing checklist and success metrics - Rollback procedures and communication plan ### Developer Guides - docs/script-library-guide.md: Complete library usage guide - docs/CONTRIBUTING-SCRIPTS.md: Contribution workflow - docs/installer-v2-quickref.md: Quick reference for operators ## Metrics - Code reduction: 48% (1098 → 563 lines) - Reusable functions: 0 → 30+ - Test coverage: 0 → 8 test scenarios - Documentation: 0 → 5 comprehensive guides ## Testing All tests passing: - Smoke tests: 2/2 passed (8 test cases) - Integration tests: 5/5 scenarios passed - Bundled output: Syntax validated, dry-run tested ## Next Steps This lays the foundation for migrating other installers (install.sh, install-sensor-proxy.sh) to use the same pattern, reducing overall maintenance burden and improving code quality across the project.
85 lines
5.0 KiB
Markdown
85 lines
5.0 KiB
Markdown
# Pulse Script Library
|
|
|
|
The `scripts/lib` directory houses shared Bash modules used by Pulse installation and maintenance scripts. The goal is to keep production installers modular and testable while still supporting bundled single-file artifacts for curl-based distribution.
|
|
|
|
## Modules & Namespaces
|
|
|
|
- Each module lives in `scripts/lib/<module>.sh`.
|
|
- Public functions use the `module::function` namespace (`common::log_info`, `proxmox::get_nodes`, etc.).
|
|
- Internal helpers can be marked `local` or use a `module::__helper` prefix.
|
|
- Scripts should only rely on documented `module::` APIs.
|
|
|
|
## Using the Library
|
|
|
|
### Development Mode
|
|
|
|
```bash
|
|
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/lib" && pwd)"
|
|
if [[ -f "${LIB_DIR}/common.sh" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "${LIB_DIR}/common.sh"
|
|
fi
|
|
|
|
common::init "$@"
|
|
common::log_info "Starting installer..."
|
|
|
|
# Acquire a temp directory (automatically cleaned on exit)
|
|
common::temp_dir TMP_DIR --prefix pulse-install-
|
|
common::log_info "Working in ${TMP_DIR}"
|
|
```
|
|
|
|
### Bundled Mode
|
|
|
|
Bundled scripts have the library concatenated into the file during the release process. The `source` guard remains but is a no-op because all functions are already defined.
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Description |
|
|
|----------------------|------------------------------------------------------------------------------|
|
|
| `PULSE_DEBUG` | When set to `1`, forces debug logging and enables additional diagnostics. |
|
|
| `PULSE_LOG_LEVEL` | Sets log level (`debug`, `info`, `warn`, `error`). Defaults to `info`. |
|
|
| `PULSE_NO_COLOR` | When `1`, disables ANSI colors (used for non-TTY or forced monochrome). |
|
|
| `PULSE_SUDO_CMD` | Overrides the sudo command (e.g., `/usr/bin/doas`). |
|
|
| `PULSE_FORCE_INTERACTIVE` | Forces interactive behavior (treats script as running in a TTY). |
|
|
|
|
## `common.sh` API Reference
|
|
|
|
- `common::init "$@"` — Initializes logging, traps, and script metadata. Call once at script start.
|
|
- `common::log_info "msg"` — Logs informational messages to stdout.
|
|
- `common::log_warn "msg"` — Logs warnings to stderr.
|
|
- `common::log_error "msg"` — Logs errors to stderr.
|
|
- `common::log_debug "msg"` — Logs debug output (requires log level `debug`).
|
|
- `common::fail "msg" [--code N]` — Logs error and exits with optional status code.
|
|
- `common::require_command cmd...` — Verifies required commands exist; exits on missing dependencies.
|
|
- `common::is_interactive` — Returns success when stdin/stdout are TTYs or forced interactive.
|
|
- `common::ensure_root [--allow-sudo] [--args "${COMMON__ORIGINAL_ARGS[@]}"]` — Ensures root privileges, optionally re-executing via sudo.
|
|
- `common::sudo_exec command...` — Executes command with sudo, printing guidance if sudo is unavailable.
|
|
- `common::run [--label desc] [--retries N] [--backoff "1 2"] -- cmd...` — Executes a command with optional retries and dry-run support.
|
|
- `common::run_capture [--label desc] -- cmd...` — Runs a command and prints captured stdout; honors dry-run.
|
|
- `common::temp_dir VAR [--prefix name]` — Creates a temporary directory, assigns it to `VAR`, and registers cleanup (avoid command substitution so handlers persist).
|
|
- `common::cleanup_push "description" "command"` — Registers cleanup/rollback handler (LIFO order).
|
|
- `common::cleanup_run` — Executes registered cleanup handlers; automatically called on exit.
|
|
- `common::set_dry_run true|false` — Enables or disables dry-run mode for command wrappers.
|
|
- `common::is_dry_run` — Returns success when dry-run mode is active.
|
|
|
|
## Bundling Workflow
|
|
|
|
1. Define modules under `scripts/lib/`.
|
|
2. Reference them from scripts using the development source guard.
|
|
3. Update `scripts/bundle.manifest` to list output artifacts and module order.
|
|
4. Run `scripts/bundle.sh` to generate bundled files under `dist/`.
|
|
5. Distribute bundled files (e.g., replace production installer).
|
|
|
|
Headers inserted during bundling (`# === Begin: ... ===`) mark module boundaries and aid debugging. The generated file includes provenance metadata with timestamp and manifest path.
|
|
- `systemd.sh` — safe wrappers around `systemctl`, unit creation helpers, and service lifecycle utilities.
|
|
- `http.sh` — download helpers, API call wrappers with retries, and GitHub release discovery.
|
|
|
|
- `systemd::safe_systemctl args...` — Run `systemctl` with timeout protection (container-friendly).
|
|
- `systemd::service_exists name` / `systemd::detect_service_name …` — Inspect available unit files.
|
|
- `systemd::create_service path [mode]` — Write a unit file from stdin (respects dry-run).
|
|
- `systemd::enable_and_start name` / `systemd::restart name` — Common service workflows.
|
|
- `http::download --url URL --output FILE [...]` — Robust curl/wget download helper with retries.
|
|
- `http::api_call --url URL [...]` — Token-authenticated API invocation; prints response body.
|
|
- `http::get_github_latest_release owner/repo` — Fetch latest GitHub release tag.
|
|
- `http::parse_bool value` — Normalize truthy/falsy strings.
|