feat: implement config profile git mounts
- Add git_mounts column to config_profiles table (JSONB) - Create GitMount Pydantic models with validation - Add repo validation in create/update endpoints - Update profile resolver to merge git mounts from includes - Implement auto-clone, branch checkout, and glob expansion - Add parallel processing for git mount resolution - Create GitMountEditor frontend component - Update TypeScript types and API clients - Add CSS styles for git mount UI - Frontend type check and build pass Implements tasks 1.1-7.9 of config-profile-git-mounts spec
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Config profiles can reference git repositories for file mounting
|
||||
The system SHALL allow config profiles to include git repository mounts that bind repository paths into containers.
|
||||
|
||||
#### Scenario: Create profile with git mount
|
||||
- **WHEN** a user creates or updates a config profile with `git_mounts` entries
|
||||
- **THEN** the profile stores each git mount with:
|
||||
- `repo_id`: UUID of the referenced git repository
|
||||
- `source_path`: Path within the repository to mount (e.g., ".", "configs/")
|
||||
- `target_path`: Absolute path inside the container (e.g., "/home/user")
|
||||
- `branch`: Optional branch or tag name (defaults to repository default branch)
|
||||
|
||||
#### Scenario: Git mount validation
|
||||
- **WHEN** a profile with git mounts is saved
|
||||
- **THEN** the system validates that:
|
||||
- The referenced repository exists and belongs to the user's project
|
||||
- `source_path` is a relative path (no leading `/`)
|
||||
- `target_path` is an absolute path (starts with `/`)
|
||||
- `target_path` does not contain path traversal sequences (`..`)
|
||||
|
||||
#### Scenario: Profile with git mounts is resolved
|
||||
- **GIVEN** a config profile with git mounts referencing repository "dotfiles"
|
||||
- **WHEN** the profile is resolved for instance startup
|
||||
- **THEN** the resolved profile includes the git mounts with repository details:
|
||||
- Repository filesystem path
|
||||
- Resolved branch name
|
||||
- Source and target paths
|
||||
|
||||
#### Scenario: Git mount is applied at instance startup
|
||||
- **GIVEN** a resolved profile with git mounts
|
||||
- **WHEN** an instance is started with this profile
|
||||
- **THEN** for each git mount:
|
||||
- The repository filesystem path exists
|
||||
- The source path within the repository exists
|
||||
- A bind mount is created from `repo_path/source_path` to `container:target_path`
|
||||
- **AND** if the repository or path is missing, a warning is logged and the mount is skipped
|
||||
|
||||
### Requirement: Git mounts support glob patterns
|
||||
The system SHALL support glob patterns in `source_path` for matching multiple files.
|
||||
|
||||
#### Scenario: Mount files matching glob pattern
|
||||
- **GIVEN** a git mount with `source_path: "configs/**/*.json"`
|
||||
- **WHEN** the instance is started
|
||||
- **THEN** the system expands the glob pattern within the repository
|
||||
- **AND** creates individual bind mounts for each matched file
|
||||
- **AND** preserves directory structure relative to `target_path`
|
||||
|
||||
#### Scenario: Glob pattern matches nothing
|
||||
- **GIVEN** a git mount with `source_path: "nonexistent/**/*"`
|
||||
- **WHEN** the instance is started
|
||||
- **THEN** the system logs a warning that no files matched the pattern
|
||||
- **AND** the mount is skipped
|
||||
|
||||
#### Scenario: Glob pattern limit exceeded
|
||||
- **GIVEN** a git mount with `source_path: "**/*"` matching 500 files
|
||||
- **WHEN** the instance is started
|
||||
- **THEN** the system limits expansion to 100 files
|
||||
- **AND** logs a warning: "Glob pattern matched 500 files, limited to 100"
|
||||
|
||||
### Requirement: Git mounts trigger automatic cloning
|
||||
The system SHALL automatically clone referenced repositories if they do not exist locally.
|
||||
|
||||
#### Scenario: Repository not cloned at startup
|
||||
- **GIVEN** a git mount referencing a repository that has not been cloned
|
||||
- **WHEN** the instance is started
|
||||
- **THEN** the system triggers a clone operation using the repository's remote URL and SSH key
|
||||
- **AND** the clone proceeds asynchronously
|
||||
- **AND** instance startup continues once clone completes
|
||||
|
||||
#### Scenario: Clone failure handling
|
||||
- **GIVEN** a git mount referencing a repository with an invalid SSH key
|
||||
- **WHEN** the instance attempts to clone
|
||||
- **THEN** the clone operation fails
|
||||
- **AND** an error is logged with details
|
||||
- **AND** the mount is skipped
|
||||
- **AND** instance startup continues with remaining mounts
|
||||
|
||||
### Requirement: Git mounts support branch pinning
|
||||
The system SHALL support pinning git mounts to specific branches or tags.
|
||||
|
||||
#### Scenario: Mount specific branch
|
||||
- **GIVEN** a git mount with `branch: "develop"`
|
||||
- **WHEN** the instance is started
|
||||
- **THEN** the system attempts to checkout the "develop" branch in the repository
|
||||
- **AND** the bind mount uses the files from the checked-out branch
|
||||
|
||||
#### Scenario: Branch fallback to default
|
||||
- **GIVEN** a git mount with `branch: "nonexistent"`
|
||||
- **WHEN** the instance is started
|
||||
- **THEN** the system logs a warning that the branch does not exist
|
||||
- **AND** falls back to the repository's current/default branch
|
||||
- **AND** the bind mount proceeds with the fallback branch
|
||||
|
||||
### Requirement: Git mounts are visible in profile UI
|
||||
The system SHALL display git mounts in the config profile editor.
|
||||
|
||||
#### Scenario: View git mounts in profile editor
|
||||
- **GIVEN** a config profile with git mounts
|
||||
- **WHEN** the user views the profile in the UI
|
||||
- **THEN** the git mounts section displays each mount with:
|
||||
- Repository name
|
||||
- Source path within repository
|
||||
- Target path in container
|
||||
- Branch/tag (if specified)
|
||||
|
||||
#### Scenario: Add git mount via UI
|
||||
- **WHEN** a user adds a git mount in the profile editor
|
||||
- **THEN** they can:
|
||||
- Select from available repositories in the project
|
||||
- Specify the source path (with autocomplete or validation)
|
||||
- Specify the target path in the container
|
||||
- Optionally select a branch/tag
|
||||
|
||||
#### Scenario: Remove git mount via UI
|
||||
- **WHEN** a user removes a git mount from the profile editor
|
||||
- **THEN** the mount is removed from the profile
|
||||
- **AND** existing instances using this profile are unaffected
|
||||
|
||||
### Requirement: Git mounts are visible in profile preview
|
||||
The system SHALL include git mounts in the profile preview/resolve output.
|
||||
|
||||
#### Scenario: Preview shows git mount details
|
||||
- **GIVEN** a config profile with git mounts
|
||||
- **WHEN** the user requests a profile preview
|
||||
- **THEN** the preview includes a "git_mounts" section showing:
|
||||
- Repository name and URL
|
||||
- Source path (with expanded glob matches if applicable)
|
||||
- Target path in container
|
||||
- Resolved branch name
|
||||
- Clone status (exists, will clone, clone failed)
|
||||
|
||||
#### Scenario: Preview warns about missing repository
|
||||
- **GIVEN** a config profile with a git mount referencing a non-existent repository
|
||||
- **WHEN** the user requests a profile preview
|
||||
- **THEN** the preview shows a warning: "Repository [name] not found"
|
||||
- **AND** indicates that the mount will be skipped at startup
|
||||
Reference in New Issue
Block a user