Commit Graph

89 Commits

Author SHA1 Message Date
rcourtman bd6f77e093 Prepare v6.0.0 release candidate
Tighten v5-to-v6 upgrade safety, release installability, provider MSP mode handling, AI cost accounting, metrics flushing, and frontend guardrails for the v6.0.0 GA candidate.
2026-06-04 14:07:14 +01:00
rcourtman 7c35977fcb Fix post-publish pipeline failures for v6.0.0-rc.6
promote-floating-tags.yml waited on rcourtman/pulse-agent:${TAG} and
promoted floating tags for it, but publish-docker.yml never pushes the
agent image — Pulse Agent ships as GitHub Release binaries
(publish-docker.yml line 199 confirms). The wait timed out after 5
minutes on every release since the pulse-agent push step was removed,
leaving floating tags unpromoted. Stripped the vestigial wait block,
the agent promote step, and the agent line in the summary. Updated
header comments in both files to drop the past-tense reference.

install-sh-smoke.yml booted jrei/systemd-debian:12 without
--cgroupns=host, so on GHA ubuntu-24.04 (cgroup v2 unified hierarchy)
the container's systemd PID 1 exited before mounting the cgroup tree
and the container disappeared during readiness polling. Added
--cgroupns=host, an explicit /run/lock tmpfs, and dropped --rm so the
container persists for diagnostic capture on failure (trap handles
cleanup). Added an "is container still running" probe inside the
readiness loop and richer diagnostic output on timeout.
2026-05-27 22:08:15 +01:00
rcourtman 22a94f47d9 Skip release publish downstreams for drafts 2026-05-12 17:32:11 +01:00
rcourtman 29a815ef2a Fail closed on stale API action plans 2026-05-12 16:55:51 +01:00
rcourtman 3566a4d61d Drive promote-floating-tags via workflow_call from create-release
promote-floating-tags.yml's `workflow_run` chain off publish-docker.yml
silently stopped firing for rc.3 → rc.5 because publish-docker failed at
the now-removed pulse-agent push step. Customers pulling
rcourtman/pulse:latest, :6, or :6.0 stayed on whatever the previous
successful release had tagged — there was no warning anywhere that the
floating tags were stale.

Same fix pattern as install-sh-smoke (commit 7c0f65425) and
publish-helm-chart (commit 14c79a28e): add a workflow_call trigger to
promote-floating-tags.yml and call it explicitly from create-release.yml
after validate_release_assets succeeds.

Gating on validate_release_assets is intentional: that workflow waits
for the docker image to be pullable from the registry (with retry
backoff), so by the time it succeeds the image manifest exists and
re-tagging it to latest/major/minor cannot point at vapor.

The legacy workflow_run trigger stays as the primary path; this just
guarantees promotion even when the chain doesn't fire.

Tag-resolver step now accepts inputs from workflow_call / workflow_dispatch
and only falls back to the workflow_run derivation when inputs are absent,
so all three entry paths converge on the same identity.

Pinned in build_release_assets_test.go:
- new TestPromoteFloatingTagsReachableViaWorkflowCall pins the trigger
  declaration and the input-priority resolver
- existing TestCreateReleaseUploadsPowerShellInstaller extended to pin
  the promote_floating_tags job wiring (uses, tag, prerelease)

Contract delta in deployment-installability.md Extension Point 7
documents the same explicit-workflow_call requirement that applies to
publish-helm-chart, extended to promote-floating-tags.
2026-05-12 16:47:51 +01:00
rcourtman 14c79a28e7 Trigger publish-helm-chart via workflow_call from create-release
v6 rc.1 → rc.5 published successfully but the Helm chart never landed on
rcourtman.github.io/Pulse/index.yaml — the index still ends at v5.1.30.
`helm install pulse pulse/pulse --version 6.0.0-rc.5` returns
chart-not-found; without `--version` helm pulls the latest published
chart (v5.1.30) into a customer's v6 cluster.

Root cause: GitHub does not fire `release: published` for releases that
were created as drafts and later PATCHed to draft=false. create-release.yml
deliberately uses that path so it can upload assets and run
validate-release-assets against the draft before promoting. Inspection of
the workflow run history confirms: every gh-API `release: published` event
since 2026-03-02 has been from manually-dispatched v5 stable cuts; zero
fired for v6 RCs published through the create-release pipeline.

