Commit graph

597 commits

Author SHA1 Message Date
rcourtman
8d320ef56b Fix notification manager deadlock in Stop()
Critical deadlock fix:
- Stop() was holding n.mu lock while calling queue.Stop()
- queue.Stop() waits for worker goroutines to finish
- Worker goroutines call ProcessQueuedNotification() which needs n.mu lock
- This created a classic lock-order deadlock

Fix:
- Unlock n.mu before calling queue.Stop()
- Relock after queue shutdown completes
- Workers can now finish and acquire lock as needed

This resolves 30-second test timeouts in notifications package.

Tests now complete in <1s instead of timing out at 30s.
2025-11-11 23:58:18 +00:00
rcourtman
1e4061b3a2 Fix NVMe temperature merge test expectations
Update test expectations to match new SMART-preferred behavior:
- mergeNVMeTempsIntoDisks now prioritizes SMART temps over NVMe temps
- NVMe temps only applied to disks with Temperature == 0
- Tests were failing because disks started with non-zero temperatures
- Changed test disks to start with Temperature: 0 to simulate fresh disks

This change was introduced in commit 2a79d57f7 (Add SMART temperature
collection for physical disks) but tests weren't updated.

Fixes TestMergeNVMeTempsIntoDisks and TestMergeNVMeTempsIntoDisksClearsMissingOrInvalid.
2025-11-11 23:54:45 +00:00
rcourtman
754e9d1abd Fix monitoring test panic and goroutine leaks
Two critical fixes to prevent test timeouts:

1. Nil map panic in TestPollPVEInstanceUsesRRDMemUsedFallback:
   - Test monitor was missing nodeLastOnline map initialization
   - Panic occurred when pollPVEInstance tried to update nodeLastOnline[nodeID]
   - Caused deadlock when panic recovery tried to acquire already-held mutex
   - Added nodeLastOnline: make(map[string]time.Time) to test monitor

2. Alert manager goroutine leak in Docker tests:
   - newTestMonitor() created alert manager but never stopped it
   - Background goroutines (escalationChecker, periodicSaveAlerts) kept running
   - Added t.Cleanup(func() { m.alertManager.Stop() }) to test helper

These fixes resolve the 10+ minute test timeouts in CI workflows.

Related to workflow run 19281508603.
2025-11-11 23:52:24 +00:00
rcourtman
305aab88df Fix discovery test Prometheus metric collision
Remove t.Parallel() from tests that verify global Prometheus gauge values.
When tests run in parallel, they update the same global gauges
(discoveryScanServers, discoveryScanErrors) causing race conditions and
incorrect metric values.

Fixes test failure in workflow run 19281332332:
- TestPerformScanRecordsHistoryAndMetrics expected 2 servers, got 1

Related to release workflow preflight tests.
2025-11-11 23:34:49 +00:00
rcourtman
d7766af799 Fix backend test failures blocking release workflow
Three categories of fixes:

1. Goroutine leak causing 10-minute timeout:
   - Add defer mon.notificationMgr.Stop() in monitor_memory_test.go
   - Background goroutines from notification manager weren't being stopped

2. Database NULL column scanning errors:
   - Change LastError from string to *string in queue.go
   - Change PayloadBytes from int to *int in queue.go
   - SQL NULL values require pointer types in Go

3. SSRF protection blocking test servers:
   - Check allowlist for localhost before rejecting in notifications.go
   - Set PULSE_DATA_DIR to temp directory in tests
   - Add defer nm.Stop() calls to prevent goroutine leaks

Fixes for preflight test failures in workflow run 19280879903.
2025-11-11 23:27:03 +00:00
rcourtman
95c8fe9c2d Add Snap Docker support to install-docker-agent.sh
Snap-installed Docker does not automatically create a docker group,
causing permission denied errors when the pulse-docker service user
tries to access /var/run/docker.sock.

