Skip to content

πŸ”§ chore(release): v1.5.0-rc.36 β€” #321 tag-pin + maintenance-window fixes + CodeQL-clean docs deploy#435

Merged
scttbnsn merged 11 commits into
mainfrom
release/v1.5.0-rc.36
Jun 15, 2026
Merged

πŸ”§ chore(release): v1.5.0-rc.36 β€” #321 tag-pin + maintenance-window fixes + CodeQL-clean docs deploy#435
scttbnsn merged 11 commits into
mainfrom
release/v1.5.0-rc.36

Conversation

@scttbnsn

Copy link
Copy Markdown
Contributor

v1.5.0-rc.36

Consolidated RC carrying the Discussion #321 fixes, the experimental edge-agent rename, and the website-deploy hotfix. All changes verified by a 9-agent adversarial verification pass (GO, 0 blockers/0 majors) and the full coverage gate (100% app + ui).

#321 β€” Fix 1: pinned specific-precision tags are digest-only by default

A fully-specified semver tag (β‰₯3 numeric segments, e.g. image:v1.13.3) no longer silently climbs to a newer version (the reported v1.13.3 β†’ v1.46.1). getTagCandidates returns an empty candidate list (digest-only) for specific-precision tags. Opt back into semver climbing with dd.tag.include or dd.tag.family=loose. Floating tags (latest, 16-alpine) and 1–2-segment partials are unaffected.

#321 β€” Fix 2: maintenance window gates auto-update execution

The post-update fast resync (maybeFastResyncAfterUpdate) now honors the maintenance window the same way watchFromCron does β€” closing the path where a triggered resync applied an update at 21:52 outside a 0-10 4 * * * window. Manual UI/API updates remain immediate by design. (Window enforcement is at scan time in the Docker watcher; the maintenanceWindowOpen eligibility field is documented as UI-display scaffolding, not an auto-dispatch gate.)

Experimental Portwing edge-agent mode (rename from "lookout")