Fix the same way install-sh-smoke was wired in commit 7c0f65425: add a
`workflow_call` trigger to publish-helm-chart.yml and call it explicitly
from create-release.yml as a downstream of validate_release_assets. The
chart-version resolver in publish-helm-chart now accepts inputs from
either workflow_call or workflow_dispatch and only falls back to the
release-event tag when no inputs are present, keeping the legacy
release-event path working for forks / manual gh-CLI publishes that
create with draft=false from the start.

Pinned in build_release_assets_test.go:
- create-release.yml wiring (publish_helm_chart job, version inputs)
- publish-helm-chart.yml workflow_call trigger declaration
- chart-version resolver's input-priority logic

Contract delta in deployment-installability.md Extension Point 7
documents the workflow_call requirement and forbids relying on the
release-published webhook for the create-release.yml draft-promotion
path.

The fix takes effect on the next release through the pipeline. Backfill
of the v6.0.0-rc.5 chart needs a one-time manual dispatch of
publish-helm-chart.yml against chart_version=6.0.0-rc.5.
2026-05-12 16:30:53 +01:00
rcourtman 7c0f654253 Wire install.sh smoke gate into create-release.yml release pipeline
The smoke gate workflow exists from commit 065ebdb27 but until it is
called from create-release.yml it does not actually protect any release.
That is exactly the regression class that let rc.1 → rc.5 ship with a
broken install.sh: nothing in the release pipeline exercised the
documented secure-install flow against the published GitHub Release URL.

Wire install-sh-smoke.yml as a downstream workflow_call after
validate_release_assets succeeds. Gated on
historical_asset_backfill_only != 'true' since asset-backfill flows
re-upload to an already-published release and the smoke would just
re-confirm what hasn't changed.

Pre-install structural checks were verified locally against rc.5 — the
gate correctly fires the banner / agent-banner / --version handler
assertions against the broken release. The end-to-end container portion
(privileged systemd boot, install.sh execution, /api/health, /api/version
match) will run for the first time on the next release that publishes
through this workflow; existing retry loops on systemd readiness,
service activation, and health endpoint absorb transient runner flakes.

Add install-sh-smoke.yml to the deployment-installability canonical files
and to the release-promotion proof policy's match_files, and add
scripts/installtests/build_release_assets_test.go to that policy's
exact_files (matching the existing pin set for related policies in the
deployment-installability subsystem). Update subsystem_lookup_test.py
fixtures that pinned the exact_files list literally.

Pinned the create-release.yml wiring in build_release_assets_test.go
alongside the validate-release-assets wiring so the smoke step cannot
silently be unwired.

Document the gate's contract responsibilities in
deployment-installability Extension Point 2.
2026-05-12 11:44:04 +01:00
rcourtman 3da835c5bc Publish a distribution path for pulse-mcp
The MCP adapter shipped in slice 51 with one install option:
clone the repo and go build. This slice integrates pulse-mcp
into Pulse's existing governed release pipeline so a Pulse
release publishes a pulse-mcp binary alongside the unified agent
and the install scripts that bring it home in one command.

What ships:

  - scripts/build-release.sh extended to build pulse-mcp for
    the same multi-OS matrix as the unified agent, package
    per-platform tarballs and zips, and copy bare binaries to
    RELEASE_DIR for /releases/latest/download/ redirect
    compatibility.
  - .github/workflows/create-release.yml extended to upload
    the bare pulse-mcp binaries plus install-mcp.sh and
    install-mcp.ps1 as release assets.
  - scripts/install-mcp.sh: bash one-line installer that
    detects platform/arch, downloads the matching binary from
    the configured release (latest by default), verifies SHA256
    against the published checksums.txt, places at
    ~/.local/bin/pulse-mcp (or /usr/local/bin if not writable).
    Honors PULSE_MCP_VERSION, PULSE_MCP_BIN_DIR, PULSE_MCP_REPO,
    PULSE_MCP_NO_VERIFY env vars; declines Windows shells with
    a pointer at the .ps1 sibling.
  - scripts/install-mcp.ps1: PowerShell installer for Windows,
    placing pulse-mcp.exe at $LOCALAPPDATA\pulse-mcp.

Documentation aligned:

  - cmd/pulse-mcp/README.md gains an Install section above
    Quick start with three options: one-line installer,
    GitHub Release download, go install. Documents the macOS
    Gatekeeper bypass since v1 is unnotarized by design.
  - The Settings -> API Access agent-integrations panel now
    surfaces the curl|bash command above the config snippet so
    operators see "install pulse-mcp" before "configure your
    MCP client."
  - docs/releases/AGENT_PARADIGM.md drops the "no published
    distribution path" item from "what it does not do yet" and
    documents the Gatekeeper / Homebrew gaps as next-tier
    follow-ups.