Changes:
- Auto-detect Snap Docker installations
- Create docker group if missing when Snap Docker is detected
- Restart Snap Docker after group creation to refresh socket ACLs
- Add socket access validation before starting the service
- Handle symlinked Docker sockets in systemd unit ReadWritePaths
- Document troubleshooting steps in DOCKER_MONITORING.md
2025-11-11 23:07:29 +00:00
rcourtman
27c2774af4 Fix pulse-sensor-proxy pvecm errors in LXC containers (related to #600)
When pulse-sensor-proxy runs inside an LXC container on a Proxmox host,
pvecm status fails with "ipcc_send_rec[1] failed: Unknown error -1"
because the container can't access the host's corosync IPC socket.

This caused repeated warnings every few seconds even though the proxy
can function correctly by discovering local host addresses.

Extended the standalone node detection to recognize "ipcc_send_rec"
errors as indicating an LXC container deployment and gracefully fall
back to local address discovery instead of logging warnings.
2025-11-11 23:04:36 +00:00
rcourtman
f3d20a1fea Fix failing backend tests in preflight checks
Fixes three test failures that were blocking release workflow:

1. TestApplyDockerReportGeneratesUniqueIDsForCollidingHosts:
   - Initialize dockerTokenBindings and dockerMetadataStore in test helper
   - These maps were nil causing panic on first access

2. TestSendGroupedAppriseHTTP & TestSendTestNotificationAppriseHTTP:
   - Configure allowlist to permit localhost (127.0.0.1) for test servers
   - SSRF protection was blocking httptest.NewServer() URLs
   - Tests need to allowlist the test server IP to bypass security checks

Related to workflow fix in 5fa78c3e3.
2025-11-11 23:02:45 +00:00
rcourtman
c43e893034 Fix YAML syntax error in validate-release-assets workflow
The Python heredoc was not indented, causing YAML parsers to interpret
the Python code as YAML syntax. This caused workflow_dispatch runs to
fail instantly with 'workflow file issue' error before any jobs could start.

The fix indents the heredoc content and changes delimiter from 'PY' to
'EOF' to match standard conventions.
2025-11-11 22:54:37 +00:00
rcourtman
28892f4333 Revert "temp: set VERSION to 4.29.0-test for canary release"
This reverts commit 5d391a98b0.
2025-11-11 22:41:32 +00:00
rcourtman
adb35721dc temp: set VERSION to 4.29.0-test for canary release 2025-11-11 22:39:03 +00:00
rcourtman
8a5be2c0da Release workflow guardrails (related to #695) 2025-11-11 22:34:00 +00:00
rcourtman
cc595da28b Fix guest agent OS info calls causing OpenBSD VM crashes (related to #692)
Add defensive mitigation to prevent repeated guest-get-osinfo calls that
trigger buggy behavior in QEMU guest agent 9.0.2 on OpenBSD 7.6.

The issue: OpenBSD doesn't have /etc/os-release (Linux convention), and
qemu-ga 9.0.2 appears to spawn excessive helper processes trying to read
this file whenever guest-get-osinfo is called. These helpers don't clean
up properly, eventually exhausting the process table and crashing the VM.

The fix: Track consecutive OS info failures per VM. After 3 failures,
automatically skip future guest-get-osinfo calls for that VM while
continuing to fetch other guest agent data (network interfaces, version).
This prevents triggering the buggy code path while maintaining most guest
agent functionality.

The counter resets on success, so if the guest agent is upgraded or the
issue is resolved, Pulse will automatically resume OS info collection.

Related to #692
2025-11-11 22:27:22 +00:00
rcourtman
535ae1c70f Fix Windows/macOS host agent downloads for bare metal installs (related to #684)
Bare metal installations couldn't serve Windows host agent downloads because
the Windows and macOS binaries weren't included in the universal tarball. The
download endpoint would return 404 when Windows users tried to install the
host agent from a bare metal Pulse deployment (Proxmox LXC, Debian VM, etc.).

Changes:
- build-release.sh: Copy Windows/macOS host agent binaries into universal tarball
- build-release.sh: Create symlinks for Windows binaries without .exe extension
- validate-release.sh: Add Windows 386 binary and symlink to Docker validation
- validate-release.sh: Add explicit validation that universal tarball contains all Windows/macOS binaries

The universal tarball now matches the Docker image, ensuring both deployment
methods can serve the complete set of downloadable binaries for the /download/
endpoint.
2025-11-11 21:26:33 +00:00
rcourtman
399534dc7f Fix SELinux compatibility in host agent installer
Replace mv with install command to ensure correct SELinux context.
The mv command preserves the user_tmp_t label from /tmp, which
prevents systemd from executing the binary on SELinux systems.

The install command creates a new file with the correct label for
/usr/local/bin. Added automatic restorecon call for SELinux systems
to ensure policy compliance.

Related to #688
2025-11-11 21:13:33 +00:00
rcourtman
777b27b6f6 Fix checksum extraction to use word boundaries
The grep pattern was too loose and could match filenames like:
- pulse-v4.29.0-linux-amd64.tar.gz (correct)
- pulse-v4.29.0-linux-amd64.tar.gz.sha256 (also matched)

Using grep -w ensures we only match the exact filename as a complete word,
preventing false matches on files with the same prefix.
2025-11-11 20:41:42 +00:00
rcourtman
58717c759a Generate both checksums.txt and .sha256 files for backward compatibility
Following best practices for release format transitions:
- build-release.sh now generates both formats from same sha256sum run
- Workflow uploads both checksums.txt and individual .sha256 files
- Validation ensures both formats exist and match

This provides a safe transition period for users with older install scripts
while maintaining the cleaner checksums.txt format going forward. After 2-3
releases when most users have updated scripts, we can remove .sha256 generation.

Related: Install script already supports both formats (falls back gracefully).
2025-11-11 20:31:15 +00:00
rcourtman
cf5535878d Make install script backward compatible with old and new release formats
The install script now tries checksums.txt first (v4.29.0+), then falls back
to individual .sha256 files (v4.28.0 and earlier). This ensures users can
update from any version regardless of which checksum format was used.

This fixes the release format transition issue where changing asset structure
broke updates for users on older versions.
2025-11-11 20:19:47 +00:00
rcourtman
b8279b0003 Update install script to use checksums.txt instead of individual .sha256 files
Aligns with release asset reduction changes. The install script now downloads the unified checksums.txt file and extracts the checksum for the specific architecture being installed.
2025-11-11 20:14:13 +00:00
rcourtman
51aaa103cf Add manual trigger support to demo server update workflow
Allows manually deploying specific releases to the demo server via workflow_dispatch.
2025-11-11 20:12:24 +00:00
rcourtman
e7e7c95236 Fix demo workflow asset checks to follow redirects
The workflow was failing because GitHub returns 302 redirects for freshly published release assets while the CDN propagates. Adding -L flag to curl commands allows them to follow redirects and properly detect when assets are available.
2025-11-11 20:09:41 +00:00
rcourtman
dc8eaa3ffe Add production-grade Helm chart improvements
High-impact improvements based on Codex recommendations:

1. values.schema.json - JSON schema validation catches config errors at install time
2. helm-docs automation - Auto-generates documentation from values.yaml comments
3. kind smoke tests - Deploys and upgrades chart in real cluster to catch runtime issues
4. ServiceMonitor template - Built-in Prometheus integration for observability
5. Artifact Hub metadata - Changelog, links, and maintainer info for better discoverability

These improvements provide:
- Configuration validation before deployment
- Always up-to-date documentation
- Runtime validation in CI
- First-class monitoring support
- Better user experience on Artifact Hub

Related to #686
2025-11-11 19:52:58 +00:00
rcourtman
3477aa3dae Update Kubernetes docs with GitHub Pages Helm repository
- Replace GHCR OCI instructions with GitHub Pages repository
- Add comprehensive upgrade instructions with examples
- Add rollback procedures
- Add detailed uninstall instructions
- Simplify installation (no authentication required)
2025-11-11 19:40:51 +00:00
rcourtman
b042365652 Add automated version syncing and validation to Helm workflow
- Auto-update Chart.yaml version from release tag or manual input
- Add strict helm lint validation before publishing
- Validate chart templates with multiple configuration scenarios
- Ensures chart quality before publishing to GitHub Pages
2025-11-11 19:40:04 +00:00
rcourtman
3fffd165ea Add Artifact Hub repository metadata for chart discoverability
Enables automatic listing on https://artifacthub.io for improved
Helm chart discovery and provides metadata like screenshots, links,
and maintainer information.
2025-11-11 19:39:19 +00:00
rcourtman
9bc5b754c7 Update README with GitHub Pages Helm repository instructions
Replace GHCR OCI registry instructions with GitHub Pages Helm repo.
Simpler installation without authentication requirements.

Resolves #686
2025-11-11 19:32:28 +00:00
rcourtman
37dc0682ee Update Helm chart version to 4.28.0 for GitHub Pages release 2025-11-11 19:30:52 +00:00
rcourtman
8754974e21 Fix Helm chart releaser to skip existing releases
Use helm-chart- prefix for releases to avoid conflicts with main Pulse releases
2025-11-11 19:28:48 +00:00
rcourtman
b89c4317d0 Add GitHub Pages Helm repository distribution (#686)
GHCR OCI packages cannot be made public through any available mechanism:
- Package doesn't appear in user/repo package lists
- API endpoints return 404
- Workflow tokens lack package visibility permissions
- Manual UI shows no packages to configure
- OCI annotations don't link package to repository

Implementing GitHub Pages Helm repo as canonical distribution method:
- Uses chart-releaser-action to publish to gh-pages branch
- Provides standard 'helm repo add' workflow without authentication
- Maintains OCI push for future use if GHCR resolves visibility issues

Resolves #686
2025-11-11 19:26:18 +00:00
rcourtman
c7895839fb Fix validation: Linux host-agent binaries are in main tarballs
Linux host-agent binaries don't have separate archives - they're included in
the main pulse-v*.tar.gz files. Only macOS and Windows have separate archives.
2025-11-11 19:25:14 +00:00
rcourtman
0a887e9b64 Add OCI annotations to Helm chart to link package to repository
Adding org.opencontainers.image.source annotation will connect the GHCR package
to the repository, making it visible in the repo's packages section and allowing
proper visibility management.

Related to #686
2025-11-11 19:24:52 +00:00
rcourtman
3ea15b1e79 Update validation script to match new asset list
Removed validation checks for standalone binaries that are no longer
uploaded to GitHub releases. These binaries are only needed in Docker
images for the /download/ endpoint.

Updated required assets list to include all versioned tarballs/zips
instead of standalone binaries.
2025-11-11 17:50:02 +00:00
rcourtman
2fb223ffc5 Improve Helm chart package visibility configuration (related to #686)
Add fallback attempts to set package visibility through multiple API endpoints.
Also adds helpful output message with verification link.
2025-11-11 17:50:02 +00:00
rcourtman
19e86f4560 Reduce release assets by removing duplicates
Removed:
- Individual .sha256 files (checksums.txt already contains all checksums)
- Standalone binaries without version numbers (users should download versioned tarballs/zips)

Standalone binaries are only needed in Docker images for the /download/ endpoint.
GitHub releases should only contain versioned archives for user downloads.

This reduces release assets from ~54 files to ~19 files per release.
2025-11-11 17:26:00 +00:00
rcourtman
31e5d5b3b7 Automatically set Helm chart package visibility to public (related to #686)
The pulse-chart package in GHCR currently requires authentication for pulls
because it defaults to private visibility. This affects all users trying to
install via `helm install oci://ghcr.io/rcourtman/pulse-chart`.

This commit adds a workflow step to automatically set the package to public
after each push, enabling anonymous pulls without requiring `helm registry login`.

Note: The existing package will need one-time manual configuration via GitHub
web UI until the next release triggers this workflow.

Related to discussion #686
2025-11-11 17:19:03 +00:00
rcourtman
b00b176b9a Exclude development/infrastructure changes from release notes
Users don't care about CI/CD improvements, release workflows, build
processes, or testing infrastructure. Only include user-visible changes.

Related to #671
2025-11-11 17:18:50 +00:00
rcourtman
7ad8d8310b Remove commit hashes from LLM-generated release notes
Commit hashes clutter the release notes and aren't useful for end users.
Only include issue references when explicitly mentioned in commits.

Related to #671
2025-11-11 17:11:02 +00:00
rcourtman
583d21bdf9 Fix commit hash linking in release notes
Remove # symbol from commit hash references so GitHub auto-links them.
Format: (abc123) instead of (#abc123)
Issue references still use #: (#123)

Related to #671
2025-11-11 17:03:39 +00:00
rcourtman
ef0452f326 Use heredoc to write release notes without bash interpretation
Backticks in GitHub Actions output were still being interpreted even
when assigned to a variable and then echoed to a file. Use heredoc
with single quotes to prevent any bash expansion.

Related to #671
2025-11-11 16:21:22 +00:00
rcourtman
c98ab35da6 Fix release notes backtick command substitution issue
Use --notes-file instead of --notes with variable expansion to prevent
bash from interpreting markdown code blocks as shell commands.

Fixes the error where installation examples like:
  ```bash
  docker pull rcourtman/pulse:v4.29.0
  ```

Were being executed as actual commands during release creation.

Related to #671
2025-11-11 16:09:02 +00:00
rcourtman
16b46fb5f1 Fix release workflow: fetch git tags for changelog generation
The checkout wasn't fetching tags despite fetch-depth: 0.
Explicitly run git fetch --tags --force after checkout.
2025-11-11 15:44:00 +00:00
rcourtman
ffbd4a4632 Fix release workflow: fetch git tags for changelog generation
actions/checkout@v4 does not fetch tags by default, causing the
previous tag lookup to fail and fall back to comparing with the
first commit SHA. Added fetch-depth: 0 to fetch all history including tags.
2025-11-11 15:32:48 +00:00
rcourtman
a8612daecb Simplify previous tag detection for release notes
Just use the latest tag directly instead of trying to exclude the current version.
Since we're generating release notes BEFORE creating the tag, the latest tag
will always be the previous release.
2025-11-11 15:27:37 +00:00
rcourtman
cfcf09da27 Fix release notes generation: properly detect previous tag
The script was failing because git describe --tags --abbrev=0 HEAD^ returns
the current HEAD commit SHA when no tag exists before HEAD, resulting in
comparing HEAD..HEAD which has zero commits.

Now using git tag --sort=-version:refname to get the latest tag (excluding
the version being released) which will properly compare v4.29.0 with v4.28.0.
2025-11-11 15:03:47 +00:00
rcourtman
5f8bfa0cc1 Improve error reporting in release notes generation
- Capture script exit code before checking
- Show full error output if script fails
- Prevents silent failures where error is hidden in temp file

Related to #671 (automated release workflow)
2025-11-11 14:38:39 +00:00
rcourtman
a5f2568d66 Remove RELEASE_PROCEDURE.md - will add to CLAUDE.md instead 2025-11-11 14:27:48 +00:00
rcourtman
71dcac56d5 Add comprehensive release procedure documentation
Document the complete automated release process for future reference:
- Step-by-step release workflow trigger
- What each phase does (Docker build, release creation)
- How to review and publish draft releases
- Troubleshooting common issues
- Emergency rollback procedures
- Workflow architecture and design principles

This ensures future AI contexts and maintainers understand the full
release process without needing to reverse-engineer the workflow.

Related to #671 (automated release workflow)
2025-11-11 14:26:27 +00:00
rcourtman
99bc7d0593 Fix release notes extraction in workflow
- Replace sed with awk for more reliable multiline extraction
- Use temp file to capture full script output
- Extract content between separator lines correctly
- Fixes empty release notes in draft releases

Previous issue: sed pattern wasn't matching the separator lines,
resulting in empty RELEASE_NOTES variable.

New approach: Use awk to capture everything between the two separator
lines, handling multiline content properly.

Related to #671 (automated release workflow)
2025-11-11 14:22:46 +00:00
rcourtman
151aaceafc Update release notes template to match established format
- Use exact template format from v4.28.0 and prior releases
- Include all standard sections: New Features, Bug Fixes, Improvements, Breaking Changes
- Add complete installation instructions (systemd, Docker, Manual Binary, Helm)
- Include Downloads section with all artifact types
- Add Notes section for important highlights and upgrade considerations
- Ensure LLM outputs format exactly matching previous releases

Related to #671 (automated release workflow)
2025-11-11 14:05:15 +00:00
rcourtman
c7b64685e0 Add LLM-powered release notes generation
- Create scripts/generate-release-notes.sh to auto-generate release notes from git commits
- Supports both Anthropic Claude and OpenAI APIs
- Uses Claude Haiku 4.5 (claude-haiku-4-5-20251001) for cost efficiency ($1/$5 per million tokens)
- Falls back to OpenAI gpt-4o-mini if Anthropic key not available
- Integrates into release workflow between validation and release creation
- Compares current version with previous git tag to generate changelog
- Outputs categorized, user-friendly release notes with installation instructions

Workflow now automatically:
1. Finds previous release tag
2. Analyzes all commits since last release
3. Generates structured release notes via LLM
4. Uses generated notes for draft release body

Requires ANTHROPIC_API_KEY or OPENAI_API_KEY in GitHub secrets.

Related to #671 (automated release workflow)
2025-11-11 14:01:34 +00:00