Работает создание коммитов и перенос в новый enviroment

This commit is contained in:
2026-01-23 13:57:44 +03:00
parent e9d3f3c827
commit 07ec2d9797
37 changed files with 3227 additions and 252 deletions

View File

@@ -1,58 +1,93 @@
# API Contracts: Git Integration Plugin
## Git Configuration
**Feature**: Git Integration for Dashboard Development
**Date**: 2026-01-22
### `GET /api/git/config`
List all Git server configurations.
## Base Path
`/api/git`
### `POST /api/git/config`
Create a new Git server configuration.
- **Body**: `GitServerConfig` (Pydantic model)
## Endpoints
### `POST /api/git/config/test`
Test connection to a Git server.
- **Body**: `GitServerConfig`
- **Response**: `{"status": "success" | "error", "message": String}`
### 1. Configuration
## Repository & Branch Management
#### `GET /config/{dashboard_uuid}`
Retrieve Git configuration for a specific dashboard.
- **Response**: `GitServerConfig` (excluding full token)
### `GET /api/git/repositories/{dashboard_id}/branches`
List all branches for a dashboard's repository.
#### `POST /config`
Save or update Git configuration.
- **Request**: `GitServerConfig`
- **Response**: `GitServerConfig`
### `POST /api/git/repositories/{dashboard_id}/branches`
### 2. Repository Operations
#### `POST /init/{dashboard_uuid}`
Initialize/Clone the repository for the dashboard.
- **Request**: Empty (uses stored config)
- **Response**: `{ "status": "success", "message": "Repository cloned" }`
#### `GET /status/{dashboard_uuid}`
Get current status (changes between Superset export and local git HEAD).
- **Response**:
```json
{
"branch": "main",
"changes": [
{ "file_path": "charts/sales.yaml", "change_type": "MODIFIED" }
],
"is_clean": false
}
```
#### `POST /sync/{dashboard_uuid}`
Fetch latest dashboard export from Superset and unpack into the git working directory (overwriting local files to match Superset state).
- **Response**: `{ "status": "success", "changes_detected": true }`
### 3. Branch Management
#### `GET /branches/{dashboard_uuid}`
List all local and remote branches.
- **Response**: `List[Branch]`
#### `POST /branches/{dashboard_uuid}`
Create a new branch.
- **Body**: `{"name": String, "from_branch": String}`
- **Request**: `{ "name": "feature/new-chart", "source_branch": "main" }`
- **Response**: `Branch`
### `POST /api/git/repositories/{dashboard_id}/checkout`
Switch to a specific branch.
- **Body**: `{"name": String}`
#### `POST /checkout/{dashboard_uuid}`
Switch to a different branch. **Warning**: This updates the Superset Dashboard content to match the branch state!
- **Request**: `{ "branch_name": "main" }`
- **Response**: `{ "status": "success", "message": "Switched to main and updated dashboard" }`
## Git Operations
### 4. Commit & Push
### `POST /api/git/repositories/{dashboard_id}/commit`
Commit changes to the current branch.
- **Body**: `{"message": String, "files": List[String]}`
#### `POST /commit/{dashboard_uuid}`
Commit staged changes.
- **Request**: `{ "message": "Updated sales chart", "files": ["charts/sales.yaml"] }`
- **Response**: `Commit`
### `POST /api/git/repositories/{dashboard_id}/push`
Push local commits to remote.
#### `POST /push/{dashboard_uuid}`
Push commits to remote.
- **Response**: `{ "status": "success" }`
### `POST /api/git/repositories/{dashboard_id}/pull`
#### `POST /pull/{dashboard_uuid}`
Pull changes from remote.
- **Response**: `{ "status": "success", "updates": [...] }`
## Conflict Resolution
### 5. History
### `GET /api/git/repositories/{dashboard_id}/conflicts`
List active conflicts for a repository.
#### `GET /history/{dashboard_uuid}`
Get commit log.
- **Query Params**: `limit=20`, `branch=main`
- **Response**: `List[Commit]`
### `POST /api/git/repositories/{dashboard_id}/resolve`
Resolve a conflict for a specific file.
- **Body**: `{"file_path": String, "resolution": "mine" | "theirs" | "manual", "content": Optional[String]}`
### 6. Deployment
## Deployment
#### `GET /environments`
List configured target environments.
- **Response**: `List[Environment]`
### `GET /api/git/environments`
List deployment environments.
### `POST /api/git/repositories/{dashboard_id}/deploy`
Deploy dashboard from current branch to target environment.
- **Body**: `{"environment_id": UUID}`
#### `POST /deploy/{dashboard_uuid}`
Deploy current branch state to a target environment.
- **Request**: `{ "environment_id": "uuid", "commit_hash": "optional-hash" }`
- **Response**: `{ "status": "success", "job_id": "..." }`

View File

@@ -1,56 +1,76 @@
# Data Model: Git Integration Plugin
**Feature**: Git Integration for Dashboard Development
**Date**: 2026-01-22
## Entities
### GitServerConfig
- **id**: UUID (Primary Key)
- **name**: String (Display name)
- **provider**: Enum (GITHUB, GITLAB, GITEA)
- **url**: String (e.g., https://github.com)
- **pat**: String (Encrypted/Sensitive)
- **default_repository**: String (e.g., org/dashboards)
- **status**: Enum (CONNECTED, FAILED, UNKNOWN)
- **last_validated**: DateTime
### 1. GitServerConfig
Configuration for connecting a dashboard to a Git repository.
### GitRepository
- **id**: UUID (Primary Key)
- **dashboard_id**: Integer (Link to Superset Dashboard ID)
- **config_id**: UUID (FK to GitServerConfig)
- **remote_url**: String
- **local_path**: String (Relative to backend storage)
- **current_branch**: String
- **sync_status**: Enum (CLEAN, DIRTY, CONFLICT)
| Field | Type | Description |
|-------|------|-------------|
| `id` | UUID | Unique identifier |
| `dashboard_uuid` | UUID | The Superset Dashboard UUID this config applies to |
| `provider` | Enum | `GITHUB`, `GITLAB`, `GITEA`, `GENERIC` |
| `server_url` | String | Base URL of the git server (e.g., `https://gitlab.com`) |
| `repo_url` | String | Full HTTPS clone URL |
| `username` | String | Username for auth |
| `pat_token` | String | Personal Access Token (stored securely) |
| `created_at` | DateTime | Creation timestamp |
| `updated_at` | DateTime | Last update timestamp |
### Branch
- **name**: String
- **commit_hash**: String
- **is_remote**: Boolean
- **last_updated**: DateTime
### 2. Environment
Target environments for deployment.
### Commit
- **hash**: String (Primary Key)
- **author**: String
- **email**: String
- **timestamp**: DateTime
- **message**: String
- **files_changed**: List[String]
| Field | Type | Description |
|-------|------|-------------|
| `id` | UUID | Unique identifier |
| `name` | String | Display name (e.g., "Production", "Staging") |
| `superset_url` | String | Base URL of the target Superset instance |
| `auth_token` | String | Authentication token/credentials for the target API |
| `is_active` | Boolean | Whether this environment is enabled |
### Conflict
- **repository_id**: UUID (FK to GitRepository)
- **file_path**: String
- **our_content**: String
- **their_content**: String
- **base_content**: String
### 3. Branch (DTO)
Data Transfer Object representing a Git branch.
### DeploymentEnvironment
- **id**: UUID (Primary Key)
- **name**: String (e.g., Production, Staging)
- **superset_url**: String
- **superset_token**: String (Sensitive)
- **is_active**: Boolean
| Field | Type | Description |
|-------|------|-------------|
| `name` | String | Branch name (e.g., `main`, `feature/fix-chart`) |
| `is_current` | Boolean | True if currently checked out |
| `is_remote` | Boolean | True if it exists on remote |
| `last_commit_hash` | String | SHA of the tip commit |
| `last_commit_msg` | String | Message of the tip commit |
### 4. Commit (DTO)
Data Transfer Object representing a Git commit.
| Field | Type | Description |
|-------|------|-------------|
| `hash` | String | Full SHA hash |
| `short_hash` | String | First 7 chars of hash |
| `author_name` | String | Author name |
| `author_email` | String | Author email |
| `date` | DateTime | Commit timestamp |
| `message` | String | Commit message |
| `files_changed` | List[String] | List of modified files |
### 5. DashboardChange (DTO)
Represents a local change (diff) between Superset state and Git state.
| Field | Type | Description |
|-------|------|-------------|
| `file_path` | String | Relative path in repo |
| `change_type` | Enum | `ADDED`, `MODIFIED`, `DELETED`, `RENAMED` |
| `diff_content` | String | Unified diff string |
## Relationships
- **GitServerConfig** (1) <-> (*) **GitRepository**
- **GitRepository** (1) <-> (*) **Branch**
- **Branch** (1) <-> (*) **Commit**
- **GitRepository** (1) <-> (*) **DeploymentEnvironment** (Via deployment logs/config)
- **One-to-One**: `Dashboard` (Superset concept) <-> `GitServerConfig`.
- **Many-to-Many**: `Dashboard` <-> `Environment` (Technically environments are global or scoped, but for MVP they can be global settings available to all dashboards).
## Validation Rules
- `repo_url`: Must be a valid HTTPS URL ending in `.git`.
- `pat_token`: Must not be empty.
- `branch.name`: Must follow git branch naming conventions (no spaces, special chars).

View File

@@ -43,29 +43,23 @@ specs/[###-feature]/
```
### Source Code (repository root)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
```text
backend/
├── src/
│ ├── api/routes/git.py # Git integration endpoints
│ ├── models/git.py # Git-specific Pydantic/SQLAlchemy models
│ ├── plugins/git_plugin.py # PluginBase implementation
│ └── services/git_service.py # Core Git logic (GitPython wrapper)
│ ├── api/routes/git.py # Git integration endpoints
│ ├── models/git.py # Git-specific Pydantic/SQLAlchemy models (GitServerConfig, DashboardChange)
│ ├── plugins/git_plugin.py # PluginBase implementation (1 repo = 1 dashboard logic)
│ └── services/git_service.py # Core Git logic (GitPython wrapper)
└── tests/
└── plugins/test_git.py
frontend/
├── src/
│ ├── components/git/ # Git UI components (BranchSelector, CommitModal, ConflictResolver)
│ ├── routes/settings/git/ # Git configuration pages
│ └── services/gitService.js # API client for Git operations
└── tests/
│ ├── components/git/ # Git UI components (BranchSelector, CommitModal, ConflictResolver)
│ ├── routes/settings/git/ # Git configuration pages (+page.svelte)
│ └── services/gitService.js # API client for Git operations
```
**Structure Decision**: Web application structure as the project has both FastAPI backend and SvelteKit frontend.
@@ -81,22 +75,26 @@ frontend/
## Implementation Phases
### Phase 2: Backend Implementation (Plugin & Service)
1. **Git Service**: Implement `GitService` using `GitPython`. Focus on:
* Repo initialization and cloning.
1. **Data Models**: Implement `GitServerConfig`, `Branch`, `Commit`, `Environment`, and `DashboardChange` in `src/models/git.py`.
2. **Git Service**: Implement `GitService` using `GitPython`. Focus on:
* Repo initialization and cloning (1 repo per dashboard strategy).
* Branch management (list, create, checkout).
* Stage, commit, push, pull.
2. **Git Plugin**: Implement `GitPlugin(PluginBase)`.
* Integrate with `superset_tool` for exporting/importing dashboards.
* History retrieval and diff generation.
3. **Git Plugin**: Implement `GitPlugin(PluginBase)`.
* Integrate with `superset_tool` for exporting dashboards as unpacked YAML files (metadata, charts, datasets).
* Handle unpacking ZIP exports into the repo structure.
3. **API Routes**: Implement `/api/git/*` endpoints.
4. **API Routes**: Implement `/api/git/*` endpoints for config, sync, and history.
### Phase 3: Frontend Implementation
1. **Configuration UI**: Settings page for `GitServerConfig`.
1. **Configuration UI**: Settings page for `GitServerConfig` (Provider selection, PAT validation).
2. **Dashboard Integration**: Add Git controls to the Dashboard view.
* Branch selector.
* Commit/Push/Pull buttons.
3. **Conflict Resolution UI**: Implementation of "Keep Mine/Theirs" file picker.
* Branch selector (Create/Switch).
* Commit/Push/Pull buttons with status indicators.
* History viewer with search/filter.
3. **Conflict Resolution UI**: Implementation of "Keep Mine/Theirs" file picker for YAML content.
### Phase 4: Deployment Integration
1. **Environment Management**: CRUD for `DeploymentEnvironment`.
2. **Deployment Logic**: Trigger Superset Import API on target servers.
1. **Environment Management**: CRUD for `Environment` (Target Superset instances).
2. **Deployment Logic**: Implement deployment via Superset Import API (POST /api/v1/dashboard/import/).
* Handle zip packing from Git repo state before import.

View File

@@ -1,40 +1,43 @@
# Quickstart: Git Integration Plugin
# Quickstart: Git Integration for Dashboards
## Setup
## Prerequisites
- A running Superset instance.
- A Git repository (GitLab, GitHub, etc.) created for your dashboard.
- A Personal Access Token (PAT) with `repo` scope.
1. **Install Dependencies**:
```bash
cd backend && .venv/bin/pip install GitPython
```
## Setup Guide
2. **Configure Git Server**:
- Go to Settings -> Git Integration
- Click "Add Server"
- Select Provider (e.g., GitLab)
- Enter Server URL and Personal Access Token (PAT)
- Click "Test Connection" and "Save"
### 1. Configure Git Connection
1. Navigate to the **Git Integration** tab in the tools menu.
2. Select your Dashboard from the dropdown.
3. Enter your Git Provider details:
- **Repo URL**: `https://github.com/myorg/sales-dashboard.git`
- **Username**: `myuser`
- **PAT**: `ghp_xxxxxxxxxxxx`
4. Click **Save & Connect**. The system will clone the repository.
3. **Link Dashboard to Git**:
- Navigate to the Dashboard view
- Select a dashboard
- Click "Enable Git Integration"
- Select the Git server and provide repository path (e.g., `my-org/my-dashboard-repo`)
### 2. Development Workflow
## Common Workflows
#### Making Changes
1. Edit your dashboard in Superset as usual.
2. Go to the **Git Integration** panel.
3. Click **Sync Status**. This pulls the latest state from Superset and compares it with the Git repo.
4. You will see a list of changed files (e.g., `charts/my-chart.yaml`).
### Versioning Changes
1. Make changes to the dashboard in Superset.
2. In the Git Integration panel, click "Commit".
3. Enter a commit message and select files (metadata, charts, etc.).
4. Click "Push" to sync with remote.
#### Committing
1. Select the files you want to include.
2. Enter a commit message.
3. Click **Commit**.
### Branching
1. Click "New Branch".
2. Enter branch name (e.g., `feature/new-charts`).
3. The dashboard state is now tracked on this branch.
#### Pushing
1. Click **Push** to send your changes to the remote repository.
### Deployment
1. Ensure changes are committed and pushed.
2. Click "Deploy".
3. Select target environment (e.g., "Production").
4. Monitor deployment logs for success.
### 3. Branching
1. To work on a new feature, go to the **Branches** tab.
2. Enter a name (e.g., `feature/Q4-updates`) and click **Create Branch**.
3. The system automatically switches to this branch.
### 4. Deploying
1. Switch to the **Deploy** tab.
2. Select the target environment (e.g., "Production").
3. Click **Deploy**. The current version of the dashboard will be imported into the target environment.

View File

@@ -1,34 +1,74 @@
# Research: Git Integration Plugin
# Research & Decisions: Git Integration Plugin
## Unknowns & Clarifications
**Feature**: Git Integration for Dashboard Development
**Date**: 2026-01-22
**Status**: Finalized
1. **Git Library**: Should we use `GitPython` or call `git` CLI directly?
- **Decision**: Use `GitPython`.
- **Rationale**: It provides a high-level API for Git operations, making it easier to handle branches, commits, and remotes programmatically compared to parsing CLI output.
- **Alternatives considered**: `pygit2` (faster but requires libgit2), `subprocess.run(["git", ...])` (simple but brittle).
## 1. Unknowns & Clarifications
2. **Git Provider API Integration**: How to handle different providers (GitHub, GitLab, Gitea) for connection testing?
- **Decision**: Use a unified provider interface with provider-specific implementations.
- **Rationale**: While Git operations are standard, testing connections and potentially creating repositories might require provider-specific REST APIs.
- **Alternatives considered**: Generic Git clone test (slower, requires local disk space).
The following clarifications were resolved during the specification phase:
3. **Superset Export/Import**: How to handle the "unpacked" requirement?
- **Decision**: Use the existing `superset_tool` logic or similar to export as ZIP and then unpack to the Git directory.
- **Rationale**: Superset's native export is a ZIP. To fulfill FR-019, we must unpack this ZIP into the repository structure.
| Question | Answer | Implication |
|----------|--------|-------------|
| **Dashboard Content** | Unpacked Superset export (YAMLs for metadata, charts, datasets, DBs). | We need to use `superset_tool` or internal logic to unzip exports before committing, and zip them before importing/deploying. |
| **Repo Structure** | 1 Repository per Dashboard. | Simplifies conflict resolution (no cross-dashboard conflicts). Requires managing multiple local clones if multiple dashboards are edited. |
| **Deployment** | Import via Superset API. | Need to repackage the YAML files into a ZIP structure compatible with Superset Import API. |
| **Conflicts** | UI-based "Keep Mine / Keep Theirs". | We need a frontend diff viewer/resolver. |
| **Auth** | Personal Access Token (PAT). | Uniform auth mechanism for GitHub/GitLab/Gitea. |
4. **Merge Conflict UI**: How to implement "Keep Mine/Theirs" in a web UI?
- **Decision**: Implement a file-based conflict resolver in the Frontend.
- **Rationale**: Since the data is YAML, we can show a list of conflicting files and let the user pick the version.
- **Alternatives considered**: Full 3-way merge UI (too complex for MVP).
## 2. Technology Decisions
## Best Practices
### 2.1 Git Interaction Library
**Decision**: `GitPython`
**Rationale**:
- Mature and widely used Python wrapper for the `git` CLI.
- Supports all required operations (clone, fetch, pull, push, branch, commit, diff).
- Easier to handle output parsing compared to raw `subprocess` calls.
**Alternatives Considered**:
- `pygit2`: Bindings for `libgit2`. Faster but harder to install (binary dependencies) and more complex API.
- `subprocess.run(['git', ...])`: Too manual, error-prone parsing.
- **Security**: Never store PATs in plain text in logs. Use environment variables or encrypted storage if possible (though SQLite is the current project standard).
- **Concurrency**: Git operations on the same repository should be serialized to avoid index locks.
- **Repository Isolation**: Each dashboard gets its own directory/repository to prevent cross-dashboard pollution.
### 2.2 Dashboard Serialization Format
**Decision**: Unpacked YAML structure (Superset Export format)
**Rationale**:
- Superset exports dashboards as a ZIP containing YAML files.
- Unpacking this allows Git to track changes at a granular level (e.g., "changed x-axis label in chart A") rather than a binary blob change.
- Enables meaningful diffs and merge conflict resolution.
## Findings Consolidations
### 2.3 Repository Management Strategy
**Decision**: Local Clone Isolation
**Path**: `backend/data/git_repos/{dashboard_uuid}/`
**Rationale**:
- Each dashboard corresponds to a remote repository.
- Isolating clones by dashboard UUID prevents collisions.
- The backend acts as a bridge between the Superset instance (source of truth for "current state" in UI) and the Git repo (source of truth for version control).
- **Decision**: Use `GitPython` for core Git logic.
- **Decision**: Use Provider-specific API clients for connection validation.
- **Decision**: Unpack Superset exports into `dashboard/`, `charts/`, `datasets/`, `databases/` directories.
### 2.4 Authentication Storage
**Decision**: Encrypted storage in SQLite
**Rationale**:
- PATs are sensitive credentials.
- They should not be stored in plain text.
- We will use the existing `config_manager` or a new secure storage utility if available, or standard encryption if not. (For MVP, standard storage in SQLite `GitServerConfig` table is acceptable per current project standards, assuming internal tool usage).
## 3. Architecture Patterns
### 3.1 The "Bridge" Workflow
1. **Edit**: User edits dashboard in Superset UI.
2. **Sync/Stage**: User clicks "Git" in our plugin. Plugin fetches current dashboard export from Superset API, unpacks it to the local git repo working directory.
3. **Diff**: `git status` / `git diff` shows changes between Superset state and last commit.
4. **Commit**: User selects files and commits.
5. **Push**: Pushes to remote.
### 3.2 Deployment Workflow
1. **Select**: User selects target environment (another Superset instance).
2. **Package**: Plugin zips the current `HEAD` (or selected commit) of the repo.
3. **Upload**: Plugin POSTs the ZIP to the target environment's Import API.
## 4. Risks & Mitigations
- **Risk**: Superset Export format changes.
- *Mitigation*: We rely on the Superset version's export format. If it changes, the YAML structure changes, but Git will just see it as text changes. The Import API compatibility is the main constraint.
- **Risk**: Large repositories.
- *Mitigation*: We are doing 1 repo per dashboard, which naturally limits size.
- **Risk**: Concurrent edits.
- *Mitigation*: Git itself handles this via locking, but we should ensure our backend doesn't try to run parallel git ops on the same folder.

View File

@@ -1,83 +1,88 @@
# Tasks: Git Integration Plugin for Dashboard Development
# Tasks: Git Integration Plugin
Feature: 011-git-integration-dashboard
**Feature**: Git Integration for Dashboard Development
**Status**: Completed
**Total Tasks**: 35
## Phase 1: Setup
Goal: Initialize project structure and dependencies.
**Goal**: Initialize project structure and dependencies.
- [ ] T001 Add `GitPython` to `backend/requirements.txt`
- [ ] T002 Create git plugin directory structure in `backend/src/plugins/git/` and `frontend/src/components/git/`
- [x] T001 Install GitPython dependency in `backend/requirements.txt`
- [x] T002 Create backend directory structure (routes, models, plugins, services)
- [x] T003 Create frontend directory structure (components, routes, services)
## Phase 2: Foundational
Goal: Define data models and base classes for Git integration.
**Goal**: Implement core data models and service skeletons.
**Prerequisites**: Phase 1
- [ ] T003 [P] Create SQLAlchemy models for `GitServerConfig` and `GitRepository` in `backend/src/models/git.py`
- [ ] T004 [P] Create Pydantic schemas for Git entities in `backend/src/api/routes/git_schemas.py`
- [ ] T005 Implement `GitService` base logic (init, clone) in `backend/src/services/git_service.py`
- [ ] T006 Implement `GitPlugin(PluginBase)` skeleton in `backend/src/plugins/git_plugin.py`
- [x] T004 Create Git Pydantic models (Branch, Commit, DashboardChange) in `backend/src/api/routes/git_schemas.py`
- [x] T005 Create GitServerConfig and Environment SQLAlchemy models in `backend/src/models/git.py`
- [x] T006 Implement GitService class skeleton with GitPython init in `backend/src/services/git_service.py`
- [x] T007 Implement GitPlugin class skeleton inheriting PluginBase in `backend/src/plugins/git_plugin.py`
## Phase 3: User Story 1 - Configure Git Server Connection (P1)
Goal: Enable connection to Git servers (GitHub, GitLab, Gitea) via PAT.
Independent Test: Configure a Git server connection and verify "Test Connection" succeeds.
## Phase 3: User Story 1 - Configure Git Server (P1)
**Goal**: Enable users to configure and validate Git server connections.
**Prerequisites**: Phase 2
- [ ] T007 [US1] Implement Git provider connection validation logic in `backend/src/services/git_service.py`
- [ ] T008 [US1] Implement `/api/git/config` and `/api/git/config/test` endpoints in `backend/src/api/routes/git.py`
- [ ] T009 [P] [US1] Create Git configuration service in `frontend/src/services/gitService.js`
- [ ] T010 [US1] Implement Git server settings page in `frontend/src/routes/settings/git/+page.svelte`
- [x] T008 [US1] Implement `GitService.test_connection` method in `backend/src/services/git_service.py`
- [x] T009 [US1] Implement GET/POST `/api/git/config` endpoints in `backend/src/api/routes/git.py`
- [x] T010 [US1] Create `frontend/src/services/gitService.js` API client
- [x] T011 [US1] Create `frontend/src/components/tools/ConnectionForm.svelte` (or similar) for Git config
- [x] T012 [US1] Implement Settings page at `frontend/src/routes/settings/git/+page.svelte`
## Phase 4: User Story 2 - Dashboard Branch Management (P1)
Goal: Manage branches for dashboard repositories.
Independent Test: Create a new branch, switch to it, and verify the local repository state updates.
## Phase 4: User Story 2 - Branch Management (P1)
**Goal**: Enable creating and switching branches for dashboards.
**Prerequisites**: Phase 3
- [ ] T011 [US2] Implement branch listing and creation logic in `backend/src/services/git_service.py`
- [ ] T012 [US2] Implement branch checkout logic in `backend/src/services/git_service.py`
- [ ] T013 [US2] Implement branch management endpoints in `backend/src/api/routes/git.py`
- [ ] T014 [P] [US2] Create `BranchSelector` component in `frontend/src/components/git/BranchSelector.svelte`
- [ ] T015 [US2] Integrate branch management into Dashboard view in `frontend/src/pages/Dashboard.svelte`
- [x] T013 [US2] Implement `GitService` branch operations (list, create, checkout) in `backend/src/services/git_service.py`
- [x] T014 [US2] Implement `GitService.init_repo` (clone/init strategy) in `backend/src/services/git_service.py`
- [x] T015 [US2] Implement GET/POST `/api/git/branches` endpoints in `backend/src/api/routes/git.py`
- [x] T016 [US2] Implement POST `/api/git/checkout` endpoint in `backend/src/api/routes/git.py`
- [x] T017 [US2] Create `frontend/src/components/git/BranchSelector.svelte` component
- [x] T018 [US2] Update Dashboard page to include Git controls container
## Phase 5: User Story 3 - Dashboard Synchronization with Git (P1)
Goal: Commit, push, and pull dashboard changes.
Independent Test: Modify a dashboard, commit changes, push to remote, and verify changes on the Git server.
## Phase 5: User Story 3 - Synchronization (P1)
**Goal**: Enable committing, pushing, and pulling changes.
**Prerequisites**: Phase 4
- [ ] T016 [US3] Implement Superset export unpacking logic (YAML files) in `backend/src/plugins/git_plugin.py`
- [ ] T017 [US3] Implement commit, push, and pull logic in `backend/src/services/git_service.py`
- [ ] T018 [US3] Implement sync endpoints (commit, push, pull) in `backend/src/api/routes/git.py`
- [ ] T019 [P] [US3] Create `CommitModal` component in `frontend/src/components/git/CommitModal.svelte`
- [ ] T020 [US3] Implement sync controls (Commit/Push/Pull) in `frontend/src/pages/Dashboard.svelte`
- [ ] T021 [US3] Implement conflict detection and resolution logic in `backend/src/services/git_service.py`
- [ ] T022 [US3] Implement conflict resolution endpoints in `backend/src/api/routes/git.py`
- [ ] T023 [P] [US3] Create `ConflictResolver` component in `frontend/src/components/git/ConflictResolver.svelte`
- [x] T019 [US3] Implement Dashboard export/unpack logic (using SupersetClient/superset_tool) in `backend/src/plugins/git_plugin.py`
- [x] T020 [US3] Implement `GitService` status and diff generation methods in `backend/src/services/git_service.py`
- [x] T021 [US3] Implement `GitService` commit, push, and pull methods in `backend/src/services/git_service.py`
- [x] T022 [US3] Implement `/api/git/sync`, `/commit`, `/push`, `/pull` endpoints in `backend/src/api/routes/git.py`
- [x] T023 [US3] Create `frontend/src/components/git/CommitModal.svelte` with diff viewer
- [x] T024 [US3] Create `frontend/src/components/git/ConflictResolver.svelte` (Keep Mine/Theirs UI)
## Phase 6: User Story 4 - Environment Deployment (P2)
Goal: Deploy dashboard changes to target environments.
Independent Test: Select a target environment and trigger deployment, verifying the dashboard is updated on the target Superset instance.
## Phase 6: User Story 4 - Deployment (P2)
**Goal**: Deploy dashboard versions to target environments.
**Prerequisites**: Phase 5
- [ ] T024 [P] [US4] Implement `DeploymentEnvironment` model in `backend/src/models/git.py`
- [ ] T025 [US4] Implement deployment logic (Superset Import API) in `backend/src/plugins/git_plugin.py`
- [ ] T026 [US4] Implement deployment endpoints in `backend/src/api/routes/git.py`
- [ ] T027 [US4] Create environment management UI in `frontend/src/routes/settings/environments/+page.svelte`
- [ ] T028 [US4] Implement deployment trigger in `frontend/src/pages/Dashboard.svelte`
- [x] T025 [US4] Implement Environment CRUD endpoints in `backend/src/api/routes/git.py`
- [x] T026 [US4] Implement deployment logic (zip packing + Import API) in `backend/src/plugins/git_plugin.py`
- [x] T027 [US4] Implement POST `/api/git/deploy` endpoint in `backend/src/api/routes/git.py`
- [x] T028 [US4] Create Deployment modal/interface in `frontend/src/components/git/DeploymentModal.svelte`
## Phase 7: User Story 5 - Git History and Change Tracking (P3)
Goal: View dashboard commit history and changes.
Independent Test: Open the history view and verify the list of commits matches the Git repository history.
## Phase 7: User Story 5 - History (P3)
**Goal**: View commit history and audit changes.
**Prerequisites**: Phase 5
- [ ] T029 [US5] Implement commit history retrieval in `backend/src/services/git_service.py`
- [ ] T030 [US5] Implement history endpoint in `backend/src/api/routes/git.py`
- [ ] T031 [P] [US5] Create `CommitHistory` component in `frontend/src/components/git/CommitHistory.svelte`
- [x] T029 [US5] Implement `GitService.get_history` method in `backend/src/services/git_service.py`
- [x] T030 [US5] Implement GET `/api/git/history` endpoint in `backend/src/api/routes/git.py`
- [x] T031 [US5] Create `frontend/src/components/git/CommitHistory.svelte` component
- [x] T032 [US5] Integrate History viewer into Dashboard page
## Phase 8: Polish & Cross-cutting Concerns
- [ ] T032 Add error handling and loading states to all Git UI components
- [ ] T033 Implement offline mode checks for Git operations
- [ ] T034 Final integration testing of the complete Git workflow
## Phase 8: Polish & Cross-Cutting
**Goal**: Finalize error handling, UI feedback, and performance.
- [x] T033 Add comprehensive error handling for Git operations (timeouts, auth failures)
- [x] T034 Add loading states and progress indicators to all Git UI components
- [x] T035 Verify offline mode behavior and graceful degradation
## Dependencies
- US1 is a prerequisite for all other stories.
- US2 and US3 are closely related; US2 (branches) should precede US3 (sync).
- US4 depends on US3 (changes must be committed to be deployed).
- US5 is independent but requires commits to exist.
- US1 -> US2 -> US3 -> US4
- US3 -> US5
- US1 is the critical path.
## Implementation Strategy
1. **MVP**: Complete Phase 1-3 (Setup, Foundational, and US1) to allow Git server configuration.
2. **Core Workflow**: Complete Phase 4-5 (Branches and Sync) to enable version control.
3. **Extension**: Complete Phase 6-7 (Deployment and History).
- MVP: Complete US1, US2, and US3 (Configure, Branch, Sync). This allows local-only versioning if remote is optional, or full sync if remote is configured.
- Incremental: Add Deployment (US4) and History (US5) after core sync workflow is stable.