Renames the experimental edge-agent feature lookout β†’ portwing across code, API (/api/v1/portwing/*, portwing/1.0 subprotocol), env (DD_EXPERIMENTAL_PORTWING), and docs. Zero stale lookout references remain in tracked source.

Website deploy hotfix (CodeQL-clean)

The changelog MDX generator stripped HTML comments with a single-pass regex that CodeQL flags as js/incomplete-multi-character-sanitization (high) β€” which the code_scanning ruleset blocks merge on. Replaced with a complete indexOf scan (byte-identical output, linear-time). This unblocks the stalled getdrydock.com production deploy (broken since the maintainer upgrade-note comment landed in #426).

Verification

  • 9 independent adversarial verifiers across all fixes β†’ GO, 0 blockers, 0 majors
  • Full coverage gate: 100% (app + ui); pre-push gate (coverage + build + e2e) green
  • Verifier-flagged minors addressed: suffixed/4-segment pin tests, honest JSDoc, tightened tautological assertion

Cut

After merge, release-cut.yml is dispatched with release_tag=v1.5.0-rc.36 (package versions stay 1.5.0; RC suffix is tag-only).

Closes the rc.35 regressions reported in Discussion #321. Supersedes hotfix PR #434 (same docs fix, CodeQL-clean here).

scttbnsn added 9 commits June 15, 2026 08:17
…rtwing

- env flag DD_EXPERIMENTAL_LOOKOUT β†’ DD_EXPERIMENTAL_PORTWING (default off, zero footprint when unset)
- WS endpoint /api/v1/lookout/ws β†’ /api/v1/portwing/ws; subprotocol lookout/1.0 β†’ portwing/1.0
- key registry /api/v1/lookout/keys β†’ /api/v1/portwing/keys
- rename app/api/lookout*.ts β†’ portwing*.ts, openapi path module, and api docs page
- update EdgeAgentAdapter, agent-keys store, configuration, OpenAPI index, CHANGELOG [Unreleased], README, docs meta
sync-docs.mjs copied CHANGELOG.md verbatim into the fumadocs MDX source.
The <!-- ... --> maintainer note in the [Unreleased] section is valid in the
GitHub-rendered CHANGELOG but MDX v3 rejects HTML comments, failing the
Turbopack build (drydock-website production + preview deploys erroring since
2026-06-13). Strip HTML comments during generation (they are not published-docs
content) and collapse the resulting blank-line gap. CHANGELOG.md stays
GitHub-valid and unchanged.
Resolves #321 (Fix 1): containers tagged with a fully-specified
semver (β‰₯3 segments, tagPrecision='specific') were silently
climbing to newer versions. Gate getTagCandidates to return an
empty tag list (digest-only path) for 'specific' tags unless the
user opts in via dd.tag.include or dd.tag.family=loose.
Resolves #321 (Fix 2): auto-triggered container updates were applied
outside the configured maintenance window.

- Gate maybeFastResyncAfterUpdate with the same window check used in
  watchFromCron β€” debug-log and return early when the window is closed
- Add maintenance-window-closed UpdateBlocker (soft, auto-updates only)
  with maintenanceWindowOpen context field in computeUpdateEligibility;
  manual UI/API updates remain ungated
- Update HARD_BLOCKER_STATUS in request-update.ts to keep exhaustive map
- Mirror UpdateBlockerReason + BLOCKER_SEVERITY in UI types and utils
Add tests for all previously-uncovered branches and functions:
- specific-tag pin gate without a debug function
- excludeTags regex compile failure (null safeRegExp)
- over-length regex pattern (>1024 chars)
- no-prefix candidate warning when tag starts with a digit
- undefined/null tagFamily falling back to strict
- invalid tagFamily value warning + fallback
- logSemverCandidateFilterStats no-debug-function early return
- filterSemverOnly callback (non-semver tag + includeTags with semver candidates)
- isSemverFamilyMatch with null referenceShape
- afterSemver > 0 + afterFamily == 0 family warning path

Fixes: #321
- specific-tag pin: containers with 3-segment semver now digest-only by default
- maintenance-window gate: now applies at update execution, not just detection
…ncomplete-sanitization

Replace the single-pass /<!--[\s\S]*?-->/g regex in the changelog MDX
generator with a complete indexOf-based scan. CodeQL flags the regex
as js/incomplete-multi-character-sanitization (high) because a single
replace can leave a residual "<!--" when comment spans abut; the
ruleset's code_scanning rule blocks merge on high+ alerts, so the
regex would block the rc.36 -> main PR exactly as it did on #434.

The index scan removes every complete <!-- ... --> span and leaves any
unterminated trailing "<!--" untouched. Output is byte-identical for
the well-formed maintainer note in CHANGELOG.md (verified: 0 residual
comments in the generated MDX). Build-time docs generation only; input
is the repo's own trusted CHANGELOG, no untrusted-input/XSS surface.
…nce-window JSDoc

Address adversarial-verifier findings on the rc.36 #321 fixes:
- Add getTagCandidates gate tests for the most common real-world pinned
  patterns β€” suffixed 3-segment (1.13.3-bookworm) and 4-segment
  (1.2.3.4) β€” asserting digest-only (tags === []), no semver climb.
- Rewrite the maintenanceWindowOpen JSDoc to be accurate: no auto-trigger
  dispatch path sets it; window enforcement is done at scan time in the
  Docker watcher. Prevents a future-maintainer trap.
- Tighten a tautological assertion to an exact-array check.
…lidator

Convert the accumulated [Unreleased] section into the dated
## [1.5.0-rc.36] release section so scripts/extract-changelog-entry.mjs
(invoked by release-cut.yml) finds the entry for tag v1.5.0-rc.36.

This RC ships:
- #321 Fix 1: fully-pinned specific-precision tags are digest-only by
  default (no surprise semver climb); opt in via dd.tag.include or
  dd.tag.family=loose.
- #321 Fix 2: maintenance window gates the post-update fast resync so
  auto-updates are not applied outside the window.
- Experimental Portwing edge-agent mode (PR #429/#430).
- Self-update overlay flicker fix (#425).
- CodeQL-clean changelog MDX generation (unblocks the website deploy).
@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
drydock-website Ready Ready Preview, Comment Jun 15, 2026 2:23pm
drydockdemo-website Ready Ready Preview, Comment Jun 15, 2026 2:23pm

@biggest-littlest biggest-littlest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. #321 rc.35 regressions fixed (specific-tag digest-only default + maintenance-window resync gate), portwing rename clean, CodeQL-clean changelog generator. Verified by 9-agent adversarial pass (GO) + 100% coverage.

ALARGECOMPANY
ALARGECOMPANY previously approved these changes Jun 15, 2026

@ALARGECOMPANY ALARGECOMPANY left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second code-owner approval. Full pre-push gate green (coverage + build + e2e); release heading validated against extract-changelog-entry.mjs.

…gate

The #321 fix gates bare specific (3-segment) tags to digest-only updates by
default. The Playwright 'actions tab' test opens Nginx (Hooked) and asserts an
Update Now / Force Update control renders, which requires an available update.
Without an include the container is correctly 'no-update-available' (hard
blocker β†’ disabled Blocked button), so the test counted zero controls.

Add dd.tag.include=^1\.\d+\.\d+-alpine$ β€” the explicit family opt-in that
survives the gate (identical to the edge-nginx fixture) β€” restoring the
'has an update' precondition main relied on via the buggy climb, now via a
legitimate mechanism. Net update-state for all other specs is unchanged.

Refs: #321
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

βœ… All modified and coverable lines are covered by tests.

πŸ“’ Thoughts on this report? Let us know!

…ab test

The actions-tab Playwright test opens openAnyContainerDetail(), which is supposed
to open Nginx (Hooked) but cannot: its matcher /\bNginx \(Hooked\)\b/ can never
match a name ending in ')' (no word boundary after the paren), so the helper falls
through to the next known container β€” Redis Cache (redis:7.2.0-alpine).

Redis Cache had no include, so the #321 fix correctly gates it to digest-only β†’
no-update-available hard blocker β†’ disabled Blocked button, and the test counted
zero Update Now/Force Update controls. Add dd.tag.include=^7\.\d+\.\d+-alpine$ so
it climbs within its family and shows an update β€” exactly the state main relied on
via the buggy climb, now via a legitimate mechanism. Verified the opened container
and regex behavior against the failed run's error-context snapshot.

Refs: #321

@biggest-littlest biggest-littlest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving after fixture commits (445c256). E2E fixture only β€” Redis Cache opt-in to family climbing so the actions-tab test's opened container has an update post-#321 gate.

@ALARGECOMPANY ALARGECOMPANY left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving after fixture commits (445c256). Test-fixture-only change; verified against the failed run's snapshot.

@scttbnsn scttbnsn merged commit 423b6b0 into main Jun 15, 2026
23 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants