Skip to content

fix: auto update service logic#323

Merged
kmendell merged 16 commits into1.0.0from
fix/auto-update-service
Jul 2, 2025
Merged

fix: auto update service logic#323
kmendell merged 16 commits into1.0.0from
fix/auto-update-service

Conversation

@kmendell
Copy link
Member

@kmendell kmendell commented Jun 29, 2025

Summary by CodeRabbit

  • New Features

    • Introduced unified auto-update functionality for containers and stacks, including a new update history view and status tracking.
    • Added support for dry-run update checks and detailed update result reporting.
    • Expanded Docker image metadata display, including architecture, OS, labels, and environment variables.
    • Enhanced code editor component with multi-language support and customizable dimensions.
  • Bug Fixes

    • Improved robustness in date parsing and display for image details.
    • Standardized JSON response formats for update-related API endpoints.
  • Refactor

    • Unified and streamlined auto-update backend logic for improved concurrency and error handling.
    • Replaced separate YAML and ENV editors with a single, versatile code editor.
    • Improved UI for stack management, exposed ports, and service listing.
  • Chores

    • Updated and added frontend dependencies to support new editor and UI features.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 29, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This set of changes extensively refactors and expands the auto-update feature across backend and frontend. It unifies update logic into a single, DTO-driven service, introduces persistent update records, adds endpoints for update history and status, and standardizes API responses. Frontend components and services are updated to support these new APIs and data structures, while code editors are unified and enhanced.

Changes

Files/Areas Change Summary
backend/internal/api/auto_update_handler.go, routes.go Refactored auto-update handlers to use unified CheckForUpdates, added endpoints for containers, stacks, and history, standardized JSON responses.
backend/internal/api/image_handler.go Removed unused nil argument from CheckImageMaturity calls.
backend/internal/api/network_handler.go Standardized network ID parameter name in handler methods.
backend/internal/bootstrap/services_bootstrap.go Updated service constructors for ImageMaturityService and AutoUpdateService to accept new dependencies.
backend/internal/dto/auto_update_dto.go Added DTOs for auto-update check requests, results, resource results, and config.
backend/internal/job/auto_update_job.go Refactored job to use unified update check, consolidated logging, improved error handling.
backend/internal/models/auto_update.go Added model for persistent auto-update records and status constants.
backend/internal/services/auto_update_service.go Major refactor: unified update logic, concurrent checking, persistent records, registry auth improvements, new methods for history and status.
backend/internal/services/image_maturity_service.go Refactored to use ContainerRegistryService for registry resolution, removed explicit credentials from method signatures, standardized DB access.
frontend/package.json Added/updated dependencies for code editors, syntax highlighting, and icons.
frontend/src/lib/components/editor.svelte Enhanced editor to support multiple languages, added props for language, height, and font size, unified YAML and ENV editing.
frontend/src/lib/components/env-editor.svelte Removed, replaced by unified editor component.
frontend/src/lib/components/ui/button/button.svelte, ui/copy-button/copy-button.svelte Updated icon imports for consistency.
frontend/src/lib/components/universal-table.svelte Code style and layout refactor, added explicit classes, no logic changes.
frontend/src/lib/models/image.type.ts Expanded ServiceImage type with new Docker image metadata fields.
frontend/src/lib/services/api/autoupdate-api-service.ts Added/updated methods for unified update checks, history, status, and dry run; updated return types.
frontend/src/lib/types/auto-update.type.ts Added new TypeScript interfaces for auto-update DTOs and records.
frontend/src/routes/compose/+page.svelte, [composeId]/+page.svelte, new/+page.svelte Updated to use new auto-update API, unified code editor, improved UI, added floating header and enhanced service/port display.
frontend/src/routes/images/[imageId]/+page.svelte Refactored computed values, improved robustness, added environment variables display, updated data paths.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend
    participant APIHandler
    participant AutoUpdateService
    participant DB

    User->>Frontend: Initiates update check (all/containers/stacks)
    Frontend->>APIHandler: POST /updates/check (with DTO)
    APIHandler->>AutoUpdateService: CheckForUpdates(ctx, DTO)
    AutoUpdateService->>AutoUpdateService: Concurrently check containers/stacks
    AutoUpdateService->>DB: Record update results for each resource
    AutoUpdateService-->>APIHandler: Return AutoUpdateResultDto
    APIHandler-->>Frontend: JSON response (success/data)
    Frontend-->>User: Display update results
