Prepare v6.0.5 patch release
Some checks are pending
Build and Test / Secret Scan (push) Waiting to run
Build and Test / Frontend & Backend (push) Waiting to run
Canonical Governance / governance (push) Waiting to run
Helm CI / Lint and Render Chart (push) Waiting to run
Core E2E Tests / Playwright Core E2E (push) Waiting to run

Refs #1530

Refs #1531
This commit is contained in:
rcourtman 2026-07-06 23:29:17 +01:00
parent 5b6e7dc35e
commit 41a99c1a03
16 changed files with 133 additions and 43 deletions

View file

@ -1 +1 @@
6.0.4
6.0.5

View file

@ -2,9 +2,9 @@ apiVersion: v2
name: pulse
description: Helm chart for deploying the Pulse hub and optional Docker monitoring agent.
type: application
version: 6.0.4
appVersion: "6.0.4"
icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.0.4/docs/images/pulse-logo.svg
version: 6.0.5
appVersion: "6.0.5"
icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.0.5/docs/images/pulse-logo.svg
keywords:
- monitoring
- proxmox
@ -32,7 +32,7 @@ annotations:
description: Smoke tests with kind cluster deployment
artifacthub.io/links: |
- name: Documentation
url: https://github.com/rcourtman/Pulse/blob/v6.0.4/docs/KUBERNETES.md
url: https://github.com/rcourtman/Pulse/blob/v6.0.5/docs/KUBERNETES.md
- name: Support
url: https://github.com/rcourtman/Pulse/discussions
artifacthub.io/maintainers: |

View file

@ -1,6 +1,6 @@
# pulse
![Version: 6.0.4](https://img.shields.io/badge/Version-6.0.4-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.0.4](https://img.shields.io/badge/AppVersion-6.0.4-informational?style=flat-square)
![Version: 6.0.5](https://img.shields.io/badge/Version-6.0.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.0.5](https://img.shields.io/badge/AppVersion-6.0.5-informational?style=flat-square)
Helm chart for deploying the Pulse hub and optional Docker monitoring agent.

View file

@ -2,7 +2,7 @@ version: '3.8'
services:
pulse:
image: ${PULSE_IMAGE:-rcourtman/pulse:6.0.4}
image: ${PULSE_IMAGE:-rcourtman/pulse:6.0.5}
container_name: pulse
restart: unless-stopped
logging:

View file

@ -7,6 +7,8 @@ For historical v4 notes that previously lived in this repo, see:
`docs/releases/RELEASE_NOTES_v4.md`
For the current stable v6 patch packet, see:
- `docs/releases/RELEASE_NOTES_v6.0.5.md`
- `docs/releases/V6_CHANGELOG_v6.0.5.md`
- `docs/releases/RELEASE_NOTES_v6.0.4.md`
- `docs/releases/V6_CHANGELOG_v6.0.4.md`
- `docs/releases/RELEASE_NOTES_v6.0.3.md`

View file

@ -4,6 +4,8 @@ This guide covers practical upgrade steps for existing Pulse installs moving to
For the current stable v6 packet and rollout references, see:
- `docs/releases/RELEASE_NOTES_v6.0.5.md`
- `docs/releases/V6_CHANGELOG_v6.0.5.md`
- `docs/releases/RELEASE_NOTES_v6.0.4.md`
- `docs/releases/V6_CHANGELOG_v6.0.4.md`
- `docs/releases/RELEASE_NOTES_v6.0.3.md`

View file

@ -807,15 +807,14 @@ TLS floor in the dynamic config.
## Current State
The active stable `v6.0.4` cut sets the repo-root `VERSION`,
The active stable `v6.0.5` cut sets the repo-root `VERSION`,
repo-root `docker-compose.yml` image default, `scripts/install-docker.sh`
fallback, and Helm chart release metadata to the same `6.0.4` release version.
This patch release uses the stable hotfix path with `rollback_version=v6.0.3`,
fallback, and Helm chart release metadata to the same `6.0.5` release version.
This patch release uses the stable hotfix path with `rollback_version=v6.0.4`,
`hotfix_exception=true`, a release-owner reason, and no fabricated same-version
RC tag. It advances the v6.0.3 stable line with customer-support fixes for
audit log timestamp compatibility, remembered-login persistence, platform and
agent metric normalization, PBS/recovery memory retention, OIDC provider
persistence, and Docker/Proxmox platform metadata. The initial GA promotion
RC tag. It advances the v6.0.4 stable line with customer-support fixes for
Gemini Patrol tool-call readiness and remembered-login submit persistence.
The initial GA promotion
metadata remains
`promoted_from_tag=v6.0.0-rc.7`, `rollback_version=v5.1.35`,
`ga_date=2026-07-04`, and `v5_eos_date=2026-10-02` for the first stable
@ -868,8 +867,8 @@ compose image default, standalone installer fallback constant, and packaged
Helm metadata. A draft release workflow failure caused by stale image or chart
pins is a release-packet blocker until the defaults, tests, and evidence
record are refreshed from the new branch head.
For the active stable `v6.0.4` cut, the repo-root compose default and
`scripts/install-docker.sh` fallback must both pin `6.0.4`. The stable
For the active stable `v6.0.5` cut, the repo-root compose default and
`scripts/install-docker.sh` fallback must both pin `6.0.5`. The stable
promotion guard remains in force by rejecting leftover `-rc.` defaults when
the governed `VERSION` is a stable release.
The RC7 packet refresh records `fc10de9b5477613316473267b72b05b6b2b7aaff`

View file

@ -0,0 +1,22 @@
# Pulse v6.0.5 Release Notes
`v6.0.5` is a stable patch release for the Pulse v6 line. It follows
`v6.0.4` and bundles support fixes for Patrol Gemini model readiness and
remembered-login submit persistence.
## Fixes
- Fixed Patrol readiness checks for Gemini models so tool-call capability is
detected from Gemini candidate parts as well as top-level tool-call lists.
- Fixed the login form so enabling "remember me" during submit persists the
remembered username immediately.
- Refreshed Docker, Helm, installer, and release-helper metadata for the stable
patch line.
## Upgrade Notes
Use the normal v6 install or update flow for `v6.0.5`. The rollback target for
this patch release is `v6.0.4`.
Paid Pulse Pro, Relay, and eligible legacy customers should continue to use the
private download page and private runtime image for paid runtime features.

View file

@ -0,0 +1,19 @@
# Pulse v6.0.5
_This changelog describes the stable `v6.0.5` patch release compared with
`v6.0.4`._
## Fixed
- Patrol readiness checks now detect Gemini tool-call capability from Gemini
candidate parts as well as top-level tool-call lists.
- Remembered-login state now persists the saved username when the checkbox is
enabled during submit.
- Docker, Helm, installer, and release-helper metadata now track the active
stable patch version.
## Release Metadata
- Version: `v6.0.5`
- Rollback target: `v6.0.4`
- Promotion path: stable patch hotfix from `main`

View file

@ -116,6 +116,8 @@ describe('useAppRuntimeState', () => {
vi.doMock('@/utils/localStorage', () => ({
STORAGE_KEYS: {
AUTH: 'auth',
AUTH_USER: 'pulse_auth_user',
REMEMBERED_LOGIN_USERNAME: 'pulse_remembered_login_username',
ORG_ID: 'org_id',
GUEST_METADATA: 'guest_metadata',
DOCKER_METADATA: 'docker_metadata',

View file

@ -6,7 +6,7 @@ set -euo pipefail
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
DOCKER_IMAGE_REPO="${DOCKER_IMAGE_REPO:-rcourtman/pulse}"
CANONICAL_DEFAULT_PULSE_VERSION="6.0.4"
CANONICAL_DEFAULT_PULSE_VERSION="6.0.5"
resolve_default_pulse_version() {
if [ -n "${PULSE_IMAGE_VERSION:-}" ]; then

View file

@ -261,12 +261,16 @@ func TestCurrentStablePatchReleasePacketTracksInstallMetadata(t *testing.T) {
assertFileContainsAllNormalized(t, releaseNotesPath,
"`v"+version+"` is a stable patch release",
"`v"+previous+"`",
"Patrol Gemini model readiness",
"remembered-login submit persistence",
"rollback target for this patch release is `v"+previous+"`",
)
assertFileContainsAll(t, changelogPath,
"Version: `v"+version+"`",
"Rollback target: `v"+previous+"`",
"Promotion path: stable patch hotfix from `"+releaseBranch+"`",
"Gemini tool-call capability",
"Remembered-login state now persists",
)
assertFileContainsAll(t, repoFile("docs", "RELEASE_NOTES.md"),
"docs/releases/RELEASE_NOTES_v"+version+".md",
@ -285,6 +289,7 @@ func TestCurrentStablePatchReleasePacketTracksInstallMetadata(t *testing.T) {
assertFileContainsAll(t, repoFile("deploy", "helm", "pulse", "README.md"),
"Version-"+version+"-informational",
"AppVersion-"+version+"-informational",
"Autogenerated from chart metadata using [helm-docs v1.14.2]",
)
assertFileContainsAll(t, repoFile("docker-compose.yml"),
"image: ${PULSE_IMAGE:-rcourtman/pulse:"+version+"}",

View file

@ -211,6 +211,7 @@ func TestInstallDockerProofTracksStablePatchReleaseContract(t *testing.T) {
assertFileContainsAllNormalized(t, repoFile("docs", "release-control", "v6", "internal", "subsystems", "deployment-installability.md"),
"The active stable `v"+version+"` cut sets the repo-root `VERSION`, repo-root `docker-compose.yml` image default, `scripts/install-docker.sh` fallback, and Helm chart release metadata to the same `"+version+"` release version.",
"This patch release uses the stable hotfix path with `rollback_version=v"+previous+"`, `hotfix_exception=true`, a release-owner reason, and no fabricated same-version RC tag.",
"It advances the v"+previous+" stable line with customer-support fixes",
"For the active stable `v"+version+"` cut, the repo-root compose default and `scripts/install-docker.sh` fallback must both pin `"+version+"`",
)
}

View file

@ -477,6 +477,9 @@ class ReleasePromotionPolicyTest(unittest.TestCase):
self.assertIn("release-dry-run.yml", dry_run_trigger)
self.assertIn("gh workflow run release-dry-run.yml", dry_run_trigger)
self.assertIn("Release Dry Run executes the selected remote ref", dry_run_trigger)
self.assertIn("Hotfix exception to bypass 72-hour prerelease soak? [y/N]", dry_run_trigger)
self.assertIn("blank only for approved hotfix", dry_run_trigger)
self.assertIn('if [ -z "$PROMOTED_FROM_TAG" ] && [ "$HOTFIX_EXCEPTION" != "true" ]; then', dry_run_trigger)
self.assertNotIn("Continue anyway?", dry_run_trigger)
self.assertIn('if [ "${REHEARSAL_CONCLUSION}" != "success" ]; then', workflow)
self.assertIn("did not produce a valid promotion metadata envelope", workflow)
@ -506,6 +509,10 @@ class ReleasePromotionPolicyTest(unittest.TestCase):
self.assertIn("https://pulserelay.pro/download.html", contract)
self.assertIn("PULSE_IMAGE`-aware compose image line", normalize_ws(contract))
self.assertIn("hardcoded `image: rcourtman/pulse:...`", normalize_ws(contract))
self.assertIn("Resolving governed promotion metadata...", helper)
self.assertIn("--release-notes-file \"$NOTES_FILE\"", helper)
self.assertIn("blank for hotfix with no RC lineage", helper)
self.assertIn('if [ -z "$PROMOTED_FROM_TAG" ] && [ "$HOTFIX_EXCEPTION" != "true" ]; then', helper)
self.assertIn("control_plane.py --branch-for-version", content)
self.assertIn('git fetch --prune origin main "${REQUIRED_BRANCH}" --tags', content)
self.assertIn('REQUIRED_BRANCH: ${{ steps.branch_policy.outputs.required_branch }}', content)

View file

@ -100,19 +100,6 @@ if [ -z "$ROLLBACK_VERSION" ]; then
fi
if [ "$IS_PRERELEASE" != "true" ]; then
DEFAULT_PROMOTED_FROM_TAG=$(git tag -l "v${VERSION}-rc.*" --sort=-version:refname | head -1 || true)
echo ""
if [ -n "$DEFAULT_PROMOTED_FROM_TAG" ]; then
read -r -p "Promoted prerelease tag [${DEFAULT_PROMOTED_FROM_TAG}]: " PROMOTED_FROM_TAG
PROMOTED_FROM_TAG="${PROMOTED_FROM_TAG:-$DEFAULT_PROMOTED_FROM_TAG}"
else
read -r -p "Promoted prerelease tag (for example v${VERSION}-rc.2): " PROMOTED_FROM_TAG
fi
if [ -z "$PROMOTED_FROM_TAG" ]; then
echo "❌ Error: promoted prerelease tag is required for stable rehearsals"
exit 1
fi
echo ""
read -r -p "Hotfix exception to bypass 72-hour prerelease soak? [y/N] " HOTFIX_REPLY
if [[ "$HOTFIX_REPLY" =~ ^[Yy]$ ]]; then
@ -124,6 +111,23 @@ if [ "$IS_PRERELEASE" != "true" ]; then
fi
fi
DEFAULT_PROMOTED_FROM_TAG=$(git tag -l "v${VERSION}-rc.*" --sort=-version:refname | head -1 || true)
echo ""
if [ -n "$DEFAULT_PROMOTED_FROM_TAG" ]; then
if [ "$HOTFIX_EXCEPTION" = "true" ]; then
read -r -p "Promoted prerelease tag, or blank for hotfix with no RC lineage [${DEFAULT_PROMOTED_FROM_TAG}]: " PROMOTED_FROM_TAG
else
read -r -p "Promoted prerelease tag [${DEFAULT_PROMOTED_FROM_TAG}]: " PROMOTED_FROM_TAG
PROMOTED_FROM_TAG="${PROMOTED_FROM_TAG:-$DEFAULT_PROMOTED_FROM_TAG}"
fi
else
read -r -p "Promoted prerelease tag (for example v${VERSION}-rc.2; blank only for approved hotfix): " PROMOTED_FROM_TAG
fi
if [ -z "$PROMOTED_FROM_TAG" ] && [ "$HOTFIX_EXCEPTION" != "true" ]; then
echo "❌ Error: promoted prerelease tag is required for stable rehearsals unless this is an approved hotfix"
exit 1
fi
if [ "$VERSION" = "6.0.0" ]; then
echo ""
read -r -p "v6 GA date to publish with GA (YYYY-MM-DD): " GA_DATE

View file

@ -184,19 +184,6 @@ echo ""
echo "Derived rollback command: ${ROLLBACK_COMMAND}"
if [ "$IS_PRERELEASE" != "true" ]; then
DEFAULT_PROMOTED_FROM_TAG=$(git tag -l "v${VERSION}-rc.*" --sort=-version:refname | head -1 || true)
echo ""
if [ -n "$DEFAULT_PROMOTED_FROM_TAG" ]; then
read -r -p "Promoted prerelease tag [${DEFAULT_PROMOTED_FROM_TAG}]: " PROMOTED_FROM_TAG
PROMOTED_FROM_TAG="${PROMOTED_FROM_TAG:-$DEFAULT_PROMOTED_FROM_TAG}"
else
read -r -p "Promoted prerelease tag (for example v${VERSION}-rc.2): " PROMOTED_FROM_TAG
fi
if [ -z "$PROMOTED_FROM_TAG" ]; then
echo "❌ Error: promoted prerelease tag is required for stable releases"
exit 1
fi
echo ""
read -r -p "Hotfix exception to bypass 72-hour prerelease soak? [y/N] " HOTFIX_REPLY
if [[ "$HOTFIX_REPLY" =~ ^[Yy]$ ]]; then
@ -208,6 +195,23 @@ if [ "$IS_PRERELEASE" != "true" ]; then
fi
fi
DEFAULT_PROMOTED_FROM_TAG=$(git tag -l "v${VERSION}-rc.*" --sort=-version:refname | head -1 || true)
echo ""
if [ -n "$DEFAULT_PROMOTED_FROM_TAG" ]; then
if [ "$HOTFIX_EXCEPTION" = "true" ]; then
read -r -p "Promoted prerelease tag, or blank for hotfix with no RC lineage [${DEFAULT_PROMOTED_FROM_TAG}]: " PROMOTED_FROM_TAG
else
read -r -p "Promoted prerelease tag [${DEFAULT_PROMOTED_FROM_TAG}]: " PROMOTED_FROM_TAG
PROMOTED_FROM_TAG="${PROMOTED_FROM_TAG:-$DEFAULT_PROMOTED_FROM_TAG}"
fi
else
read -r -p "Promoted prerelease tag (for example v${VERSION}-rc.2; blank only for approved hotfix): " PROMOTED_FROM_TAG
fi
if [ -z "$PROMOTED_FROM_TAG" ] && [ "$HOTFIX_EXCEPTION" != "true" ]; then
echo "❌ Error: promoted prerelease tag is required for stable releases unless this is an approved hotfix"
exit 1
fi
if [ "$VERSION" = "6.0.0" ]; then
echo ""
read -r -p "v6 GA date to publish with GA (YYYY-MM-DD): " GA_DATE
@ -226,6 +230,29 @@ if [ "$IS_PRERELEASE" != "true" ]; then
fi
# Trigger the workflow
echo ""
echo "Resolving governed promotion metadata..."
RESOLVER_ARGS=(
--version "$VERSION"
--rollback-version "$ROLLBACK_VERSION"
--hotfix-reason "$HOTFIX_REASON"
--release-notes-file "$NOTES_FILE"
)
if [ -n "$PROMOTED_FROM_TAG" ]; then
RESOLVER_ARGS+=(--promoted-from-tag "$PROMOTED_FROM_TAG")
fi
if [ -n "$GA_DATE" ]; then
RESOLVER_ARGS+=(--ga-date "$GA_DATE")
fi
if [ -n "$V5_EOS_DATE" ]; then
RESOLVER_ARGS+=(--v5-eos-date "$V5_EOS_DATE")
fi
if [ "$HOTFIX_EXCEPTION" = "true" ]; then
RESOLVER_ARGS+=(--hotfix-exception)
fi
python3 scripts/release_control/resolve_release_promotion.py "${RESOLVER_ARGS[@]}" >/tmp/pulse-release-metadata.out
cat /tmp/pulse-release-metadata.out
echo ""
echo "Triggering release workflow..."
if [ -n "$NOTES_FILE" ]; then