Trade-offs surfaced and chosen:

  - Same cadence as Pulse: pulse-mcp ships per Pulse release,
    not on its own track. The MCP server reads the manifest
    from the Pulse it talks to, so version alignment is the
    natural model.
  - No Homebrew tap or core formula in v1. Maintaining a tap
    is real ongoing work; foundation supports adding Homebrew
    later as a layer.
  - No Docker image. Stdio JSON-RPC fights Docker's stdin
    /stdout pattern.
  - No notarization in v1. SHA256 verification through the
    installer preserves the audit trail; README documents the
    Gatekeeper bypass.

Subsystem contract: deployment-installability.md gains
scripts/install-mcp.sh, scripts/install-mcp.ps1, and
cmd/pulse-mcp/ in canonical files (mid-list entries
renumbered) plus a paragraph documenting the new MCP entry
point alongside the existing installer family.

Verification artifacts:

  - scripts/installtests/build_release_assets_test.go gains
    TestBuildReleasePackagesPulseMcpForAllPlatforms which pins
    the build/package/copy wiring and the load-bearing
    install-mcp.sh helpers (platform detection, SHA256
    verification, install-dir resolution).
  - scripts/release_control/render_release_body_test.py gains
    test_agent_paradigm_release_notes_blurb_documents_-
    distribution_path which pins the AGENT_PARADIGM.md draft's
    install-mcp.sh reference and the four-axis frame so a
    future edit cannot regress the install story silently.

Smoke-tested install-mcp.sh locally on darwin-arm64: platform
detection, install-dir resolution, URL building, and 404 error
handling all correct. The full end-to-end install path becomes
live the moment a Pulse release ships pulse-mcp binaries; the
next RC cut will exercise it.
2026-05-10 17:04:49 +01:00
rcourtman d6e96ebeca Fix v6 demo release signing key deployment 2026-05-05 21:40:14 +01:00
rcourtman 9ba0c3fa96 Retry release asset uploads 2026-05-03 10:26:51 +01:00
rcourtman 011d288cb4 Fix release asset validation workflow gates 2026-05-02 00:36:54 +01:00
rcourtman fb6b53268a Harden release Docker key embedding cache 2026-04-24 17:21:04 +01:00
rcourtman f58840e8a8 Guard forward release signing against trust-root drift 2026-04-22 19:59:18 +01:00
rcourtman c0f48b27ba Grant release validation workflow required permissions 2026-04-22 17:47:13 +01:00
rcourtman 9c2e3d5ffb Add historical backfill mode to create-release workflow 2026-04-22 17:43:37 +01:00
rcourtman f96abc5ee0 Publish signed release-packet SBOM assets 2026-04-22 16:49:29 +01:00
rcourtman 74df03c78c Pin workflow actions and CI image versions 2026-04-22 10:12:15 +01:00
rcourtman 4720807ae5 Require signed installer downloads and local release sidecars 2026-04-22 03:51:46 +01:00
rcourtman 96034f5e10 Attest release artifacts and harden image provenance 2026-04-22 03:22:29 +01:00
rcourtman 7be844f23a Require signed unified agent release assets 2026-04-22 02:00:29 +01:00
rcourtman a8d9051b15 Restrict default workflow token permissions 2026-04-22 01:21:24 +01:00
rcourtman fb7b9b01fc Update pinned Go toolchain to 1.25.9 2026-04-18 10:04:34 +01:00
rcourtman b19991f4ae Fix published release body rendering 2026-04-16 22:20:17 +01:00
rcourtman 6fcdcf8b8e Add pre-release Helm chart smoke gate 2026-04-16 21:48:35 +01:00
rcourtman 447280a0ce Fix release-line demo workflow dispatch and verification 2026-04-16 20:54:01 +01:00
rcourtman ef288b250b Reconcile draft release retries 2026-04-12 10:52:19 +01:00
rcourtman a48fb63cb3 Preserve draft release validation state 2026-04-11 17:35:14 +01:00
rcourtman 58ad221d47 Add governed v6 preview demo targets 2026-04-10 10:53:17 +01:00
rcourtman c6de686cb4 Fix release workflow branch policy env 2026-04-04 15:13:16 +01:00
rcourtman f34ec16138 fix(release): require explicit rollback targets in workflows 2026-03-26 13:03:24 +00:00
rcourtman cb41473018 Rename promotion RC wording to prerelease 2026-03-25 11:08:05 +00:00
rcourtman 11c50eb7a0 Align v6 release branch governance 2026-03-19 10:18:45 +00:00
rcourtman 778a2577b6 feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
rcourtman ac9003d105 fix: build pulse:test Docker image for integration tests
The docker-compose test stack expects a pulse:test image. Build it
from the Dockerfile before running docker compose.
2026-02-04 17:13:17 +00:00
rcourtman 04dbfa6329 fix: use docker compose plugin instead of standalone docker-compose
GitHub Actions runners no longer include the standalone docker-compose
binary. Use the docker compose plugin syntax instead.
2026-02-04 17:08:56 +00:00
rcourtman cae9ed7332 fix: skip frontend rebuild in integration test job
The integration_tests job restores the pre-built frontend dist from
cache and copies it to the embed location, but then runs make build
which unconditionally rebuilds the frontend via npm — failing because
node_modules aren't installed. Use go build directly since the
frontend is already embedded.
2026-02-04 17:04:56 +00:00
rcourtman 655b8905c9 fix(ci): fix YAML quoting on line 494 2026-02-03 22:09:24 +00:00
rcourtman 5b48b37c4f fix(ci): replace emojis with ASCII in workflow 2026-02-03 22:07:12 +00:00
rcourtman cb54cc5dc3 fix(ci): correct sparse-checkout syntax 2026-02-03 22:05:38 +00:00
rcourtman 75cda5011c fix(ci): wrap job-level if expressions 2026-02-03 22:04:23 +00:00
rcourtman 8fe6d9c753 chore: add comment to force workflow re-parse 2026-02-03 21:58:14 +00:00
rcourtman a4916fc6ff perf(ci): parallelize release workflow for faster builds
Optimizations:
- Split monolithic preflight_tests into parallel jobs:
  - frontend_checks (lint) - ~2 min
  - backend_tests (Go tests) - ~5 min
  - docker_build (verify build) - ~5 min
