Skip to content

feat(onboarding): Docker label discovery during init - #6158

Open
ajnart wants to merge 5 commits into
devfrom
feat/onboarding-docker-label-discovery
Open

feat(onboarding): Docker label discovery during init#6158
ajnart wants to merge 5 commits into
devfrom
feat/onboarding-docker-label-discovery

Conversation

@ajnart

@ajnart ajnart commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

  • Ports Docker label discovery (homarr.* / homepage.*) from the config-portability work into onboarding
  • Labeled containers take priority over image-based matching on the integrations step
  • Selected label apps sync into category sections via docker_app_source tracking
  • Integration widgets still land in the empty section without duplicating label-synced apps

Test plan

  • parse-container-labels.spec.ts (28 tests)
  • Typecheck @homarr/docker, @homarr/api
  • Manual: containers with homarr.name/group/href appear in onboarding with correct metadata
  • Manual: finish creates category sections; unlabeled containers still use image matching

Summary by CodeRabbit

  • New Features

    • Docker label onboarding now supports separate “label” sourcing, syncing label-based apps and placing widgets into the appropriate board sections.
    • Added Docker discovery tracking for label-sourced apps and their container origin.
    • Introduced Docker label discovery settings for target board selection, homepage-label fallback, and widget/integration handling.
  • Bug Fixes

    • Improved Docker discovery handling: hidden containers are ignored, label/docker candidates are deduplicated, and onboarding works more reliably when metadata/templates are missing.
    • Avoid duplicate app creation by reusing existing app links.
  • Documentation

    • Added Docker labels documentation and clarified Docker hide behavior during label discovery.
  • Tests

    • Added coverage for Docker label parsing edge cases.

Port label-based container discovery from config-portability and wire it
into the onboarding integrations step. Labeled containers take priority
over image matching, sync into category sections, and preserve board
layout when placing integration widgets.
@ajnart
ajnart requested a review from a team as a code owner July 1, 2026 20:30
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e9329b5-f841-48fa-8a95-19e92caa8e41

📥 Commits

Reviewing files that changed from the base of the PR and between cf655b8 and 4040f28.

📒 Files selected for processing (6)
  • apps/docs/docs/integrations/docker-labels/index.mdx
  • apps/docs/docs/integrations/docker/index.mdx
  • apps/nextjs/src/app/[locale]/init/_steps/integrations/init-integrations.tsx
  • packages/api/src/router/onboard/onboard-router.ts
  • packages/docker/src/discovery/parse-container-labels.ts
  • packages/docker/src/discovery/sync-discovered-services.ts
✅ Files skipped from review due to trivial changes (2)
  • apps/docs/docs/integrations/docker/index.mdx
  • apps/docs/docs/integrations/docker-labels/index.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/docker/src/discovery/parse-container-labels.ts
  • apps/nextjs/src/app/[locale]/init/_steps/integrations/init-integrations.tsx
  • packages/docker/src/discovery/sync-discovered-services.ts
  • packages/api/src/router/onboard/onboard-router.ts

📝 Walkthrough

Walkthrough

Adds Docker label discovery and sync for onboarding, backed by a new docker_app_source table and server settings. The router, UI, and docs now handle label-sourced apps separately from image-sourced apps.

Changes

Docker label discovery, sync, and onboarding

