OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / unit / ship-handoff-update.test.js

117 lines · javascript ref:
import test from 'brittle'
import {
  formatWorktreeSummary,
  parseReleaseBlockers,
  renderShipHandoff
} from '../../scripts/update-ship-handoff.mjs'

const BLOCKER_STDERR = `Release distribution preflight failed:
- UMBREL_STORE_TOKEN must be a GitHub token without whitespace or control characters
- UMBREL_OFFICIAL_PR_TOKEN must be a GitHub token without whitespace or control characters
- UMBREL_OFFICIAL_FORK must be a GitHub owner/umbrel-apps fork slug with a normal owner name and must not be getumbrel/umbrel-apps
- STARTOS_REGISTRY_URL must be a public https URL without embedded credentials, query strings, fragments, or reserved/local hostnames

Repair path:
- Generate the targeted issue #120 repair file outside the repo: npm run release:write-secret-template -- --issue-120-repair --out /private/tmp/hiverelay-release-secrets.env
- Validate without publishing: npm run release:check-distribution-env -- --issue-120-repair --env-file /private/tmp/hiverelay-release-secrets.env
`

test('ship handoff updater parses release blocker facts from preflight stderr', (t) => {
  t.alike(parseReleaseBlockers(BLOCKER_STDERR), [
    'UMBREL_STORE_TOKEN must be a GitHub token without whitespace or control characters',
    'UMBREL_OFFICIAL_PR_TOKEN must be a GitHub token without whitespace or control characters',
    'UMBREL_OFFICIAL_FORK must be a GitHub owner/umbrel-apps fork slug with a normal owner name and must not be getumbrel/umbrel-apps',
    'STARTOS_REGISTRY_URL must be a public https URL without embedded credentials, query strings, fragments, or reserved/local hostnames'
  ])
})

test('ship handoff updater renders git and preflight-derived facts', (t) => {
  const doc = renderShipHandoff({
    date: '2026-06-26',
    ref: '683ef0a',
    refIsCurrentCheckout: false,
    branch: 'main',
    shortSha: '683ef0a',
    commitSubject: 'docker: pin entrypoint and storage env (#136)',
    packageName: 'p2p-hiverelay-monorepo',
    packageVersion: '0.20.2',
    worktree: {
      clean: true,
      changedPaths: 0,
      statusLine: 'main...origin/main'
    },
    prNumber: '136',
    prCheckNames: ['audit', 'lint', 'unit', 'integration', 'Bare tests'],
    testRun: '28249805132',
    dockerRun: '28249805122',
    issueNumber: '120',
    preflightRun: '28244297762',
    preflightUrl: 'https://github.com/bigdestiny2/P2P-Hiverelay/actions/runs/28244297762',
    preflightHead: 'a8eb77df74d4e245b8577a50435a00be04786d96',
    preflightBranch: 'main',
    preflightCreatedAt: '2026-06-26T14:25:04Z',
    preflightState: 'completed/failure',
    supersededPreflightSuccess: '28238930607',
    supersededPreflightSuccessHead: '1ffffe6d5ed8c6af310219409e59ef2101812ed7',
    repo: 'bigdestiny2/P2P-Hiverelay',
    releaseBlockers: parseReleaseBlockers(BLOCKER_STDERR),
    releaseDefaults: {
      full: 'both',
      prerelease: 'none'
    }
  })

  t.ok(doc.includes('Generated by `npm run docs:update-ship-handoff`'))
  t.ok(doc.includes('HEAD inspected: `683ef0a`'))
  t.ok(doc.includes('Commit subject: `docker: pin entrypoint and storage env (#136)`'))
  t.ok(doc.includes('Post-merge main Test run: `28249805132` passed.'))
  t.ok(doc.includes('Release distribution preflight run: `28244297762` (issue #120).'))
  t.ok(doc.includes('Run URL: https://github.com/bigdestiny2/P2P-Hiverelay/actions/runs/28244297762'))
  t.ok(doc.includes('Latest checked preflight: state `completed/failure`, head `main@a8eb77d`, created `2026-06-26T14:25:04Z`.'))
  t.ok(doc.includes('Earlier passing preflight `28238930607` at `1ffffe6` is superseded by this newer failure.'))
  t.ok(doc.includes('UMBREL_STORE_TOKEN must be a GitHub token without whitespace or control characters'))
  t.ok(doc.includes('UMBREL_OFFICIAL_PR_TOKEN must be a GitHub token without whitespace or control characters'))
  t.ok(doc.includes('UMBREL_OFFICIAL_FORK must be a GitHub owner/umbrel-apps fork slug'))
  t.ok(doc.includes('Full releases with no explicit channel resolve to `both`.'))
  t.ok(doc.includes('Prereleases with no explicit channel resolve to `none`.'))
  t.ok(doc.includes('node --test test/unit/ecosystem-consumers.test.js'))
  t.ok(doc.includes('direct-consumer default-pinning'))
  t.ok(doc.includes('before any image is published'))
  t.ok(doc.includes('npm run ecosystem:sync -- --check'))
  t.ok(doc.includes('npm run audit:ecosystem-consumers'))
  t.ok(doc.includes('known app defaults and linked'))
  t.ok(doc.includes('lockfile metadata plus versioned source markers'))
  t.ok(doc.includes('StartOS package proof is also release-image gated'))
  t.ok(doc.includes('ghcr.io/bigdestiny2/p2p-hiverelay:0.20.2'))
  t.ok(doc.includes('HIVERELAY_IMAGE_DIGEST=sha256:<digest> npm run startos:verify'))
  t.ok(doc.includes('Confirm the release GHCR tag resolves to a multi-arch digest'))
  t.ok(doc.includes('npm run release:write-secret-template -- \\'))
  t.ok(doc.includes('--issue-120-repair \\'))
  t.ok(doc.includes('npm run release:check-distribution-env -- \\'))
  t.ok(doc.includes('npm run release:apply-github-secrets -- \\'))
  t.ok(doc.includes('--env-file /private/tmp/hiverelay-release-secrets.env \\'))
  t.absent(doc.includes('--channel both \\'))
  t.ok(doc.includes('The template command writes placeholders only for the four current issue #120'))
  t.ok(doc.includes('The check command validates the candidate file locally without publishing.'))
  t.ok(doc.includes('writing only those four'))
  t.ok(doc.includes('Masked release values are sent through `gh secret set` stdin'))
  t.ok(doc.includes('The same preflight did not report malformed `FLEET_SSH_PRIVATE_KEY`'))
  t.absent(doc.includes('Put corrected release values in a local candidate env file outside the repo'))
  t.absent(doc.includes('malformed GitHub secret/variable values'))
  t.absent(doc.includes('`NPM_TOKEN`'))
})

test('ship handoff updater reports actual generator checkout when snapshot ref differs', (t) => {
  t.is(formatWorktreeSummary({
    branch: 'main',
    ref: '683ef0a',
    refIsCurrentCheckout: false,
    shortSha: '683ef0a',
    worktree: {
      clean: false,
      changedPaths: 3,
      statusLine: 'audit/lease-api-durable-config'
    }
  }), 'clean snapshot (`main@683ef0a`)')
})