- Skip arm64 builds for prereleases (RC/alpha/beta) - saves ~4 min
- Skip integration tests for prereleases - saves ~3 min
- Don't push staging images, just verify builds
- Merge version_guard into prepare job with sparse checkout
- Use frontend build cache across jobs

Expected time savings:
- RC releases: ~12 min → ~5-6 min (parallel + skip arm64/integration)
- Stable releases: ~12 min → ~8-9 min (parallel jobs)
2026-02-03 21:55:09 +00:00
rcourtman 1490a6e6e3 revert: remove dual-key license verification
Restored original license signing key from backup - key was never
compromised (private repo). Removes unnecessary dual-key complexity:

- Remove legacyPublicKey and SetLegacyPublicKey from license.go
- Simplify signature verification to single key
- Remove EmbeddedLegacyPublicKey from pubkey.go
- Remove PULSE_LICENSE_LEGACY_PUBLIC_KEY from Dockerfile and workflows
- Remove dual-key test
- Simplify mock.env
2026-02-03 21:29:21 +00:00
rcourtman f810a003eb license: add dual-key verification 2026-02-03 20:45:00 +00:00
rcourtman 445c5c0587 Fix: remove install-sensor-proxy.sh from release workflow (script was removed) 2026-02-03 00:08:19 +00:00
rcourtman 8eb42f6b31 ci: set PULSE_DATA_DIR in test step to prevent /etc/pulse fallback 2026-01-20 18:00:07 +00:00
rcourtman 5b7a68bcc0 fix: Add VERSION build arg to all Docker builds in CI workflows 2026-01-01 16:14:56 +00:00
rcourtman e0325e5cf9 fix(ci): test multi-arch Docker build in preflight before releasing
Previously, preflight only built amd64 images, so multi-arch failures
(like the QEMU timeout in 5.0.5) weren't caught until after the
release was published.

Now preflight builds linux/amd64,linux/arm64 staging images. If
multi-arch build fails, the release pipeline stops before publishing.

Combined with the Dockerfile fix (forcing amd64 for build stages),
this ensures Docker build issues are caught early.
2025-12-27 13:25:01 +00:00
rcourtman 9bd7e31843 fix: Handle 404 response in release existence check 2025-12-26 16:49:37 +00:00
rcourtman 4bcad25433 fix: Make release workflow idempotent for re-runs
- Check if tag exists before creating (skip if pointing to HEAD, fail with
  helpful message if pointing elsewhere)
- Check if draft release exists before creating (update existing draft)
- Add --clobber to all asset uploads to allow re-uploading on retry
2025-12-26 16:26:45 +00:00