Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/tests/readme-translations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ const requiredFragments = [
'v1.6.0-rc.12',
'v1.6.0-rc.11',
'./CHANGELOG.md#160--2026-08-11',
'./CHANGELOG.md#170-rc1--2026-08-13',
'./CHANGELOG.md#170-rc1--2026-08-14',
'Portwing 0.9.0+',
'Standard HTTP',
'`DD_EXPERIMENTAL_PORTWING=false`',
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.7.0-rc.1] — 2026-08-13
## [1.7.0-rc.1] — 2026-08-14

### Added

- **Edge Portwing polling cadence is configurable** ([#688](https://github.com/CodesWhat/drydock/issues/688)). `DD_PORTWING_POLL_INTERVAL` sets the controller-owned Edge container-refresh interval in positive integer seconds; the authenticated welcome frame and reported agent metadata use the same value, while absent or invalid values retain the 300-second default.
- **Installable PWA support** (Roadmap Phase 6.9). Drydock is now an installable Progressive Web App via `vite-plugin-pwa`: a web app manifest (`Drydock`, standalone display, theme/background color matched to the One Dark default `--dd-bg`, 192/512 icons plus dedicated maskable variants with safe-zone padding) and an auto-updating service worker (`registerType: 'autoUpdate'`) that precaches the SPA shell so the dashboard boots offline. `/api/**` is explicitly excluded from all service-worker handling — no navigation fallback, no runtime caching — so a live dashboard never serves stale API data from cache; those requests always hit the network and surface a normal error if it's unreachable. A dismissible install banner (new `InstallBanner` component, following the existing `AnnouncementBanner` pattern) listens for the browser's `beforeinstallprompt` event and offers a one-click install, with the dismissal persisted under a versioned localStorage key. iOS home-screen install is supported via `apple-mobile-web-app-capable` and the existing `apple-touch-icon`. The backend's static UI server now serves `sw.js` with `Cache-Control: no-cache` so a new deploy is never masked by a browser-cached service worker script.
- **Clickable port links in the container list and detail views.** Each host-published port in a container's `details.ports` now renders as a link (opened in a new tab, `rel="noopener noreferrer"`) instead of inert text — in the side panel, the full-page detail tabs, and new opt-in "Ports" columns/rows in the table and card views. The scheme is auto-detected from the container-side port (`443`/`8443` → `https://`, everything else → `http://`); the link target host prefers the port's own bound `HostIp` when it's a real address (not `0.0.0.0`/`::`/`::0`), falling back to the agent's configured host for agent-watched containers, or the browser's own hostname otherwise. Internal-only (unpublished) ports still render as plain text. A new `dd.port.label` container label lets you attach a friendly name to a specific port (`dd.port.label=80=Web UI,443=Admin Console`) shown in place of the raw `hostPort->containerPort/protocol` mapping.
- **Container uptime, with a live-refreshing display.** The existing `details.startedAt` field (from Docker's `State.StartedAt`) now also drives an opt-in "Uptime" tooltip showing the exact start timestamp in the container list, and a live "Up …" indicator in the card view's footer — both refresh on a timer and update immediately on SSE container-state changes, matching the full-page detail view's existing uptime display.
Expand Down Expand Up @@ -42,6 +43,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- **Edge exec completion reasons now reach the controller-side consumer** ([#635](https://github.com/CodesWhat/drydock/issues/635)). String `exec_end.reason` values are forwarded through the internal `startExec` end callback; sessions are removed before consumer code runs, and a throwing callback cannot leak state or stop disconnect cleanup.
- **Controller-owned Portwing containers now use the controller's configured registry identity before native checks** ([#687](https://github.com/CodesWhat/drydock/issues/687)). Complete Docker-transport inventory and event records are normalized to the canonical registry name, URL, credentials, and image identity, so watch-now no longer delegates registry work to Portwing's intentional 501 stub; traditional agents and partial events keep their existing behavior.
- **Manifest `created` metadata failures no longer become successful missing dates** ([#606](https://github.com/CodesWhat/drydock/issues/606)). Exhausted 4xx, 5xx, network, and non-object failures now propagate the original failure; only 301/302/303/307/308 responses on optional manifest/blob metadata may omit `created`, preserving an already resolved digest while redirect following stays disabled.
- **Demo site favicon now matches the refreshed branding.** The v1.5.1 brand refresh (#439) moved the website to the cropped whale "headshot" icon and the app UI followed, but demo.getdrydock.com kept showing the old full-body whale: its stale `favicon.svg` — which modern browsers preferred over the PNGs — was never replaced. The demo now ships the same headshot icon set as the website and app UI, the `favicon.svg` is removed, and the icon links carry a `?v=2` cache-buster so browsers re-fetch instead of serving the aggressively cached old icon. (#689, forward-ported in #690)
- **Audit nav icon no longer renders blank for the Lucide icon-library preference, and the icon bundle no longer silently drops aliased or renamed icons at image build time.** PR [#668](https://github.com/CodesWhat/drydock/pull/668)'s icon-bundle regeneration against tabler 1.2.38 dropped `lucide:history` from `ui/src/boot/icon-bundle.json` because the installed `@iconify-json/lucide` (1.2.121) demoted `history` to an alias of `rotate-ccw-clock`; `ui/scripts/extract-icons.mjs`'s bundler only ever looked up plain icon entries, never aliases, so every image built since that pin shipped without it (no network fallback, since the iconify API module is offline-only). The extractor now resolves alias chains (parent-following, depth-capped at 5), refusing any alias that carries a `rotate`/`hFlip`/`vFlip` transform the body-only bundle can't represent. `ui/src/icons.ts`'s `iconMap.audit.lucide` is repointed to `lucide:rotate-ccw-clock` directly (the same clock-with-counter-clockwise-arrow concept `fa6-solid:clock-rotate-left`/`ph:clock-counter-clockwise` already use for the same entry) rather than relying on alias resolution for that one. A bundle-consistency sweep against the currently installed iconsets turned up more references that never resolved against the locked collections at all: `iconoir:history` → `iconoir:clock-rotate-right`, `iconoir:gitlab` → `iconoir:gitlab-full`, `iconoir:stack` → `iconoir:multiple-pages`, `lucide:more-vertical` → `lucide:ellipsis-vertical`, `iconoir:key-alt` → `iconoir:key`, plus four `fa6-brands:*` icons that were never bundled because `@iconify-json/fa6-brands` (now exact-pinned as a devDependency) was missing from `ui/package.json` entirely — all fixed or backfilled so every `<library>:<icon>` reference in `iconMap` now resolves. Two guard tests now cover this class of regression: `ui/tests/icons.spec.ts` asserts every `iconMap` entry has a matching `icon-bundle.json` key, and `ui/tests/boot/icon-bundle.spec.ts` independently asserts every `'prefix:name'` reference found in `icons.ts` exists in the generated bundle with a body.
- **Compose-derived dependency detection now works when drydock itself runs in a container (v1.7, [discussion #219](https://github.com/CodesWhat/drydock/discussions/219)).** `resolveComposeDependsOn` (`app/dependencies/compose-dependency-resolver.ts`) read a container's compose file at its host-side label path — which doesn't exist inside drydock's own container filesystem unless a bind mount happens to line up 1:1 — so most non-trivial layouts silently detected zero dependencies. Host compose-file paths are now translated through drydock's own bind mounts (reusing the existing Docker Compose trigger's translation logic, `ComposePathBindMounts.ts`, cached per Docker API instance) before being read; when none of a container's configured compose file paths can be translated and read, that now surfaces as a single warning naming every path tried instead of a silent empty result.
Expand Down
2 changes: 1 addition & 1 deletion README.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Weitere Informationen zu Docker Compose, Socket-Sicherheit, Reverse-Proxy und al
- **Sicherheits- und Lifecycle-Härtung** – Authentifizierung, Agent-Anfragen, Protokolle, WebSockets und Registry-Anfragen sind explizit begrenzt; vertrauliche Befehls- und Hook-Werte werden redigiert; die Home-Assistant-Erkennung synchronisiert sich nach dem Start neu und beendet Provider-Arbeit ohne veraltete Veröffentlichungen. ([#708](https://github.com/CodesWhat/drydock/issues/708))
- **First-Party-Star-History** – der Same-Origin-Provider `/api/star-history` stellt Diagramme für die freigegebenen Repositories Drydock, Sockguard und Portwing ohne Drittanbieter-Tracker bereit.

Vollständige Versionshinweise in [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13).
Vollständige Versionshinweise in [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Consulte la [guía de inicio rápido](https://getdrydock.com/docs/quickstart) pa
- **Refuerzo de seguridad y ciclo de vida**: la autenticación, las solicitudes de agentes, los registros, WebSockets y las solicitudes a registros tienen límites explícitos; se ocultan valores sensibles de comandos y hooks; el descubrimiento de Home Assistant se resincroniza después del arranque y retira trabajo de proveedores sin publicaciones obsoletas. ([#708](https://github.com/CodesWhat/drydock/issues/708))
- **Historial de estrellas propio**: el proveedor de mismo origen `/api/star-history` sirve gráficos de Drydock, Sockguard y Portwing mediante una lista permitida, sin depender de un rastreador externo.

Notas completas en [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13).
Notas completas en [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Consultez le [Guide de démarrage rapide](https://getdrydock.com/docs/quickstart
- **Renforcement de la sécurité et du cycle de vie** : l'authentification, les requêtes d'agents, les journaux, les WebSockets et les requêtes de registres sont explicitement bornés ; les valeurs sensibles de commandes et hooks sont masquées ; la découverte Home Assistant se resynchronise après le démarrage et retire les tâches des fournisseurs sans publication périmée. ([#708](https://github.com/CodesWhat/drydock/issues/708))
- **Historique des étoiles propriétaire** : le fournisseur même origine `/api/star-history` sert les graphiques Drydock, Sockguard et Portwing autorisés sans dépendre d'un service tiers.

Notes complètes dans [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13).
Notes complètes dans [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ See the [Quick Start guide](https://getdrydock.com/docs/quickstart) for Docker C
- **Security and lifecycle hardening** — bounded authentication, agent, log, WebSocket, and registry operations; sensitive command and hook values are redacted; Home Assistant discovery resynchronizes after startup and retires provider work without stale publishes. ([#708](https://github.com/CodesWhat/drydock/issues/708))
- **First-party star history** — the same-origin `/api/star-history` provider now serves allowlisted Drydock, Sockguard, and Portwing charts without a third-party tracker dependency.

Full release notes in [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13).
Full release notes in [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.pl.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Zobacz [Przewodnik szybkiego startu](https://getdrydock.com/docs/quickstart) dla
- **Wzmocnienie bezpieczeństwa i cyklu życia** — uwierzytelnianie, żądania agentów, dzienniki, WebSockety i żądania do rejestrów mają jawne limity; poufne wartości poleceń i hooków są maskowane; wykrywanie Home Assistant ponownie synchronizuje się po starcie i wycofuje zadania dostawców bez publikowania nieaktualnych danych. ([#708](https://github.com/CodesWhat/drydock/issues/708))
- **Własna historia gwiazdek** — dostawca same-origin `/api/star-history` udostępnia wykresy dla dozwolonych repozytoriów Drydock, Sockguard i Portwing bez zewnętrznego modułu śledzącego.

Pełne informacje o wersji znajdują się w [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13).
Pełne informacje o wersji znajdują się w [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Consulte o [Guia de início rápido](https://getdrydock.com/docs/quickstart) par
- **Reforço de segurança e ciclo de vida** — autenticação, solicitações de agentes, logs, WebSockets e solicitações a registros têm limites explícitos; valores sensíveis de comandos e hooks são ocultados; a descoberta do Home Assistant sincroniza novamente após a inicialização e encerra o trabalho dos provedores sem publicações obsoletas. ([#708](https://github.com/CodesWhat/drydock/issues/708))
- **Histórico de estrelas próprio** — o provedor de mesma origem `/api/star-history` serve gráficos permitidos de Drydock, Sockguard e Portwing sem depender de um rastreador de terceiros.

Notas completas em [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13).
Notas completas em [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14).

</details>

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ docker run -d \
- **安全与生命周期强化** — 身份验证、代理请求、日志、WebSocket 和镜像仓库请求均有明确的资源限制;敏感的命令和钩子值会被遮盖;Home Assistant 发现会在启动后重新同步,并在停用提供程序任务时避免发布过期数据。([#708](https://github.com/CodesWhat/drydock/issues/708))
- **第一方 Star History** — 同源 `/api/star-history` 提供程序仅为允许的 Drydock、Sockguard 和 Portwing 仓库生成图表,不再依赖第三方跟踪服务。

完整发行说明请参阅 [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-13)。
完整发行说明请参阅 [CHANGELOG.md](./CHANGELOG.md#170-rc1--2026-08-14)。

</details>

Expand Down
4 changes: 3 additions & 1 deletion content/docs/current/updates/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ description: "Release update notes and feature highlights, with direct links to

## Unreleased

## v1.7.0-rc.1 Highlights — August 13, 2026
## v1.7.0-rc.1 Highlights — August 14, 2026

- **Dependency-aware updates** — labels or Compose metadata resolve into deterministic update waves, with preview-bound confirmation, restart-only dependents, cycle handling, and explicit skipped-dependency results ([Discussion #219](https://github.com/CodesWhat/drydock/discussions/219)).
- **Operator UX additions** — installable PWA support, clickable named port links, live container uptime, keyboard shortcuts, and a configurable settling window for newly discovered containers.
- **Trigger migration reaches removal** — `DD_TRIGGER_*` now fails startup and legacy `dd.trigger.include` / `dd.trigger.exclude` labels no longer route work; use the action/notification-specific replacements.
- **Security and lifecycle hardening** — authentication, agent requests, logs, WebSockets, and registry requests have explicit resource bounds; sensitive command/hook values are redacted; Home Assistant discovery now resynchronizes after startup and drains retiring provider work without stale publishes ([#708](https://github.com/CodesWhat/drydock/issues/708)).
- **Portwing controller and Edge reliability** — Edge refresh cadence is configurable with `DD_PORTWING_POLL_INTERVAL`; `exec_end.reason` reaches internal consumers without leaking sessions; and controller-owned Docker inventory/events normalize against configured registries so native watch-now checks no longer round-trip through Portwing's intentional 501 registry stub ([#688](https://github.com/CodesWhat/drydock/issues/688), [#635](https://github.com/CodesWhat/drydock/issues/635), [#687](https://github.com/CodesWhat/drydock/issues/687)).
- **Registry metadata failures stay visible** — optional manifest/blob responses with status 301, 302, 303, 307, or 308 can omit `created` without discarding a resolved digest, while exhausted 4xx, 5xx, network, and non-object failures now propagate instead of silently becoming a successful result with unstable metadata ([#606](https://github.com/CodesWhat/drydock/issues/606)).
- **First-party star history** — the same-origin `/api/star-history` provider serves allowlisted Drydock, Sockguard, and Portwing charts without relying on a third-party tracker.

## v1.6.0 Highlights — August 11, 2026
Expand Down
52 changes: 50 additions & 2 deletions scripts/release-docs-identity.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import test from 'node:test';

const RC_VERSION = '1.7.0-rc.1';
const PREV_RC_VERSION = '1.6.0';
const RC_DATE = '2026-08-13';
const RC_DISPLAY_DATE = 'August 13, 2026';
const RC_DATE = '2026-08-14';
const RC_DISPLAY_DATE = 'August 14, 2026';
const DOC_ROOTS = ['content/docs/current', 'content/docs/v1.6', 'content/docs/v1.5'];
const BROAD_401_CLAIM =
/(?:all|every) API (?:call|request)s?(?: (?:is|are) rejected with| returns?) `401`/iu;
Expand All @@ -18,6 +18,13 @@ function escapeRegExp(value) {
return value.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
}

function extractMarkdownSection(document, heading) {
const sectionStart = document.indexOf(`${heading}\n`);
assert.notEqual(sectionStart, -1, `missing Markdown section: ${heading}`);
const nextSectionStart = document.indexOf('\n## ', sectionStart + heading.length + 1);
return document.slice(sectionStart, nextSectionStart === -1 ? undefined : nextSectionStart);
}

test('public release surfaces identify the v1.7 release candidate', () => {
const readme = read('README.md');
const siteConfig = read('apps/web/src/lib/site-config.ts');
Expand Down Expand Up @@ -90,6 +97,47 @@ test('public release surfaces identify the v1.7 release candidate', () => {
);
});

test('release-note section extraction stops at the next level-two heading', () => {
assert.equal(
extractMarkdownSection('## Target\nkeep\n\n## Later\nignore\n', '## Target'),
'## Target\nkeep\n',
);
});

test('release candidate notes cover the post-promotion fixes', () => {
const changelog = extractMarkdownSection(read('CHANGELOG.md'), `## [${RC_VERSION}] — ${RC_DATE}`);
const updates = extractMarkdownSection(
read('content/docs/current/updates/index.mdx'),
`## v${RC_VERSION} Highlights — ${RC_DISPLAY_DATE}`,
);

for (const issue of [606, 635, 687, 688]) {
const issueLink = `https://github.com/CodesWhat/drydock/issues/${issue}`;
assert.ok(changelog.includes(issueLink), `CHANGELOG.md must link issue #${issue}`);
assert.ok(updates.includes(issueLink), `updates page must link issue #${issue}`);
}

assert.doesNotMatch(updates, /\b3xx\b/iu);
for (const fragment of [
'`DD_PORTWING_POLL_INTERVAL`',
'`exec_end.reason`',
"controller's configured registry identity",
'4xx, 5xx, network, and non-object failures',
]) {
assert.ok(changelog.includes(fragment), `CHANGELOG.md must include ${fragment}`);
}

for (const fragment of [
'`DD_PORTWING_POLL_INTERVAL`',
'`exec_end.reason`',
'normalize against configured registries',
'301, 302, 303, 307, or 308',
'4xx, 5xx, network, and non-object failures',
]) {
assert.ok(updates.includes(fragment), `updates page must include ${fragment}`);
}
});
Comment thread
scttbnsn marked this conversation as resolved.

test('v1.6.0 is released and public release routing advances to v1.7', () => {
const readme = read('README.md');
const siteContent = read('apps/web/src/lib/site-content.ts');
Expand Down
Loading