Loading
sequenceDiagram
    participant User
    participant Frontend
    participant APIHandler
    participant AutoUpdateService
    participant DB

    User->>Frontend: Requests update history
    Frontend->>APIHandler: GET /updates/history?limit=50
    APIHandler->>AutoUpdateService: GetAutoUpdateHistory(ctx, limit)
    AutoUpdateService->>DB: Query auto_update_records
    AutoUpdateService-->>APIHandler: Return records
    APIHandler-->>Frontend: JSON response (success/data)
    Frontend-->>User: Display update history
Loading

Possibly related PRs

  • ofkm/arcane#296: Initial implementation of the auto-update handler and service structure, which this PR directly refactors and extends.
  • ofkm/arcane#162: Adds support for private Docker registries and credential management, directly related to registry authentication improvements in this PR's auto-update service.
  • ofkm/arcane#83: Introduces the initial auto-update feature for containers and stacks, upon which this PR builds with unified logic and expanded features.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@kmendell kmendell marked this pull request as ready for review July 2, 2025 01:49
@kmendell
Copy link
Member Author

kmendell commented Jul 2, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 2, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@kmendell kmendell changed the title fix: auto update service logic, and frontend UX fix: auto update service logic Jul 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🔭 Outside diff range comments (2)
frontend/src/routes/compose/[composeId]/+page.svelte (2)

391-422: Remove duplicate exposed ports section.

This entire section is an exact duplicate of the exposed ports card above (lines 357-388). This appears to be a copy-paste error.

