feat(containers): add compose editor tab for compose-managed containers#5
Open
feat(containers): add compose editor tab for compose-managed containers#5
Conversation
…iners (getarcaneapp#1554) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ainerComposePanel component - Fix project lookup: search by name via getProjectsForEnvironment then fetch by ID, instead of incorrectly passing project name to getProject (which expects an ID) - Move project loading to +page.ts data loader (proper SvelteKit pattern) - Extract inline CodePanel usage into dedicated ContainerComposePanel.svelte component - Support editable compose file with save via projectService.updateProject - Show read-only alert for GitOps-managed projects - Use untrack() on initial state to satisfy Svelte 5 reactive reference rules - Link back to project page via ExternalLink button Closes getarcaneapp#1554
…-compose
When a project's compose.yml uses `include:` directives (a meta/wrapper compose),
the service definition lives in a sub-file — not the root compose. Showing and editing
the root compose from a container view is misleading and not useful.
Parse the project's composeContent with the yaml library to check whether
`services.{serviceName}` exists directly in the top-level services block.
If not, suppress the Compose tab entirely for that container.
Also tightens the info banner copy to drop the redundant
'Changes to this file affect all services' sentence (now always accurate since
we only show direct-service composes).
…ived not a stored function
$derived((): boolean => {...}) stores a function as the derived value; Svelte 5
doesn't track reactive reads (project, composeServiceName) when the stored function
is called later from inside tabItems. Use an IIFE inside $derived instead so the
boolean is computed directly and reactivity is properly tracked.
…including sub-files)
When a container belongs to a project with `include:` directives, find the
include file that directly defines the service and show/edit that instead of
the root wrapper compose.
- serviceComposeSource derived: scans root compose, then includeFiles[], to find
which file has `services.{serviceName}` defined
- Shows tab for both root-defined and include-file-defined services
- Hides tab only when the service isn't found in any file
- ContainerComposePanel now accepts optional `includeFile` prop
- Displays includeFile.content instead of project.composeContent
- Saves via projectService.updateProjectIncludeFile (relativePath + content)
- Falls back to updateProject for root compose
- fileTitle shows the actual file name (e.g. ollama/compose.yml)
- fileId scoped per include file so editor state doesn't collide
1256f3e to
788ba6c
Compare
- Add ComposeInfo to backend container Details response with Docker Compose metadata - Extract compose project/service info from labels in Go (backend-side processing) - Add i18n strings for all hardcoded text in ContainerComposePanel component - Simplify frontend logic to use composeInfo from API instead of label parsing - Fix Svelte reactivity pattern to properly track source content changes - Remove redundant Svelte effect antipattern per code review feedback Addresses code review feedback to move heavy lifting to backend and ensure proper internationalization coverage.
c19f751 to
678f8f2
Compare
…etarcaneapp#2056) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
….14.0 in /backend (getarcaneapp#2057) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…getarcaneapp#2058) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…etarcaneapp#2063) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…n remaining networks (getarcaneapp#2053)
Resolved conflict in types/container/container.go by keeping both: - ComposeInfo struct (from feature branch) - SummaryGroup struct (from upstream main) Both structs serve different purposes and can coexist without conflict.
…getarcaneapp#2059) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…nd (getarcaneapp#2061) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…etarcaneapp#2060) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
… 1.16.2 in /cli (getarcaneapp#2054) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…etarcaneapp#2055) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1. Add dirty tracking to prevent unsaved edits from being lost on data refresh
- Track isDirty state based on composeContent vs sourceContent
- Only update editor when source changes AND no unsaved edits exist
- Reset isDirty flag after successful save
2. Add 'Viewing' vs 'Editing' label for read-only mode
- Added container_compose_viewing_info i18n string
- Conditionally display 'Viewing' when isReadOnly is true
- Maintains consistent i18n coverage
3. Remove unused saveError state variable
- Errors are already surfaced via toast notifications
- Simplifies component state management
4. Add explicit pagination limit to project lookup
- Pass pagination: { page: 1, limit: 100 } to getProjectsForEnvironment
- Ensures compose tab appears even with many projects (>20)
- Prevents silently missing projects beyond default page size
Addresses automated review feedback from greptile-apps[bot].
…aneapp#2064) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kyle Mendell <ksm@ofkm.us>
- Move success toast before invalidateAll() to avoid misleading error on cache refresh failure - Pass actual root compose filename instead of hardcoding compose.yml
Co-authored-by: Felix <gitea@felixnuesse.de> Co-authored-by: Kyle Mendell <ksm@ofkm.us>
Extract duplicated compose editor UI (GitOps alert, info banner, save button, view project link, toast+invalidateAll logic) into a reusable ComposeEditorWrapper component in $lib/components/compose/. Update ContainerComposePanel to delegate to it via an onSave callback. Co-authored-by: Michael Kaltner <mkaltner@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ckend in the go_modules group across 1 directory (getarcaneapp#2098) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Compose tab to the individual container detail view. When a container belongs to an Arcane-managed project, the tab loads the relevant compose file — whether defined directly in the root compose or in an included sub-file — and allows viewing and editing it without leaving the container view.
Fixes: getarcaneapp#1554
Changes
Backend (
types/container/container.go)ComposeInfotype to structure Docker Compose metadataNewDetailsto extract compose information from container labels:com.docker.compose.project→projectNamecom.docker.compose.service→serviceNamecom.docker.compose.config-files→configFilecomposeInfofield in container Details response when labels existFrontend Types (
container.type.ts)ComposeInfointerface matching backend structureContainerDetailsDtowith optionalcomposeInfofieldInternationalization (
messages/en.json)Added i18n strings for all hardcoded text:
container_compose_gitops_managed_title: "GitOps Managed — Read Only"container_compose_gitops_managed_description: Parameterized alert descriptioncontainer_compose_editing_info: Editing info banner with file/project/service contextcontainer_compose_save_success: Success toast messagecontainer_compose_save_failed: Error toast messagecontainer_compose_view_project: Button label+page.tscontainer.composeInfo?.projectNameinstead of direct label access+page.sveltecontainer.composeInfofrom API response instead of accessing labels directlycomposeServiceNamefrom structuredcomposeInfoobjectcomposeInfoexistsContainerComposePanel.sveltem.*)composeContentwhen source actually changes@htmlfor parameterized messages with embedded formattingBehavior
updateProjectollama/compose.yml), saves viaupdateProjectIncludeFilecomposeInfo)Code Review Improvements
✅ Backend processing: Compose metadata extraction moved to Go (faster, reduces client load)
✅ i18n coverage: All UI strings now localized via paraglide messages
✅ Svelte best practices: Removed state-updating effects per Svelte 5 recommendations
✅ Simplified frontend: Uses structured API response instead of raw label parsing
PR Checklist
./scripts/development/dev.sh start)just lint frontendjust format frontend✅Manual Testing
include:-based project (e.g.ai-ollama-1→ollama/compose.yml)composeInfofield appears in API response when compose labels existAI Disclosure
AI Tool: Claude Code (Anthropic)
Assistance Level: Significant — implementation was AI-generated with human direction, review, and testing oversight per AI_POLICY.md