Layer / File(s) Summary
Label definitions and DiscoveredService type
packages/docker/src/labels.ts, packages/docker/src/discovery/types.ts
Adds homepageLabels alongside expanded dockerLabels keys, and defines the DiscoveredService interface used by parsing/sync.
parseContainerLabels implementation and tests
packages/docker/src/discovery/parse-container-labels.ts, packages/docker/src/discovery/__tests__/parse-container-labels.spec.ts
Parses container labels into DiscoveredService, resolving Homarr vs homepage fallback fields, hide semantics, and integration/widget kind validation, with coverage for parsing scenarios.
Container listing and discovery barrel
packages/docker/src/discovery/list-discovered-containers.ts, packages/docker/src/discovery/index.ts, packages/docker/src/index.ts
Adds listDiscoveredContainersAsync to enumerate and filter labeled containers across Docker instances, and exports it through discovery barrels.
docker_app_source schema and migrations
packages/db/migrations/mysql/..., packages/db/migrations/postgresql/..., packages/db/migrations/sqlite/..., packages/db/schema/*.ts
Adds the docker_app_source table with composite primary key, foreign keys to app/board/item/integration, an index, corresponding Drizzle schemas/relations, and journal entries across all dialects.
syncDiscoveredServicesAsync implementation
packages/docker/src/discovery/sync-discovered-services.ts
Syncs discovered services into boards by resolving target boards, matching or creating apps, sections, and items, computing layout offsets, and persisting docker_app_source rows transactionally.
Server settings for docker discovery
packages/server-settings/src/index.ts
Adds a docker settings key with defaults for target board, homepage label reading, pruning, integration creation, and default item size.
Onboarding router discovery and setup integration
packages/api/src/router/onboard/onboard-router.ts
Combines label-based and container-based discovery, deduplicates created apps by href, and scopes widget placement and empty-section cleanup during onboarding setup.
Onboarding UI wiring for label sourced apps
apps/nextjs/src/app/[locale]/init/_steps/integrations/init-integrations.tsx
Adds "label" to IntegrationDraft.source, wires a syncDockerLabelApps mutation, splits setup completion by source, adjusts URL templating for label drafts, and updates card layout and continue-button behavior.
Documentation for docker labels
apps/docs/docs/integrations/docker-labels/index.mdx, apps/docs/docs/integrations/docker-labels/index.ts, apps/docs/docs/integrations/docker/index.mdx
Adds a new Docker labels documentation page and integration metadata, and updates the Docker integration doc to describe label discovery and the expanded homarr.hide behavior.

Sequence Diagram(s)

sequenceDiagram
  participant OnboardRouter
  participant SyncService
  participant Database
  OnboardRouter->>SyncService: discovered label apps
  SyncService->>Database: load boards and existing sources
  SyncService->>Database: insert or update apps, items, layouts
  SyncService->>Database: upsert docker_app_source rows
  SyncService-->>OnboardRouter: created / updated / skipped counts
Loading
sequenceDiagram
  participant InitIntegrations
  participant SyncLabelApps
  participant CreateApps
  InitIntegrations->>InitIntegrations: split selected apps by source
  InitIntegrations->>SyncLabelApps: label-sourced apps
  InitIntegrations->>CreateApps: image-sourced apps
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: Docker label discovery added to onboarding init.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Yagni / Over-Engineering ✅ Passed The PR adds only the plumbing needed for label onboarding, source tracking, and a parser test; no obvious dead abstractions or gratuitous deps stood out.
Docs Are Up To Date ✅ Passed PASS: added apps/docs/docs/integrations/docker-labels/* and updated docker/index.mdx to document label discovery and homarr.hide.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/onboarding-docker-label-discovery

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/docs/integrations/docker-labels/index.mdx`:
- Around line 32-35: The Homepage fallback documentation is incomplete because
`homepage.icon` and `homepage.description` are missing from the fallback payload
description. Update the `Homepage fallback` section in the Docker labels docs to
list all fields handled by the fallback behavior, using the existing
`homepage.*` symbols alongside `homarr.name` so the reference fully matches the
implementation.

In `@apps/docs/docs/integrations/docker/index.mdx`:
- Around line 96-100: The Docker labels documentation link in the onboarding
section points to the wrong relative location and will resolve to a 404 from
this page. Update the link in the Docker integration docs to point to the
sibling docker-labels page using the correct relative path, and verify the
markdown link in the Homarr onboarding copy still references the intended Docker
labels reference.

In `@apps/nextjs/src/app/`[locale]/init/_steps/integrations/init-integrations.tsx:
- Around line 161-170: The label-app sync flow in init-integrations currently
filters out missing hosts and still continues into setup, which can hide a sync
result of notFound. Update the logic around syncLabelApps and the
labelAppsWithHost handling so missing label apps are explicitly detected and
surfaced before calling setupIntegrations(), and stop completion or prompt the
user when selected apps no longer exist. Use the
syncDockerLabelApps/syncLabelApps path and the labelAppsWithHost block to locate
the change.
- Around line 386-388: The continue flow in
handleContinueToConfig/init-integrations should treat app-only selections as a
valid path to completion instead of always entering ConfigurePhase. Update the
transition logic so that when selectedKinds is empty but selectedAppCount is
greater than zero, it skips the configure step and goes straight to the finish
path, avoiding any access to selectedKinds[currentIndex] in ConfigurePhase. Keep
the existing behavior for kind-based selections, but guard the configure-phase
branch against empty selectedKinds.

In `@packages/api/src/router/onboard/onboard-router.ts`:
- Around line 190-191: `onboard-router` is mutating `emptyResult` by aliasing
its `integrations` and `apps` arrays into `discoveredIntegrations` and
`discoveredApps`, so later failures can return populated data with `status:
"unavailable"`. In the onboarding flow, make `discoveredIntegrations` and
`discoveredApps` fresh local arrays instead of references to `emptyResult`, and
only merge them into the success response path; keep `emptyResult` unchanged so
the `catch` path in `onboard-router` always spreads truly empty fallback data.

In `@packages/db/schema/sqlite.ts`:
- Around line 559-563: The unique identity in this table is currently based on
compoundKey using host and containerId, but syncDiscoveredServicesAsync and
lookups rely on host plus externalId. Update the primary uniqueness in the table
definition from containerId to externalId so existing mappings are reused when
containers are recreated, and keep containerId as non-unique mutable metadata;
also verify the externalIdIdx and any related schema references in sqlite.ts
still align with the host/externalId identity.

In `@packages/docker/src/discovery/parse-container-labels.ts`:
- Around line 37-45: Normalize blank values to undefined in readLabel so
whitespace-only labels do not count as present before fallback logic runs.
Update readLabel and the resolveLabelValue path in parse-container-labels.ts so
homarr.* keys that trim to an empty string are treated as missing, allowing
homepage.* fallback and the container.Id default to work correctly for fields
like name and externalId.

In `@packages/docker/src/discovery/sync-discovered-services.ts`:
- Around line 233-236: The update paths in sync-discovered-services do not
refresh updatedAt when modifying an existing source row, so the timestamp stays
stale even though the row is active. Update the relevant update statements in
the discovery sync flow (including the blocks around the source row updates) to
explicitly set updatedAt to the current time alongside the existing
appId/boardId/itemId/externalId fields, using the same database update logic
already used in this module.
- Around line 136-153: The new item’s vertical placement is being computed only
once via getNextItemYOffset using firstLayout.id and then reused across all
layouts, which can cause overlaps when breakpoints differ. Update
sync-discovered-services.ts in the item layout creation flow so each entry in
board.layouts.map computes its own yOffset using that layout’s id before
building the item layout object. Keep the fix localized around
getNextItemYOffset, firstLayout, and the newItemLayouts mapping.
- Around line 341-343: The ping status toggle logic in sync-discovered-services
is letting service.pingUrl override options.forceDisableStatus, so
forceDisableStatus is ignored for services with a ping URL. Update the
pingEnabled assignment in the service sync flow to check forceDisableStatus
first and only enable pinging when it is not disabled, then apply the existing
enableStatusByDefault/pingUrl behavior afterward. Use the pingEnabled logic near
the service discovery mapping in sync-discovered-services to make the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c93dfc58-3cbd-4c0a-a2b3-edd4b91ea369

📥 Commits

Reviewing files that changed from the base of the PR and between dd2eb3a and cf655b8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (25)
  • apps/docs/docs/integrations/docker-labels/index.mdx
  • apps/docs/docs/integrations/docker-labels/index.ts
  • apps/docs/docs/integrations/docker/index.mdx
  • apps/nextjs/src/app/[locale]/init/_steps/integrations/init-integrations.tsx
  • packages/api/src/router/onboard/onboard-router.ts
  • packages/db/migrations/mysql/0042_add_docker_app_source.sql
  • packages/db/migrations/mysql/meta/_journal.json
  • packages/db/migrations/postgresql/0008_add_docker_app_source.sql
  • packages/db/migrations/postgresql/meta/_journal.json
  • packages/db/migrations/sqlite/0040_add_docker_app_source.sql
  • packages/db/migrations/sqlite/meta/_journal.json
  • packages/db/schema/index.ts
  • packages/db/schema/mysql.ts
  • packages/db/schema/postgresql.ts
  • packages/db/schema/sqlite.ts
  • packages/docker/package.json
  • packages/docker/src/discovery/__tests__/parse-container-labels.spec.ts
  • packages/docker/src/discovery/index.ts
  • packages/docker/src/discovery/list-discovered-containers.ts
  • packages/docker/src/discovery/parse-container-labels.ts
  • packages/docker/src/discovery/sync-discovered-services.ts
  • packages/docker/src/discovery/types.ts
  • packages/docker/src/index.ts
  • packages/docker/src/labels.ts
  • packages/server-settings/src/index.ts

Comment thread apps/docs/docs/integrations/docker-labels/index.mdx
Comment thread apps/docs/docs/integrations/docker/index.mdx Outdated
Comment thread packages/api/src/router/onboard/onboard-router.ts Outdated
Comment thread packages/db/schema/sqlite.ts
Comment thread packages/docker/src/discovery/parse-container-labels.ts Outdated
Comment thread packages/docker/src/discovery/sync-discovered-services.ts Outdated
Comment thread packages/docker/src/discovery/sync-discovered-services.ts
Comment thread packages/docker/src/discovery/sync-discovered-services.ts Outdated
ajnart and others added 3 commits July 2, 2026 10:45
Fix app-only continue flow, handle stale label sync, per-layout yOffset,
blank label normalization, updatedAt on source upsert, docs link, and
forceDisableStatus for ping-enabled apps.
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.

1 participant