-{#if servicePorts && Object.keys(servicePorts).length > 0}
-    {@const allUniquePorts = [...new Set(Object.values(servicePorts).flat())]}
-    <Card.Root class="border">
-        <Card.Header class="pb-4">
-            <Card.Title>Exposed Ports</Card.Title>
-        </Card.Header>
-        <Card.Content>
-            <div class="flex flex-wrap gap-2">
-                {#each allUniquePorts as port (port)}
-                    {@const portValue =
-                        typeof port === 'string' ||
-                        typeof port === 'number' ||
-                        (typeof port === 'object' && port !== null)
-                            ? port
-                            : String(port)}
-                    {@const serviceWithPort = stack.services?.find((s) =>
-                        s.ports?.includes(String(port))
-                    ) || { container_id: '', name: '', status: '' }}
-                    <a
-                        href={getServicePortUrl(serviceWithPort, portValue)}
-                        target="_blank"
-                        rel="noopener noreferrer"
-                        class="inline-flex items-center rounded-md bg-blue-500/10 px-3 py-2 font-medium text-blue-600 transition-colors hover:bg-blue-500/20 dark:text-blue-400"
-                    >
-                        Port {port}
-                        <ExternalLink class="ml-2 size-4" />
-                    </a>
-                {/each}
-            </div>
-        </Card.Content>
-    </Card.Root>
-{/if}

160-165: Incorrect protocol assignment for non-TCP ports.

The logic on line 164 assigns 'https' for non-TCP protocols, which doesn't make sense for UDP ports. UDP is not an HTTP-based protocol.

if (port.Type) {
-    protocol = port.Type.toLowerCase() === 'tcp' ? 'http' : 'https';
+    protocol = port.Type.toLowerCase() === 'tcp' ? 'http' : port.Type.toLowerCase();
}

Consider also handling the case where the protocol might be 'udp' differently, as UDP URLs aren't typically accessed via browser.

🧹 Nitpick comments (5)
backend/internal/job/auto_update_job.go (1)

104-104: Clarify the boolean parameter purpose.

The false parameter added to RegisterJob lacks context. Consider adding a comment to explain what this parameter controls for better code maintainability.

	return scheduler.RegisterJob(
		ctx,
		"auto-update",
		jobDefinition,
		job.Execute,
-		false,
+		false, // runImmediately
	)
frontend/src/lib/types/auto-update.type.ts (1)

33-47: Consider strengthening type definitions for consistency

The AutoUpdateRecord interface correctly mirrors the backend model but could benefit from stronger typing for better consistency with the resource result interface.

export interface AutoUpdateRecord {
    id: string;
    resourceId: string;
-    resourceType: string;
+    resourceType: 'container' | 'stack';
    resourceName: string;
-    status: string;
+    status: 'pending' | 'checking' | 'updating' | 'completed' | 'failed' | 'skipped';
    startTime: string;
    endTime?: string;
    updateAvailable: boolean;
    updateApplied: boolean;
    oldImageVersions?: Record<string, string>;
    newImageVersions?: Record<string, string>;
    error?: string;
    details?: Record<string, any>;
}
frontend/src/routes/compose/new/+page.svelte (1)

154-159: Potential CSS class conflict on example buttons.

The truncate class on line 158 may not work as intended when combined with break-all whitespace-normal classes. Consider using either truncation or word breaking, but not both.

-class="h-auto w-full justify-start p-2 text-left font-mono text-xs break-all whitespace-normal"
+class="h-auto w-full justify-start p-2 text-left font-mono text-xs"

And update the span:

-<span class="truncate">{command}</span>
+<span class="block truncate">{command}</span>
backend/internal/api/auto_update_handler.go (1)

23-27: Consider logging JSON binding errors for debugging.

While defaulting to {Type: "all"} on binding failure provides good backward compatibility, consider logging the error to help debug client issues.

var req dto.AutoUpdateCheckDto
if err := c.ShouldBindJSON(&req); err != nil {
+    // Log the error for debugging but continue with default
+    c.Set("binding_error", err.Error())
    req = dto.AutoUpdateCheckDto{Type: "all"}
}
frontend/src/lib/services/api/autoupdate-api-service.ts (1)

25-34: Consider adding type guards for wrapped responses.

The code correctly handles the backend's wrapped response format for getUpdateHistory and getUpdateStatus. Consider adding type safety for these wrapped responses.

interface WrappedResponse<T> {
    success: boolean;
    data: T;
}

async getUpdateHistory(limit?: number): Promise<AutoUpdateRecord[]> {
    const params = limit ? { limit } : {};
    const response = await this.api.get<WrappedResponse<AutoUpdateRecord[]>>('/updates/history', { params });
    return response.data.data;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd10ad0 and c3afa75.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (23)
  • backend/internal/api/auto_update_handler.go (2 hunks)
  • backend/internal/api/image_handler.go (2 hunks)
  • backend/internal/api/network_handler.go (2 hunks)
  • backend/internal/api/routes.go (1 hunks)
  • backend/internal/bootstrap/services_bootstrap.go (1 hunks)
  • backend/internal/dto/auto_update_dto.go (1 hunks)
  • backend/internal/job/auto_update_job.go (3 hunks)
  • backend/internal/models/auto_update.go (1 hunks)
  • backend/internal/services/auto_update_service.go (3 hunks)
  • backend/internal/services/image_maturity_service.go (16 hunks)
  • frontend/package.json (1 hunks)
  • frontend/src/lib/components/editor.svelte (2 hunks)
  • frontend/src/lib/components/env-editor.svelte (0 hunks)
  • frontend/src/lib/components/ui/button/button.svelte (1 hunks)
  • frontend/src/lib/components/ui/copy-button/copy-button.svelte (1 hunks)
  • frontend/src/lib/components/universal-table.svelte (7 hunks)
  • frontend/src/lib/models/image.type.ts (1 hunks)
  • frontend/src/lib/services/api/autoupdate-api-service.ts (1 hunks)
  • frontend/src/lib/types/auto-update.type.ts (1 hunks)
  • frontend/src/routes/compose/+page.svelte (1 hunks)
  • frontend/src/routes/compose/[composeId]/+page.svelte (17 hunks)
  • frontend/src/routes/compose/new/+page.svelte (5 hunks)
  • frontend/src/routes/images/[imageId]/+page.svelte (9 hunks)
💤 Files with no reviewable changes (1)
  • frontend/src/lib/components/env-editor.svelte
🧰 Additional context used
🧠 Learnings (7)
frontend/src/lib/components/ui/copy-button/copy-button.svelte (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
frontend/src/lib/components/ui/button/button.svelte (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
frontend/src/lib/components/editor.svelte (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
frontend/src/lib/components/universal-table.svelte (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
frontend/package.json (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
frontend/src/routes/compose/[composeId]/+page.svelte (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
frontend/src/routes/compose/new/+page.svelte (1)
Learnt from: kmendell
PR: ofkm/arcane#86
File: src/lib/components/table-cells/user-table-actions.svelte:15-15
Timestamp: 2025-04-30T01:20:17.798Z
Learning: This project uses Svelte 5 with the runes syntax, where props are declared using `$props()` rather than the older `export let` pattern.
🧬 Code Graph Analysis (5)
backend/internal/job/auto_update_job.go (1)
backend/internal/dto/auto_update_dto.go (1)
  • AutoUpdateCheckDto (3-8)
frontend/src/lib/types/auto-update.type.ts (2)
backend/internal/dto/auto_update_dto.go (1)
  • AutoUpdateResourceResult (22-33)
backend/internal/models/auto_update.go (3)
  • AutoUpdateRecord (18-33)
  • AutoUpdateRecord (35-37)
  • AutoUpdateStatus (7-7)
backend/internal/models/auto_update.go (2)
frontend/src/lib/types/auto-update.type.ts (2)
  • AutoUpdateStatus (49-54)
  • AutoUpdateRecord (33-47)
backend/internal/models/base.go (2)
  • JSON (17-17)
  • BaseModel (11-14)
backend/internal/dto/auto_update_dto.go (1)
frontend/src/lib/types/auto-update.type.ts (1)
  • AutoUpdateResourceResult (20-31)
backend/internal/api/auto_update_handler.go (1)
backend/internal/dto/auto_update_dto.go (1)
  • AutoUpdateCheckDto (3-8)
🔇 Additional comments (45)
frontend/src/lib/components/ui/copy-button/copy-button.svelte (1)

9-11: LGTM! Import style updated consistently.

The change from named imports to default imports from specific icon paths aligns with the package update pattern mentioned in the AI summary. This is a clean refactor that maintains functionality while potentially improving tree-shaking.

frontend/src/lib/components/ui/button/button.svelte (1)

70-70: LGTM! Consistent import style update.

The LoaderCircleIcon import change follows the same pattern as other UI components, maintaining consistency across the codebase.

backend/internal/api/image_handler.go (1)

62-62: Method signature update handled correctly.

The removal of the final nil argument from both CheckImageMaturity calls aligns with the updated signature. I didn’t spot any remaining invocations using the old five-parameter form, but please double-check across the repository to be sure:

# List all invocations of CheckImageMaturity and verify they use the new signature
rg --color=never 'CheckImageMaturity' -n .
frontend/src/routes/compose/+page.svelte (1)

156-156: Confirmed – checkStacks() is implemented and no old checkStack() remains.

  • In frontend/src/lib/services/api/autoupdate-api-service.ts (line 20):
    async checkStacks(): Promise<AutoUpdateResult> { … }
  • No remaining references to checkStack() across the codebase.
  • The call at frontend/src/routes/compose/+page.svelte line 156 is correct.
backend/internal/api/routes.go (1)

255-258: Well-structured API route refactoring.

The new route organization provides both unified and specific update endpoints, along with useful history functionality. The routing structure is clean and follows REST conventions.

frontend/package.json (1)

29-29: Good dependency additions for enhanced code editing.

The new dependencies support improved code editing features:

  • @uiw/codemirror-theme-github for GitHub-style theming
  • @shikijs/langs and @shikijs/themes with shiki for advanced syntax highlighting
  • isomorphic-dompurify for content sanitization (good security practice)
  • svelte-toolbelt for additional Svelte utilities

These align well with the PR's frontend UX improvement objectives.

Also applies to: 45-46, 58-58, 62-62, 66-66

backend/internal/job/auto_update_job.go (2)

39-45: Excellent refactoring to unified DTO-based approach.

The change to use dto.AutoUpdateCheckDto with a single CheckForUpdates method is much cleaner than separate calls. The DTO structure allows for flexible update types and options like dry runs.


51-70: Enhanced logging provides excellent visibility.

The detailed logging of update results, including counts and individual resource outcomes, will be very helpful for monitoring and debugging auto-update operations.

backend/internal/bootstrap/services_bootstrap.go (1)

25-25: Correct dependency injection updates.

The updated service constructors properly inject the required dependencies:

  • imageMaturityService now receives containerRegistry for credential management
  • autoUpdate service now receives db for persistent update records

These changes are consistent with the service refactoring.

Also applies to: 29-29

frontend/src/lib/models/image.type.ts (1)

4-31: Comprehensive image metadata type expansion.

The expanded ServiceImage type now includes extensive Docker image metadata:

  • Architecture and OS information
  • Detailed configuration (ports, environment, labels)
  • Storage and filesystem details
  • Metadata and descriptors

All properties are appropriately optional for backward compatibility. This enhancement supports the richer image functionality mentioned in the PR objectives.

frontend/src/lib/components/editor.svelte (4)

13-22: LGTM - Well-structured TypeScript interface and props declaration

The CodeLanguage union type and props declaration using Svelte 5 runes syntax are implemented correctly. The bindable value prop and default values for all props provide good defaults and flexibility.


26-42: LGTM - Excellent dynamic language extension implementation

The getLanguageExtension function provides clean separation of concerns for different language modes:

  • YAML mode includes syntax highlighting and conditional linting for editable editors
  • ENV mode uses legacy properties mode without linting
  • Proper conditional logic prevents linting in read-only mode

This approach is maintainable and easily extensible for additional languages.


69-70: LGTM - Clean template implementation with dynamic extensions

The template correctly uses the new githubDark theme and dynamically applies language extensions via the getLanguageExtension function. The binding to height and fontSize props provides proper customization.


51-52: Fix potential off-by-one error in YAML linter

The end position calculation may cause issues when err.mark.position is 0, as Math.max(start + 1, err.mark.position + 1) would result in Math.max(1, 1) = 1, creating a zero-length range.

-			const end =
-				err.mark?.position !== undefined ? Math.max(start + 1, err.mark.position + 1) : start + 1;
+			const end = err.mark?.position !== undefined ? Math.max(start + 1, start + 1) : start + 1;

Or more simply:

-			const end =
-				err.mark?.position !== undefined ? Math.max(start + 1, err.mark.position + 1) : start + 1;
+			const end = start + 1;

Likely an incorrect or invalid review comment.

frontend/src/lib/components/universal-table.svelte (5)

2-21: LGTM - Improved import organization and readability

The multi-line import formatting significantly improves readability and makes it easier to track dependencies. The alphabetical grouping of TanStack table imports is well organized.


72-89: LGTM - Enhanced destructuring with clear defaults

The multi-line destructuring with explicit defaults improves code readability and makes the component's configuration options more discoverable. The type annotations and default values are well-defined.


204-216: LGTM - Improved reactive computations formatting

The multi-line formatting of derived values enhances readability while maintaining the same logic. The computed properties are well-structured and easy to understand.


269-312: LGTM - Enhanced table header styling and accessibility

The explicit CSS classes and improved multi-line formatting provide better control over table layout. The addition of proper aria-label attributes enhances accessibility. The conditional styling for sortable columns is well-implemented.


364-380: LGTM - Improved pagination control formatting

The multi-line formatting of the Select component improves readability while maintaining all functionality. The event handling and accessibility attributes are properly preserved.

frontend/src/lib/types/auto-update.type.ts (4)

1-6: LGTM - Well-structured request interface

The AutoUpdateCheck interface provides comprehensive request parameters with proper optional fields and clear union types for the type field. The boolean flags for forceUpdate and dryRun are appropriately optional.


8-18: LGTM - Comprehensive result interface

The AutoUpdateResult interface captures all essential metrics from an auto-update operation with proper field types. The inclusion of timing information and summary statistics provides good observability.


20-31: LGTM - Detailed resource result interface

The AutoUpdateResourceResult interface aligns well with the backend DTO structure. The union type for resourceType and detailed status enum provide type safety. The optional fields for images and error handling are appropriate.


49-54: LGTM - Clear status interface

The AutoUpdateStatus interface provides a clear summary of current update operations with proper field types for counts and ID arrays.

backend/internal/models/auto_update.go (3)

7-16: LGTM - Well-defined status type with comprehensive constants

The AutoUpdateStatus string type with clear lifecycle constants provides excellent type safety and covers all necessary states for auto-update operations. The naming convention is consistent and self-explanatory.


18-33: LGTM - Comprehensive model with proper database mapping

The AutoUpdateRecord struct is well-designed with:

  • Proper GORM tags for primary key, indexing, and constraints
  • Appropriate field types including pointers for nullable fields
  • JSON tags matching the frontend interface naming
  • Good use of the JSON type for complex data storage
  • Embedding of BaseModel for common timestamp fields

The model provides excellent persistence capabilities for auto-update operations.


35-37: LGTM - Proper table name specification

The TableName() method correctly specifies the database table name following Go naming conventions.

frontend/src/routes/images/[imageId]/+page.svelte (6)

27-27: LGTM - Safer ID extraction with optional chaining

The use of optional chaining (image?.Id?.split) with fallback to 'N/A' provides robust null safety for the short ID extraction.


29-42: LGTM - Excellent date parsing with comprehensive error handling

The enhanced date parsing function provides multiple layers of safety:

  • Early return for missing data
  • Try-catch for parsing errors
  • NaN validation for invalid dates
  • Graceful fallback to 'N/A' in all error cases

This is a significant improvement in robustness.


45-46: LGTM - Safer property access for image metadata

The optional chaining for image?.Architecture and image?.Os with fallback values provides consistent null safety across the component.


199-218: LGTM - Updated labels access path and improved layout

The change from image.Labels to image.Config?.Labels correctly reflects the updated data structure. The enhanced flex layout with separators improves visual presentation and readability.


220-242: LGTM - Excellent addition of Environment Variables display

The new Environment Variables card provides valuable information with:

  • Proper conditional rendering
  • Safe environment variable parsing with split/join logic
  • Consistent styling matching the Labels card
  • Proper separator handling

The implementation handles edge cases well, such as environment variables containing multiple '=' characters.


94-100: LGTM - Consistent component usage with ArcaneButton

The transition to using ArcaneButton with proper props provides consistent UI patterns across the application. The loading and disabled state handling is appropriate.

frontend/src/routes/compose/new/+page.svelte (3)

1-18: Import changes look good!

The import updates align well with the UI refactoring - removing unused components and adding the necessary Dialog components and converterAPI.


26-26: Dialog state management implemented correctly.

Good UX decision to close the converter dialog on successful conversion.

Also applies to: 68-68, 74-74


216-244: Clean grid layout implementation with unified editors.

The switch to CodeEditor components with language-specific configurations is well implemented. The fixed height provides consistent editing experience.

backend/internal/dto/auto_update_dto.go (3)

3-8: Well-structured request DTO.

The AutoUpdateCheckDto provides good flexibility with clear field documentation and appropriate use of omitempty tags.


10-33: Comprehensive result DTOs with good structure.

The separation between overall results (AutoUpdateResultDto) and per-resource results (AutoUpdateResourceResult) is well-designed. The JSON field names properly follow camelCase convention and match the frontend TypeScript interfaces.


35-44: Well-designed configuration DTO.

Good structure with clear field names and helpful comment indicating CheckInterval is in minutes.

frontend/src/lib/services/api/autoupdate-api-service.ts (1)

36-42: Clean implementation of dry run functionality.

The dryRun method provides a convenient way to perform update checks without applying changes. Good use of default parameter.

frontend/src/routes/compose/[composeId]/+page.svelte (2)

72-81: Well-implemented scroll-based header visibility.

Good use of Svelte's $effect with proper cleanup and browser check. The opacity and pointer-events transitions create a smooth UX.

Also applies to: 203-208


431-503: Excellent services grid implementation.

The responsive grid layout with distinct styling for created vs not-created services provides clear visual feedback. The hover effects and port count badges enhance the user experience.

backend/internal/services/image_maturity_service.go (2)

20-32: Good use of dependency injection pattern.

The integration of ContainerRegistryService through constructor injection is well implemented, following SOLID principles.


637-649: Correct handling of GORM result type.

The updated implementation properly handles the *gorm.DB result with appropriate error checking before accessing RowsAffected.

backend/internal/services/auto_update_service.go (2)

418-444: Well-implemented image update detection logic.

Good practices:

  • Correctly skips immutable digest-based images
  • Compares image IDs for accurate update detection
  • Provides helpful logging for debugging

598-625: Excellent handling of different label formats.

The method properly handles both map-based and list-based label formats, ensuring compatibility with different Docker Compose versions.

@kmendell kmendell merged commit 80f4ec8 into 1.0.0 Jul 2, 2025
1 check passed
@kmendell kmendell deleted the fix/auto-update-service branch July 2, 2025 21:34
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