From a6437f885f47cf65e24b5f41c2c65cd0ca0ce5cd Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Sun, 11 Oct 2026 21:09:21 +0100 Subject: [PATCH] Keep native maintenance checks compiling and command facts clean Completed PR2825 CI reports Windows Unix-type compilation failures and three Prettier fixture failures. Compile the existing Linux-only MSP daemon fixture only on Linux and format the unchanged frontend assertions. Separate successful CLI stdout from retained stderr diagnostics so Compose warnings cannot corrupt container identities, ports or bootstrap facts; add three executable controls without changing deadlines or acceptance gates. Change-source: pulse-maintainer --- .../subsystems/deployment-installability.md | 17 +++++++++++ .../__tests__/agentTokenFileGuide.test.ts | 13 +++++++-- .../docs/__tests__/alertOffFAQ.test.ts | 23 +++++++++++---- .../src/utils/__tests__/docsLinks.test.ts | 4 +-- .../installtests/provider_msp_startup_test.go | 29 ++++++++++++++++--- 5 files changed, 70 insertions(+), 16 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/deployment-installability.md b/docs/release-control/v6/internal/subsystems/deployment-installability.md index cc76794db9..53353260fd 100644 --- a/docs/release-control/v6/internal/subsystems/deployment-installability.md +++ b/docs/release-control/v6/internal/subsystems/deployment-installability.md @@ -7781,3 +7781,20 @@ or failed parsers, failed transport with a plausible body, redirects, pins and downgrade refusal. Existing extracted-function tests include the shared selector. These are source-level selection controls, not native installation, published release acceptance or a repair to a third-party community helper. + + +### Combined-batch native fixture reconciliation (11 October 2026) + +The real provider-MSP startup fixture is Linux-only at compile time, matching +its existing Linux transport admission. Its cloud-control-plane import must not +pull Unix filesystem types into Windows installer test compilation. Windows +installer and lifecycle tests remain enabled; the startup fixture still runs in +the Linux process proof and hosted Compose job. + +Successful command stdout alone supplies container identities, published ports +and bootstrap facts. Stderr warnings remain logged evidence, never arguments to +the next Docker command. Failure diagnostics retain both streams and the original +nonzero exit. `TestProviderMSPStartupCommandSeparatesDiagnostics` checks three +consumer shapes with controlled successful stderr; it is not Docker acceptance. +Hosted mounted-secret/readiness/persistence/refusal/cleanup checks remain required. +Frontend fixture reformatting retains all assertions and changes no runtime UI. diff --git a/frontend-modern/src/features/docs/__tests__/agentTokenFileGuide.test.ts b/frontend-modern/src/features/docs/__tests__/agentTokenFileGuide.test.ts index 73d72364e2..eeff5e1ae2 100644 --- a/frontend-modern/src/features/docs/__tests__/agentTokenFileGuide.test.ts +++ b/frontend-modern/src/features/docs/__tests__/agentTokenFileGuide.test.ts @@ -25,7 +25,9 @@ describe('agent token-file help in the shipped Markdown renderer', () => { expect(link?.getAttribute('href')).toBe(`#${id}`); expect(link?.hasAttribute('data-doc-link')).toBe(false); expect(link?.hasAttribute('target')).toBe(false); - expect(article.querySelector(`#${id}`)?.textContent).toBe('Token-file format is not shell syntax'); + expect(article.querySelector(`#${id}`)?.textContent).toBe( + 'Token-file format is not shell syntax', + ); expect(guide).toBe( readFileSync(path.join(repoRoot, 'frontend-modern/public/docs/UNIFIED_AGENT.md'), 'utf8'), ); @@ -55,10 +57,15 @@ describe('agent token-file help in the shipped Markdown renderer', () => { ].entries()) { expect(rows[index].textContent).toContain(phrase); } - const text = parts.map((element) => element.textContent).join(' ').replace(/\s+/g, ' '); + const text = parts + .map((element) => element.textContent) + .join(' ') + .replace(/\s+/g, ' '); expect(text).toContain('not the value, length, hint, screenshot or file'); expect(text).toContain('Do not print, source, upload or edit the installed token file'); expect(text).toContain('not proof of accepted reporting'); - expect(parts.some((element) => element.matches('pre') || element.querySelector('pre'))).toBe(false); + expect(parts.some((element) => element.matches('pre') || element.querySelector('pre'))).toBe( + false, + ); }); }); diff --git a/frontend-modern/src/features/docs/__tests__/alertOffFAQ.test.ts b/frontend-modern/src/features/docs/__tests__/alertOffFAQ.test.ts index 75c24c7492..e481b4523e 100644 --- a/frontend-modern/src/features/docs/__tests__/alertOffFAQ.test.ts +++ b/frontend-modern/src/features/docs/__tests__/alertOffFAQ.test.ts @@ -5,7 +5,8 @@ import { describe, expect, it } from 'vitest'; import { renderDocMarkdown } from '../docMarkdown'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../..'); -const guide = (name: string): string => readFileSync(path.join(root, 'frontend-modern/public/docs', `${name}.md`), 'utf8'); +const guide = (name: string): string => + readFileSync(path.join(root, 'frontend-modern/public/docs', `${name}.md`), 'utf8'); const article = (name: string): HTMLElement => { const element = document.createElement('article'); element.innerHTML = renderDocMarkdown(guide(name), name); @@ -15,7 +16,11 @@ const section = (): HTMLElement => { const heading = article('FAQ').querySelector('#can-i-disable-alerts-for-specific-metrics'); expect(heading).not.toBeNull(); const element = document.createElement('section'); - for (let next = heading!.nextElementSibling; next && !/^H[1-6]$/.test(next.tagName); next = next.nextElementSibling) { + for ( + let next = heading!.nextElementSibling; + next && !/^H[1-6]$/.test(next.tagName); + next = next.nextElementSibling + ) { element.appendChild(next.cloneNode(true)); } return element; @@ -28,11 +33,14 @@ describe('shipped alert Off FAQ', () => { expect(text).toContain('not every default has a per-resource control'); expect(text).toContain('save, then reopen the editor'); expect(element.querySelectorAll('li')).toHaveLength(4); - for (const phrase of ['does not hide its readings, stop collection', - 'explicit threshold can remain active', 'Already queued notifications', + for (const phrase of [ + 'does not hide its readings, stop collection', + 'explicit threshold can remain active', + 'Already queued notifications', 'Patrol findings are separate from threshold alerts', 'when the corresponding alert default is Off', - 'Do not induce an alert, send another Test or retry the queue']) { + 'Do not induce an alert, send another Test or retry the queue', + ]) { expect(text).toContain(phrase); } expect(element.querySelector('pre')).toBeNull(); @@ -42,7 +50,10 @@ describe('shipped alert Off FAQ', () => { it('routes the two independent warning paths to real shipped headings', () => { const links = [...section().querySelectorAll('a')]; expect(links).toHaveLength(2); - expect(links.map((link) => link.textContent)).toEqual(['how Patrol works', 'ordinary notification checks']); + expect(links.map((link) => link.textContent)).toEqual([ + 'how Patrol works', + 'ordinary notification checks', + ]); for (const link of links) { const [name, fragment] = link.getAttribute('href')!.replace('/docs/', '').split('#'); expect(article(name).querySelector(`#${fragment}`)).not.toBeNull(); diff --git a/frontend-modern/src/utils/__tests__/docsLinks.test.ts b/frontend-modern/src/utils/__tests__/docsLinks.test.ts index 729b1c65b8..411703e438 100644 --- a/frontend-modern/src/utils/__tests__/docsLinks.test.ts +++ b/frontend-modern/src/utils/__tests__/docsLinks.test.ts @@ -657,9 +657,7 @@ describe('docsLinks', () => { /if !reportCallerMayUseAI\(ctx\) \{\s*return nil, nil, h\.resolveExistingFindings\(ctx\)\s*\}\s*return h\.narratorResolver\(ctx\)/, ); expect(resolver.match(/h\.narratorResolver\(/g)).toHaveLength(1); - expect(fleet).toMatch( - /_, fleetNarrator, findings := h\.resolveNarrator\(ctx\)/, - ); + expect(fleet).toMatch(/_, fleetNarrator, findings := h\.resolveNarrator\(ctx\)/); expect(fleet.match(/h\.resolveNarrator\(/g)).toHaveLength(1); }); diff --git a/scripts/installtests/provider_msp_startup_test.go b/scripts/installtests/provider_msp_startup_test.go index 47ece0c5c5..5a525d1aef 100644 --- a/scripts/installtests/provider_msp_startup_test.go +++ b/scripts/installtests/provider_msp_startup_test.go @@ -1,3 +1,5 @@ +//go:build linux + package installtests import ( @@ -265,12 +267,17 @@ func startupCommand(t *testing.T, env []string, dir, program string, args ...str defer cancel() cmd := exec.CommandContext(ctx, program, args...) cmd.Dir, cmd.Env = dir, env - output, err := cmd.CombinedOutput() - if err != nil { + var stdout, stderr bytes.Buffer + cmd.Stdout, cmd.Stderr = &stdout, &stderr + if err := cmd.Run(); err != nil { // Environment and licence contents are never diagnostic output. - t.Fatalf("%s command failed: %v\n%s", filepath.Base(program), err, output) + t.Fatalf("%s command failed: %v\n%s\n%s", filepath.Base(program), err, stdout.String(), stderr.String()) } - return string(output) + if stderr.Len() != 0 { + // Compose warnings are evidence, not container IDs, ports or CLI facts. + t.Logf("%s diagnostics: %s", filepath.Base(program), stderr.String()) + } + return stdout.String() } func startupRefusal(t *testing.T, env []string, dir, want, program string, args ...string) { @@ -384,3 +391,17 @@ func startupFacts(output string) map[string]string { } return facts } + +// Compose may warn on stderr about optional unset variables even when it +// succeeds. Never pass those diagnostics as the next docker exec identity. +func TestProviderMSPStartupCommandSeparatesDiagnostics(t *testing.T) { + for _, value := range []string{"synthetic-container-id", "127.0.0.1:8443", "provider_msp_bootstrap_ok=true"} { + t.Run(value, func(t *testing.T) { + output := startupCommand(t, []string{"PATH=" + os.Getenv("PATH")}, t.TempDir(), "sh", "-c", + `printf '%s\n' "$1"; printf 'optional variable warning\n' >&2`, "fixture", value) + if output != value+"\n" { + t.Fatalf("command facts include diagnostics: %q", output) + } + }) + } +}