mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-10 00:14:38 +00:00
Clarify paid Pulse Pro runtime install path
This commit is contained in:
parent
1f424523da
commit
fc4928e1f2
16 changed files with 168 additions and 18 deletions
|
|
@ -70,6 +70,12 @@ Power-user shortcuts:
|
|||
|
||||
## ⚡ Quick Start
|
||||
|
||||
> **Paid Pulse Pro / Relay / legacy customers:** GitHub release assets and the
|
||||
> public `rcourtman/pulse` Docker image are community builds. They can accept an
|
||||
> activation key, but they do not include the private Pulse Pro runtime hooks.
|
||||
> Use <https://pulserelay.pro/download.html> with your activation key to get the
|
||||
> private Pulse Pro Docker image or Linux archive.
|
||||
|
||||
### Option 1: Proxmox LXC (Recommended)
|
||||
Replace `vX.Y.Z` with the exact release tag you want, verify the signed installer, then run it on your Proxmox host:
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
Pulse is distributed as a lightweight, Alpine-based Docker image.
|
||||
|
||||
> **Paid Pulse Pro / Relay / legacy customers:** The public `rcourtman/pulse`
|
||||
> Docker image is the community build. It can accept an activation key, but it
|
||||
> does not include the private Pulse Pro runtime hooks. Use
|
||||
> <https://pulserelay.pro/download.html> with your activation key, then run the
|
||||
> private registry login and `PULSE_IMAGE=license.pulserelay.pro/pulse-pro:<version>`
|
||||
> compose commands shown there.
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
|
|
@ -172,6 +179,12 @@ docker login registry.example.com
|
|||
|
||||
The agent uses the Docker daemon's credentials for both pulling images and checking for updates.
|
||||
|
||||
Paid Pulse Pro Docker installs use the private Pulse Pro registry rather than
|
||||
the public `rcourtman/pulse` image. Open <https://pulserelay.pro/download.html>,
|
||||
paste your activation key, run the Docker login command shown there, then run
|
||||
the shown `PULSE_IMAGE=license.pulserelay.pro/pulse-pro:<version> docker compose pull`
|
||||
and `docker compose up -d` commands from the host that already runs Pulse.
|
||||
|
||||
### Disabling Update Features
|
||||
|
||||
Pulse provides granular control over update features via environment variables on the **Pulse server**:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
Pulse offers flexible installation options from Docker to enterprise-ready Kubernetes charts.
|
||||
|
||||
> **Paid Pulse Pro / Relay / legacy customers:** GitHub release assets and the
|
||||
> public `rcourtman/pulse` Docker image are community builds. They can accept an
|
||||
> activation key, but they do not include the private Pulse Pro runtime hooks.
|
||||
> Use <https://pulserelay.pro/download.html> with your activation key to get the
|
||||
> private Pulse Pro Docker image or Linux archive.
|
||||
|
||||
## 🚀 Quick Start (Recommended)
|
||||
|
||||
### Proxmox VE (LXC installer)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,19 @@ activation, recovery, or BYOK/local AI setup instead; any exceptional
|
|||
support-issued entitlement is reflected through hosted entitlement state rather
|
||||
than a local in-app trial acquisition flow.
|
||||
|
||||
#### Paid Pulse Pro Runtime
|
||||
|
||||
Paid Pulse Pro, Relay, and eligible legacy customers should not use public
|
||||
GitHub release assets or the public `rcourtman/pulse` Docker image for paid
|
||||
runtime features. Those public downloads are community builds. They can accept
|
||||
an activation key, but they do not include the private Pulse Pro runtime hooks.
|
||||
|
||||
Use <https://pulserelay.pro/download.html> with your activation key instead.
|
||||
Docker users should run the private registry login and
|
||||
`PULSE_IMAGE=license.pulserelay.pro/pulse-pro:<version>` compose commands shown
|
||||
there. Direct Linux users should download the private Pulse Pro archive from the
|
||||
same page.
|
||||
|
||||
#### v5 License Migration
|
||||
|
||||
Pulse v6 uses the activation/grant model for active licensing, but it can migrate valid Pulse v5 paid JWT-style licenses, including legacy Pro and Lifetime licenses.
|
||||
|
|
|
|||
|
|
@ -701,6 +701,10 @@ blocked when the process is the public community build. Customer-facing paid
|
|||
runtime copy must send those users to the private Pulse Pro download rather
|
||||
than implying that the public GitHub release or public Docker image can unlock
|
||||
the same runtime hooks.
|
||||
The owned self-hosted Plans surface must also show a direct Pulse Pro downloads
|
||||
action when an active paid entitlement is running on the community runtime, and
|
||||
the existing-key recovery panel must warn that paid Docker and Linux installs
|
||||
need the private Pulse Pro image or archive before a customer pastes a key.
|
||||
That same browser-shell boundary also owns utility-nav suppression:
|
||||
`frontend-modern/src/AppLayout.tsx` must not expose a separate top-level
|
||||
Operations destination. Diagnostics, reports, and logs now live under the
|
||||
|
|
|
|||
|
|
@ -219,9 +219,14 @@ server-side update execution surfaces.
|
|||
Paid-user GA is part of that same release boundary: the public Pulse release
|
||||
workflow builds OSS `pulse-v...` artifacts only, so release docs and runbooks
|
||||
must require a same-ref/same-version `pulse-enterprise` Pro package, verify
|
||||
`pulse-pro-v...` archives identify `Pulse Pro (Enterprise)`, and keep the
|
||||
paid install/upgrade path pointed at Pro artifacts or a verified paid image
|
||||
before any paid-user Pro runtime claim is made.
|
||||
`pulse-pro-v...` archives identify `Pulse Pro`, and keep the paid
|
||||
install/upgrade path pointed at Pro artifacts or a verified paid image before
|
||||
any paid-user Pro runtime claim is made. Public GitHub release assets and the
|
||||
public `rcourtman/pulse` Docker image must be described as community builds
|
||||
where paid customers are likely to install or upgrade, and generated public
|
||||
release bodies must send Relay, Pulse Pro, and eligible legacy customers to
|
||||
`https://pulserelay.pro/download.html` for the private Pulse Pro Docker image
|
||||
or Linux archive.
|
||||
The repo-root VERSION file is part of the same governed boundary and must
|
||||
not drift as an
|
||||
unowned release-cut switch: changing the version string for a new RC or
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ The workflow auto-marks `-rc.N`/`-alpha.N`/`-beta.N` as prerelease.
|
|||
other explicit trust-migration path before testing those newer packets.
|
||||
6. For paid-user GA, run the `pulse-enterprise` Pro release workflow against the
|
||||
same Pulse ref/version, verify `pulse-pro-v...` archives exist, verify
|
||||
`bin/pulse --version` identifies `Pulse Pro (Enterprise)`, and confirm the paid
|
||||
`bin/pulse --version` identifies `Pulse Pro`, and confirm the paid
|
||||
install/upgrade docs point paid customers to the Pro artifacts or verified paid
|
||||
container image.
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ interface ProLicensePlanSectionProps {
|
|||
tone: string;
|
||||
highlightsLabel: string;
|
||||
highlights: string[];
|
||||
actionLabel?: string;
|
||||
actionUrl?: string;
|
||||
} | null;
|
||||
activationProof: {
|
||||
title: string;
|
||||
|
|
@ -55,6 +57,10 @@ interface ProLicensePlanSectionProps {
|
|||
includedExtras: string[];
|
||||
supplementalBadges: string[];
|
||||
supplementalSummary?: string;
|
||||
privateRuntimeAction?: {
|
||||
actionLabel: string;
|
||||
actionUrl: string;
|
||||
};
|
||||
};
|
||||
entitlements: {
|
||||
in_grace_period?: boolean;
|
||||
|
|
@ -109,6 +115,16 @@ export const ProLicensePlanSection: Component<ProLicensePlanSectionProps> = (pro
|
|||
<div class={`mb-4 rounded-md border p-3 text-sm ${summary().tone}`}>
|
||||
<p class="font-medium">{summary().title}</p>
|
||||
<p class="mt-1 text-xs opacity-90">{summary().body}</p>
|
||||
<Show when={summary().actionUrl && summary().actionLabel}>
|
||||
<a
|
||||
href={summary().actionUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center gap-1 mt-3 min-h-10 sm:min-h-9 rounded-md border border-current/20 px-3 py-2 text-xs font-medium hover:bg-black/5 dark:hover:bg-white/5"
|
||||
>
|
||||
{summary().actionLabel}
|
||||
</a>
|
||||
</Show>
|
||||
<Show when={summary().highlights.length > 0}>
|
||||
<div class="mt-3">
|
||||
<p class="text-[11px] uppercase tracking-wide opacity-80">
|
||||
|
|
@ -186,6 +202,18 @@ export const ProLicensePlanSection: Component<ProLicensePlanSectionProps> = (pro
|
|||
<Show when={props.currentPlanSummary.supplementalSummary}>
|
||||
{(summary) => <p class="mt-2 text-xs text-muted">{summary()}</p>}
|
||||
</Show>
|
||||
<Show when={props.currentPlanSummary.privateRuntimeAction}>
|
||||
{(action) => (
|
||||
<a
|
||||
href={action().actionUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center gap-1 mt-3 min-h-10 sm:min-h-9 rounded-md border border-border px-3 py-2 text-xs font-medium text-base-content hover:bg-surface-hover"
|
||||
>
|
||||
{action().actionLabel}
|
||||
</a>
|
||||
)}
|
||||
</Show>
|
||||
<Show when={props.currentPlanSummary.unlockedFeatures.length > 0}>
|
||||
<div class="mt-4">
|
||||
<p class="text-xs uppercase tracking-wide text-muted mb-2">
|
||||
|
|
@ -326,9 +354,7 @@ export const ProLicensePlanSection: Component<ProLicensePlanSectionProps> = (pro
|
|||
<Show
|
||||
when={props.hasLicenseDetails}
|
||||
fallback={
|
||||
<div class="text-sm text-muted">
|
||||
{getNoActiveSelfHostedActivationState().text}
|
||||
</div>
|
||||
<div class="text-sm text-muted">{getNoActiveSelfHostedActivationState().text}</div>
|
||||
}
|
||||
>
|
||||
<CommercialStatGrid items={props.commercialPlanModel.summary} />
|
||||
|
|
@ -343,9 +369,7 @@ export const ProLicensePlanSection: Component<ProLicensePlanSectionProps> = (pro
|
|||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
||||
</Show>
|
||||
|
||||
</Show>
|
||||
</Show>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -67,6 +67,22 @@ export const SelfHostedCommercialRecoverySection: Component<
|
|||
</a>
|
||||
{SELF_HOSTED_RECOVERY_PRESENTATION.helpTextAfterTerms}
|
||||
</p>
|
||||
<div class="mt-3 rounded-md border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900 p-3 text-sm text-amber-800 dark:text-amber-200">
|
||||
<p class="font-medium">
|
||||
{SELF_HOSTED_RECOVERY_PRESENTATION.privateRuntimeNotice.title}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-amber-700 dark:text-amber-300">
|
||||
{SELF_HOSTED_RECOVERY_PRESENTATION.privateRuntimeNotice.body}
|
||||
</p>
|
||||
<a
|
||||
href={SELF_HOSTED_RECOVERY_PRESENTATION.privateRuntimeNotice.actionUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="mt-2 inline-flex min-h-10 sm:min-h-9 items-center rounded px-1 text-xs font-medium text-blue-700 dark:text-blue-300 hover:underline"
|
||||
>
|
||||
{SELF_HOSTED_RECOVERY_PRESENTATION.privateRuntimeNotice.actionLabel}
|
||||
</a>
|
||||
</div>
|
||||
<Show when={props.looksLikeLegacyLicenseKey}>
|
||||
<div class="mt-3 rounded-md border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900 p-3 text-sm text-amber-800 dark:text-amber-200">
|
||||
<p class="font-medium">{SELF_HOSTED_RECOVERY_PRESENTATION.legacyNotice.title}</p>
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ describe('ProLicensePanel', () => {
|
|||
expect(screen.getByText('Pulse Pro value proof')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"These checks come from this instance's entitlement payload, not from public pricing copy.",
|
||||
"These checks come from this instance's entitlement and runtime payloads, not from public pricing copy.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText('Remote access, pairing, and push')).toBeInTheDocument();
|
||||
|
|
@ -1118,7 +1118,9 @@ describe('ProLicensePanel', () => {
|
|||
expect(proLicensePlanSectionSource).not.toContain('getTrialEndedProLicenseNotice');
|
||||
expect(proLicensePlanSectionSource).toContain('currentPlanSummary.title');
|
||||
expect(proLicensePlanSectionSource).toContain('currentPlanSummary.supplementalBadges');
|
||||
expect(proLicensePlanSectionSource).toContain('currentPlanSummary.privateRuntimeAction');
|
||||
expect(proLicensePlanSectionSource).toContain('props.activationSuccessSummary');
|
||||
expect(proLicensePlanSectionSource).toContain('summary().actionUrl');
|
||||
expect(proLicensePlanSectionSource).toContain('props.planComparisonSummary.cards.length > 0');
|
||||
expect(proLicensePlanSectionSource).toContain(
|
||||
'SELF_HOSTED_PRO_BILLING_PRESENTATION.planComparisonSectionTitle',
|
||||
|
|
@ -1145,6 +1147,7 @@ describe('ProLicensePanel', () => {
|
|||
);
|
||||
expect(selfHostedCommercialRecoverySectionSource).toContain('TERMS_DOC_URL');
|
||||
expect(selfHostedCommercialRecoverySectionSource).toContain('disclosureLabel');
|
||||
expect(selfHostedCommercialRecoverySectionSource).toContain('privateRuntimeNotice');
|
||||
expect(selfHostedCommercialRecoverySectionSource).toContain('recoverySectionTitle');
|
||||
expect(selfHostedCommercialRecoverySectionSource).not.toContain(
|
||||
'https://github.com/rcourtman/Pulse/blob/main/TERMS.md',
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@ describe('licensePresentation', () => {
|
|||
fieldLabel: 'License or Activation Key',
|
||||
activateIdleLabel: 'Activate Key',
|
||||
clearIdleLabel: 'Clear Key',
|
||||
privateRuntimeNotice: {
|
||||
title: 'Paid Docker and Linux installs use a private runtime',
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: 'https://pulserelay.pro/download.html',
|
||||
},
|
||||
legacyNotice: {
|
||||
title: 'Legacy v5 license detected',
|
||||
},
|
||||
|
|
@ -369,6 +374,10 @@ describe('licensePresentation', () => {
|
|||
title: 'Current plan: Pulse Pro',
|
||||
body: expect.stringContaining('private Pulse Pro runtime'),
|
||||
supplementalBadges: ['Pro runtime missing'],
|
||||
privateRuntimeAction: {
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: 'https://pulserelay.pro/download.html',
|
||||
},
|
||||
});
|
||||
expect(getSelfHostedActivationProofPresentation(entitlements)?.items[0]).toMatchObject({
|
||||
label: 'Pulse Pro runtime',
|
||||
|
|
@ -387,6 +396,8 @@ describe('licensePresentation', () => {
|
|||
tone: expect.stringContaining('amber'),
|
||||
body: expect.stringContaining('community runtime'),
|
||||
highlightsLabel: 'Licensed capabilities',
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: 'https://pulserelay.pro/download.html',
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ export interface SelfHostedActivationNoticeCopy {
|
|||
body: string;
|
||||
}
|
||||
|
||||
export interface LicenseExternalActionCopy {
|
||||
actionLabel: string;
|
||||
actionUrl: string;
|
||||
}
|
||||
|
||||
export interface SelfHostedRecoveryPresentation {
|
||||
disclosureLabel: string;
|
||||
disclosureDescription: string;
|
||||
|
|
@ -82,6 +87,7 @@ export interface SelfHostedRecoveryPresentation {
|
|||
helpTextBeforeTerms: string;
|
||||
helpTextAfterTerms: string;
|
||||
termsLabel: string;
|
||||
privateRuntimeNotice: SelfHostedActivationNoticeCopy & LicenseExternalActionCopy;
|
||||
activateIdleLabel: string;
|
||||
activatePendingLabel: string;
|
||||
clearIdleLabel: string;
|
||||
|
|
@ -98,6 +104,7 @@ export interface SelfHostedCurrentPlanPresentation {
|
|||
includedExtras: string[];
|
||||
supplementalBadges: string[];
|
||||
supplementalSummary?: string;
|
||||
privateRuntimeAction?: LicenseExternalActionCopy;
|
||||
}
|
||||
|
||||
export interface SelfHostedActivationProofItem {
|
||||
|
|
@ -116,6 +123,8 @@ export interface SelfHostedActivationProofPresentation {
|
|||
export interface SelfHostedActivationSuccessPresentation extends LicenseInlineNotice {
|
||||
highlightsLabel: string;
|
||||
highlights: string[];
|
||||
actionLabel?: string;
|
||||
actionUrl?: string;
|
||||
}
|
||||
|
||||
export type SelfHostedActivationSuccessSource = 'manual' | 'purchase';
|
||||
|
|
@ -156,6 +165,8 @@ const PRO_RUNTIME_REQUIRED_TIERS = new Set([
|
|||
'enterprise',
|
||||
]);
|
||||
|
||||
export const PULSE_PRO_DOWNLOAD_URL = 'https://pulserelay.pro/download.html';
|
||||
|
||||
const isActivePaidRuntimeState = (subscriptionState?: string | null): boolean => {
|
||||
const normalized = (subscriptionState || '').trim().toLowerCase();
|
||||
return normalized === 'active' || normalized === 'grace' || normalized === 'trial';
|
||||
|
|
@ -436,13 +447,13 @@ export const getSelfHostedCurrentPlanPresentation = ({
|
|||
if (runtimeMismatch) {
|
||||
supplementalBadges.push('Pro runtime missing');
|
||||
supplementalDetails.unshift(
|
||||
'Public GitHub releases and the public Docker image are community builds. Install the private Pulse Pro runtime to test Pro-only runtime hooks during the trial.',
|
||||
'Public GitHub releases and the public Docker image are community builds. Open Pulse Pro downloads with your activation key to install the private Pulse Pro runtime and test Pro-only runtime hooks during the trial.',
|
||||
);
|
||||
}
|
||||
return {
|
||||
title: `Current plan: ${planLabel} Trial`,
|
||||
body: runtimeMismatch
|
||||
? `${planLabel} trial entitlement is active, but this install is running the community runtime. Install the private Pulse Pro runtime from the paid download page to use Pro-only features.`
|
||||
? `${planLabel} trial entitlement is active, but this install is running the community runtime. Open Pulse Pro downloads with your activation key and install the private Pulse Pro runtime to use Pro-only features.`
|
||||
: unlockedFeatures.length > 0
|
||||
? `${planLabel} trial capabilities are active on this instance right now.`
|
||||
: `${planLabel} trial entitlement is being confirmed for this instance.`,
|
||||
|
|
@ -452,6 +463,14 @@ export const getSelfHostedCurrentPlanPresentation = ({
|
|||
includedExtras,
|
||||
supplementalBadges,
|
||||
supplementalSummary: supplementalDetails.join(' '),
|
||||
...(runtimeMismatch
|
||||
? {
|
||||
privateRuntimeAction: {
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: PULSE_PRO_DOWNLOAD_URL,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -477,13 +496,17 @@ export const getSelfHostedCurrentPlanPresentation = ({
|
|||
);
|
||||
return {
|
||||
title: `Current plan: ${planLabel}`,
|
||||
body: `${planLabel} is active, but this install is running the community runtime. Install the private Pulse Pro runtime from the paid download page to use Pro-only features such as Audit Log, Audit Webhooks, RBAC, and governed remediation.`,
|
||||
body: `${planLabel} is active, but this install is running the community runtime. Open Pulse Pro downloads with your activation key and install the private Pulse Pro runtime to use Pro-only features such as Audit Log, Audit Webhooks, RBAC, and governed remediation.`,
|
||||
unlockedFeaturesLabel,
|
||||
unlockedFeatures,
|
||||
includedExtrasLabel: includedExtras.length > 0 ? 'Included extras' : undefined,
|
||||
includedExtras,
|
||||
supplementalBadges,
|
||||
supplementalSummary: supplementalDetails.join(' '),
|
||||
privateRuntimeAction: {
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: PULSE_PRO_DOWNLOAD_URL,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -588,7 +611,7 @@ export const getSelfHostedActivationProofPresentation = (
|
|||
statusLabel: hasProRuntime ? 'Active' : 'Needs attention',
|
||||
detail: hasProRuntime
|
||||
? 'This install reports the private Pulse Pro runtime.'
|
||||
: 'This install reports the community runtime. Install the private Pulse Pro runtime from the paid download page; public GitHub releases and the public Docker image do not include Pro-only runtime hooks.',
|
||||
: `This install reports the community runtime. Open ${PULSE_PRO_DOWNLOAD_URL} with your activation key and install the private Pulse Pro runtime; public GitHub releases and the public Docker image do not include Pro-only runtime hooks.`,
|
||||
});
|
||||
}
|
||||
items.push(
|
||||
|
|
@ -698,13 +721,19 @@ export const getSelfHostedActivationSuccessPresentation = ({
|
|||
body:
|
||||
source === 'purchase'
|
||||
? runtimeMismatch
|
||||
? `Checkout completed and the license is active. This install is still running the community runtime, so install the private Pulse Pro runtime from the paid download page before using Pro-only features.`
|
||||
? `Checkout completed and the license is active. This install is still running the community runtime, so open Pulse Pro downloads with your activation key and install the private Pulse Pro runtime before using Pro-only features.`
|
||||
: `Checkout completed and this instance is now running ${planLabel}.`
|
||||
: runtimeMismatch
|
||||
? `The activation key was accepted. This install is still running the community runtime, so install the private Pulse Pro runtime from the paid download page before using Pro-only features.`
|
||||
? `The activation key was accepted. This install is still running the community runtime, so open Pulse Pro downloads with your activation key and install the private Pulse Pro runtime before using Pro-only features.`
|
||||
: `The activation key was accepted and this instance is now running ${planLabel}.`,
|
||||
highlightsLabel: runtimeMismatch ? 'Licensed capabilities' : 'Available now on this instance',
|
||||
highlights,
|
||||
...(runtimeMismatch
|
||||
? {
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: PULSE_PRO_DOWNLOAD_URL,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -886,6 +915,12 @@ export const SELF_HOSTED_RECOVERY_PRESENTATION: SelfHostedRecoveryPresentation =
|
|||
'Paste the Pulse v6 activation key shown on the hosted checkout success page. A backup copy is also sent by email, but the hosted success page is the primary handoff. You can also paste a legacy Pulse v5 Pro/Lifetime license key and Pulse will exchange it automatically during activation when migration is available. By activating a license, you agree to the',
|
||||
helpTextAfterTerms: '.',
|
||||
termsLabel: 'Terms of Service',
|
||||
privateRuntimeNotice: {
|
||||
title: 'Paid Docker and Linux installs use a private runtime',
|
||||
body: 'Public GitHub releases and the public Docker image are community builds. They can accept an activation key, but Pro-only runtime hooks require the private Pulse Pro Docker image or Linux archive.',
|
||||
actionLabel: 'Open Pulse Pro downloads',
|
||||
actionUrl: PULSE_PRO_DOWNLOAD_URL,
|
||||
},
|
||||
activateIdleLabel: 'Activate Key',
|
||||
activatePendingLabel: 'Activating...',
|
||||
clearIdleLabel: 'Clear Key',
|
||||
|
|
|
|||
|
|
@ -216,6 +216,12 @@ helm upgrade --install pulse oci://ghcr.io/rcourtman/pulse-chart --version ${VER
|
|||
|
||||
See the [Installation Guide](https://github.com/rcourtman/Pulse#installation) for details.
|
||||
|
||||
Paid Pulse Pro, Relay, and eligible legacy customers: public GitHub release
|
||||
assets and the public \`rcourtman/pulse\` Docker image are community builds. They do
|
||||
not include the private Pulse Pro runtime hooks. Use
|
||||
https://pulserelay.pro/download.html with your activation key to get the
|
||||
private Pulse Pro Docker image or Linux archive.
|
||||
|
||||
GUIDELINES:
|
||||
- Write plain, factual release notes. No marketing language or excitement.
|
||||
- Only mention features that exist in the FINAL code state
|
||||
|
|
|
|||
|
|
@ -349,13 +349,14 @@ class ReleasePromotionPolicyTest(unittest.TestCase):
|
|||
self.assertIn("It does not automatically check out or build `pulse-enterprise`.", runbook)
|
||||
self.assertIn("public `pulse-v...` release archives are OSS runtime artifacts", runbook)
|
||||
self.assertIn("`pulse-pro-v...` archives", runbook)
|
||||
self.assertIn("`bin/pulse --version` identifies `Pulse Pro (Enterprise)`", runbook)
|
||||
self.assertIn("`bin/pulse --version` identifies `Pulse Pro`", runbook)
|
||||
self.assertIn("Paid-user GA is part of that same release boundary", contract)
|
||||
self.assertIn(
|
||||
"the public Pulse release workflow builds OSS `pulse-v...` artifacts only",
|
||||
normalize_ws(contract),
|
||||
)
|
||||
self.assertIn("`pulse-pro-v...` archives identify `Pulse Pro (Enterprise)`", contract)
|
||||
self.assertIn("`pulse-pro-v...` archives identify `Pulse Pro`", contract)
|
||||
self.assertIn("https://pulserelay.pro/download.html", contract)
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ def build_installation_section(version: str) -> str:
|
|||
f"Update your `docker-compose.yml` to use `rcourtman/pulse:{version}`",
|
||||
"",
|
||||
"See the [Installation Guide](https://github.com/rcourtman/Pulse#installation) for complete setup instructions.",
|
||||
"",
|
||||
"Paid Pulse Pro, Relay, and eligible legacy customers: public GitHub release assets and the public `rcourtman/pulse` Docker image are community builds. They do not include the private Pulse Pro runtime hooks. Use https://pulserelay.pro/download.html with your activation key to get the private Pulse Pro Docker image or Linux archive.",
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ Old metadata section.
|
|||
self.assertEqual(body.count("## Installation"), 1)
|
||||
self.assertEqual(body.count("## Promotion Metadata"), 1)
|
||||
self.assertIn("docker pull rcourtman/pulse:6.0.0-rc.2", body)
|
||||
self.assertIn(
|
||||
"public GitHub release assets and the public `rcourtman/pulse` Docker image are community builds",
|
||||
body,
|
||||
)
|
||||
self.assertIn("https://pulserelay.pro/download.html", body)
|
||||
self.assertIn("- Rollback target: v5.1.28", body)
|
||||
|
||||
def test_current_release_packets_use_pulse_mobile_handoff_copy(self) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue