fix
This commit is contained in:
@@ -1,20 +1,17 @@
|
||||
// #region GitServiceClient [C:3] [TYPE Service] [SEMANTICS git, service, api, repository, branch]
|
||||
// @BRIEF API client for Git operations including repository management, branch operations, commits, merges, and deployments.
|
||||
// @BRIEF API client for Git operations — repository management, branches, commits, merges, deployments.
|
||||
// @LAYER Service
|
||||
// @RELATION DEPENDS_ON -> [ApiModule]
|
||||
|
||||
// #region GitServiceClient:Module [TYPE Function]
|
||||
/**
|
||||
* @SEMANTICS: git, service, api, client
|
||||
* @PURPOSE: API client for Git operations, managing the communication between frontend and backend.
|
||||
* @LAYER Service
|
||||
* @RELATION DEPENDS_ON -> specs/011-git-integration-dashboard/contracts/api.md
|
||||
*/
|
||||
|
||||
import { requestApi } from '../lib/api';
|
||||
|
||||
const API_BASE = '/git';
|
||||
|
||||
// #region buildDashboardRepoEndpoint [C:2] [TYPE Function]
|
||||
// @BRIEF Build /git/repositories/{ref}{suffix} endpoint with optional env_id query param.
|
||||
// @PRE dashboardRef is non-empty string.
|
||||
// @POST Returns absolute API endpoint path with env_id appended when envId is provided.
|
||||
// @DATA_CONTRACT Input(dashboardRef, suffix, envId?) -> Output(string)
|
||||
function buildDashboardRepoEndpoint(dashboardRef, suffix, envId = null) {
|
||||
const encodedRef = encodeURIComponent(String(dashboardRef));
|
||||
const endpoint = `${API_BASE}/repositories/${encodedRef}${suffix}`;
|
||||
@@ -22,140 +19,113 @@ function buildDashboardRepoEndpoint(dashboardRef, suffix, envId = null) {
|
||||
const sep = endpoint.includes('?') ? '&' : '?';
|
||||
return `${endpoint}${sep}env_id=${encodeURIComponent(String(envId))}`;
|
||||
}
|
||||
// #endregion buildDashboardRepoEndpoint
|
||||
|
||||
// #region gitService:Action [TYPE Function]
|
||||
// #region gitService [C:3] [TYPE Object]
|
||||
// @BRIEF Exported Git API client with methods for all repository and config operations.
|
||||
// @RELATION CALLS -> [ApiModule.requestApi]
|
||||
export const gitService = {
|
||||
/**
|
||||
* #region getConfigs:Function [TYPE Function]
|
||||
* @purpose Fetches all Git server configurations.
|
||||
* @pre User must be authenticated.
|
||||
* @post Returns a list of Git server configurations.
|
||||
* @returns {Promise<Array>} List of configs.
|
||||
*/
|
||||
|
||||
// #region getConfigs [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch all Git server configurations.
|
||||
// @PRE User is authenticated (handled by ApiModule auth headers).
|
||||
// @POST Returns list of GitServerConfig objects.
|
||||
// @DATA_CONTRACT None -> Array<GitServerConfig>
|
||||
async getConfigs() {
|
||||
console.log('[getConfigs][Action] Fetching Git configs');
|
||||
return requestApi(`${API_BASE}/config`);
|
||||
},
|
||||
// #endregion getConfigs
|
||||
|
||||
/**
|
||||
* #region createConfig:Function [TYPE Function]
|
||||
* @purpose Creates a new Git server configuration.
|
||||
* @pre Config object must be valid.
|
||||
* @post New config is created and returned.
|
||||
* @param {Object} config - Configuration details.
|
||||
* @returns {Promise<Object>} Created config.
|
||||
*/
|
||||
// #region createConfig [C:2] [TYPE Function]
|
||||
// @BRIEF Create a new Git server configuration.
|
||||
// @PRE config object is valid with required fields.
|
||||
// @POST New config is persisted and returned.
|
||||
// @DATA_CONTRACT Input(GitServerConfig) -> Output(GitServerConfig)
|
||||
async createConfig(config) {
|
||||
console.log('[createConfig][Action] Creating Git config');
|
||||
return requestApi(`${API_BASE}/config`, 'POST', config);
|
||||
},
|
||||
// #endregion createConfig
|
||||
|
||||
/**
|
||||
* #region deleteConfig:Function [TYPE Function]
|
||||
* @purpose Deletes an existing Git server configuration.
|
||||
* @pre configId must exist.
|
||||
* @post Config is deleted from the backend.
|
||||
* @param {string} configId - ID of the config to delete.
|
||||
* @returns {Promise<Object>} Result of deletion.
|
||||
*/
|
||||
// #region deleteConfig [C:2] [TYPE Function]
|
||||
// @BRIEF Delete an existing Git server configuration.
|
||||
// @PRE configId exists in the backend.
|
||||
// @POST Config is removed from the backend.
|
||||
async deleteConfig(configId) {
|
||||
console.log(`[deleteConfig][Action] Deleting Git config ${configId}`);
|
||||
return requestApi(`${API_BASE}/config/${configId}`, 'DELETE');
|
||||
},
|
||||
// #endregion deleteConfig
|
||||
|
||||
/**
|
||||
* #region updateConfig:Function [TYPE Function]
|
||||
* @purpose Updates an existing Git server configuration.
|
||||
* @pre configId must exist and configData must be valid.
|
||||
* @post Config is updated and returned.
|
||||
* @param {string} configId - ID of the config to update.
|
||||
* @param {Object} config - Updated configuration details.
|
||||
* @returns {Promise<Object>} Updated config.
|
||||
*/
|
||||
// #region updateConfig [C:2] [TYPE Function]
|
||||
// @BRIEF Update an existing Git server configuration.
|
||||
// @PRE configId exists and configData contains valid fields.
|
||||
// @POST Config is updated and returned.
|
||||
async updateConfig(configId, config) {
|
||||
console.log(`[updateConfig][Action] Updating Git config ${configId}`);
|
||||
return requestApi(`${API_BASE}/config/${configId}`, 'PUT', config);
|
||||
},
|
||||
// #endregion updateConfig
|
||||
|
||||
/**
|
||||
* #region testConnection:Function [TYPE Function]
|
||||
* @purpose Tests the connection to a Git server with provided credentials.
|
||||
* @pre Config must contain valid URL and PAT.
|
||||
* @post Returns connection status (success/failure).
|
||||
* @param {Object} config - Configuration to test.
|
||||
* @returns {Promise<Object>} Connection test result.
|
||||
*/
|
||||
// #region testConnection [C:2] [TYPE Function]
|
||||
// @BRIEF Test connection to a Git server with provided credentials.
|
||||
// @PRE config contains valid URL and PAT.
|
||||
// @POST Returns connection status (success/failure).
|
||||
// @DATA_CONTRACT Input(GitServerConfig) -> Output({status: string})
|
||||
async testConnection(config) {
|
||||
console.log('[testConnection][Action] Testing Git connection');
|
||||
return requestApi(`${API_BASE}/config/test`, 'POST', config);
|
||||
},
|
||||
// #endregion testConnection
|
||||
|
||||
/**
|
||||
* #region listGiteaRepositories:Function [TYPE Function]
|
||||
* @purpose Lists repositories on Gitea for a saved Git configuration.
|
||||
* @pre configId must reference a GITEA config.
|
||||
* @post Returns repository metadata.
|
||||
* @param {string} configId - Git configuration ID.
|
||||
* @returns {Promise<Array>} List of Gitea repositories.
|
||||
*/
|
||||
// #region listGiteaRepositories [C:2] [TYPE Function]
|
||||
// @BRIEF List repositories on Gitea for a saved Git configuration.
|
||||
// @PRE configId references a GITEA provider config.
|
||||
// @POST Returns array of Gitea repository metadata.
|
||||
async listGiteaRepositories(configId) {
|
||||
console.log(`[listGiteaRepositories][Action] Listing Gitea repositories for config ${configId}`);
|
||||
return requestApi(`${API_BASE}/config/${configId}/gitea/repos`);
|
||||
},
|
||||
// #endregion listGiteaRepositories
|
||||
|
||||
/**
|
||||
* #region createGiteaRepository:Function [TYPE Function]
|
||||
* @purpose Creates a new repository on Gitea for a saved Git configuration.
|
||||
* @pre configId must reference a GITEA config.
|
||||
* @post Repository is created on Gitea.
|
||||
* @param {string} configId - Git configuration ID.
|
||||
* @param {Object} payload - {name, private, description, auto_init, default_branch}
|
||||
* @returns {Promise<Object>} Created repository payload.
|
||||
*/
|
||||
// #region createGiteaRepository [C:2] [TYPE Function]
|
||||
// @BRIEF Create a repository on Gitea for a saved Git configuration.
|
||||
// @PRE configId references a GITEA config; payload has non-empty name.
|
||||
// @POST Repository created on Gitea; returns created repo metadata.
|
||||
async createGiteaRepository(configId, payload) {
|
||||
console.log(`[createGiteaRepository][Action] Creating Gitea repository ${payload?.name} for config ${configId}`);
|
||||
return requestApi(`${API_BASE}/config/${configId}/gitea/repos`, 'POST', payload);
|
||||
},
|
||||
// #endregion createGiteaRepository
|
||||
|
||||
/**
|
||||
* #region createRemoteRepository:Function [TYPE Function]
|
||||
* @purpose Creates repository on remote provider selected by Git config.
|
||||
* @pre configId exists and points to supported provider config.
|
||||
* @post Remote repository created and normalized payload returned.
|
||||
* @param {string} configId - Git configuration ID.
|
||||
* @param {Object} payload - {name, private, description, auto_init, default_branch}
|
||||
* @returns {Promise<Object>} Created remote repository payload.
|
||||
*/
|
||||
// #region createRemoteRepository [C:2] [TYPE Function]
|
||||
// @BRIEF Create repository on remote provider selected by Git config (idempotent: returns existing on 409).
|
||||
// @PRE configId exists and points to supported provider; payload has non-empty name.
|
||||
// @POST Remote repository created (or existing returned); normalized payload returned.
|
||||
// @DATA_CONTRACT Input(configId, RemoteRepoCreatePayload) -> Output(RemoteRepoSchema)
|
||||
async createRemoteRepository(configId, payload) {
|
||||
console.log(`[createRemoteRepository][Action] Creating remote repository ${payload?.name} for config ${configId}`);
|
||||
return requestApi(`${API_BASE}/config/${configId}/repositories`, 'POST', payload);
|
||||
},
|
||||
// #endregion createRemoteRepository
|
||||
|
||||
/**
|
||||
* #region deleteGiteaRepository:Function [TYPE Function]
|
||||
* @purpose Deletes a repository on Gitea for a saved Git configuration.
|
||||
* @pre configId must reference a GITEA config.
|
||||
* @post Repository is deleted on Gitea.
|
||||
* @param {string} configId - Git configuration ID.
|
||||
* @param {string} owner - Repository owner.
|
||||
* @param {string} repoName - Repository name.
|
||||
* @returns {Promise<Object>} Deletion result.
|
||||
*/
|
||||
// #region deleteGiteaRepository [C:2] [TYPE Function]
|
||||
// @BRIEF Delete a repository on Gitea for a saved Git configuration.
|
||||
// @PRE configId references a GITEA config; owner and repoName are non-empty.
|
||||
// @POST Repository deleted on Gitea server.
|
||||
async deleteGiteaRepository(configId, owner, repoName) {
|
||||
console.log(`[deleteGiteaRepository][Action] Deleting Gitea repository ${owner}/${repoName} for config ${configId}`);
|
||||
return requestApi(`${API_BASE}/config/${configId}/gitea/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repoName)}`, 'DELETE');
|
||||
},
|
||||
// #endregion deleteGiteaRepository
|
||||
|
||||
/**
|
||||
* #region initRepository:Function [TYPE Function]
|
||||
* @purpose Initializes or clones a Git repository for a dashboard.
|
||||
* @pre Dashboard must exist and config_id must be valid.
|
||||
* @post Repository is initialized on the backend.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @param {string} configId - ID of the Git config.
|
||||
* @param {string} remoteUrl - URL of the remote repository.
|
||||
* @returns {Promise<Object>} Initialization result.
|
||||
*/
|
||||
// #region initRepository [C:3] [TYPE Function]
|
||||
// @BRIEF Initialize or clone a Git repository for a dashboard.
|
||||
// @PRE dashboardRef is non-empty; configId and remoteUrl are valid; envId required when ref is slug.
|
||||
// @POST Repository initialized on the backend; GitRepository record created.
|
||||
// @DATA_CONTRACT Input(dashboardRef, configId, remoteUrl, envId?) -> Output({status: string, message: string})
|
||||
// @RELATION CALLS -> [ApiModule.requestApi]
|
||||
async initRepository(dashboardRef, configId, remoteUrl, envId = null) {
|
||||
console.log(`[initRepository][Action] Initializing repo for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/init', envId), 'POST', {
|
||||
@@ -163,43 +133,32 @@ export const gitService = {
|
||||
remote_url: remoteUrl
|
||||
});
|
||||
},
|
||||
// #endregion initRepository
|
||||
|
||||
/**
|
||||
* #region getRepositoryBinding:Function [TYPE Function]
|
||||
* @purpose Fetches repository binding metadata (config/provider) for dashboard.
|
||||
* @pre Repository should be initialized for dashboard.
|
||||
* @post Returns provider and config details for current repository.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @returns {Promise<Object>} Repository binding payload.
|
||||
*/
|
||||
// #region getRepositoryBinding [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch repository binding metadata (config/provider) for a dashboard.
|
||||
// @PRE Repository should be initialized for the dashboard.
|
||||
// @POST Returns provider, config_id, remote_url, local_path.
|
||||
async getRepositoryBinding(dashboardRef, envId = null) {
|
||||
console.log(`[getRepositoryBinding][Action] Fetching repository binding for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '', envId));
|
||||
},
|
||||
// #endregion getRepositoryBinding
|
||||
|
||||
/**
|
||||
* #region getBranches:Function [TYPE Function]
|
||||
* @purpose Retrieves the list of branches for a dashboard's repository.
|
||||
* @pre Repository must be initialized.
|
||||
* @post Returns a list of branches.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @returns {Promise<Array>} List of branches.
|
||||
*/
|
||||
// #region getBranches [C:2] [TYPE Function]
|
||||
// @BRIEF List all branches for a dashboard's repository.
|
||||
// @PRE Repository must be initialized; envId required when dashboardRef is a slug.
|
||||
// @POST Returns array of BranchSchema objects.
|
||||
async getBranches(dashboardRef, envId = null) {
|
||||
console.log(`[getBranches][Action] Fetching branches for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/branches', envId));
|
||||
},
|
||||
// #endregion getBranches
|
||||
|
||||
/**
|
||||
* #region createBranch:Function [TYPE Function]
|
||||
* @purpose Creates a new branch in the dashboard's repository.
|
||||
* @pre Source branch must exist.
|
||||
* @post New branch is created.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @param {string} name - New branch name.
|
||||
* @param {string} fromBranch - Source branch name.
|
||||
* @returns {Promise<Object>} Creation result.
|
||||
*/
|
||||
// #region createBranch [C:2] [TYPE Function]
|
||||
// @BRIEF Create a new branch in the dashboard's repository.
|
||||
// @PRE Source branch exists; name is non-empty; envId required when ref is slug.
|
||||
// @POST New branch is created on the backend.
|
||||
async createBranch(dashboardRef, name, fromBranch, envId = null) {
|
||||
console.log(`[createBranch][Action] Creating branch ${name} for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/branches', envId), 'POST', {
|
||||
@@ -207,192 +166,145 @@ export const gitService = {
|
||||
from_branch: fromBranch
|
||||
});
|
||||
},
|
||||
// #endregion createBranch
|
||||
|
||||
/**
|
||||
* #region checkoutBranch:Function [TYPE Function]
|
||||
* @purpose Switches the repository to a different branch.
|
||||
* @pre Target branch must exist.
|
||||
* @post Repository head is moved to the target branch.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @param {string} name - Branch name to checkout.
|
||||
* @returns {Promise<Object>} Checkout result.
|
||||
*/
|
||||
// #region checkoutBranch [C:2] [TYPE Function]
|
||||
// @BRIEF Switch the repository to a different branch.
|
||||
// @PRE Target branch exists; envId required when ref is slug.
|
||||
// @POST Repository HEAD is moved to the target branch.
|
||||
async checkoutBranch(dashboardRef, name, envId = null) {
|
||||
console.log(`[checkoutBranch][Action] Checking out branch ${name} for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/checkout', envId), 'POST', { name });
|
||||
},
|
||||
// #endregion checkoutBranch
|
||||
|
||||
/**
|
||||
* #region commit:Function [TYPE Function]
|
||||
* @purpose Stages and commits changes to the repository.
|
||||
* @pre Message must not be empty.
|
||||
* @post Changes are committed to the current branch.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @param {string} message - Commit message.
|
||||
* @param {Array} files - Optional list of files to commit.
|
||||
* @returns {Promise<Object>} Commit result.
|
||||
*/
|
||||
// #region commit [C:2] [TYPE Function]
|
||||
// @BRIEF Stage and commit changes to the repository.
|
||||
// @PRE message is non-empty; envId required when ref is slug.
|
||||
// @POST Changes are committed to the current branch.
|
||||
async commit(dashboardRef, message, files, envId = null) {
|
||||
console.log(`[commit][Action] Committing changes for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/commit', envId), 'POST', { message, files });
|
||||
},
|
||||
// #endregion commit
|
||||
|
||||
/**
|
||||
* #region push:Function [TYPE Function]
|
||||
* @purpose Pushes local commits to the remote repository.
|
||||
* @pre Remote must be configured and accessible.
|
||||
* @post Remote is updated with local commits.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @returns {Promise<Object>} Push result.
|
||||
*/
|
||||
// #region push [C:2] [TYPE Function]
|
||||
// @BRIEF Push local commits to the remote repository.
|
||||
// @PRE Remote 'origin' is configured and accessible; envId required when ref is slug.
|
||||
// @POST Remote is updated with local commits.
|
||||
async push(dashboardRef, envId = null) {
|
||||
console.log(`[push][Action] Pushing changes for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/push', envId), 'POST');
|
||||
},
|
||||
// #endregion push
|
||||
|
||||
/**
|
||||
* #region deleteRepository:Function [TYPE Function]
|
||||
* @purpose Deletes local repository binding and workspace for dashboard.
|
||||
* @pre Dashboard reference must resolve on backend.
|
||||
* @post Repository record and local folder are removed.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @returns {Promise<Object>} Deletion result.
|
||||
*/
|
||||
// #region deleteRepository [C:2] [TYPE Function]
|
||||
// @BRIEF Delete local repository binding and workspace for a dashboard.
|
||||
// @PRE dashboardRef resolves on backend; envId required when ref is slug.
|
||||
// @POST Repository record and local folder are removed.
|
||||
async deleteRepository(dashboardRef, envId = null) {
|
||||
console.log(`[deleteRepository][Action] Deleting repository for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '', envId), 'DELETE');
|
||||
},
|
||||
// #endregion deleteRepository
|
||||
|
||||
/**
|
||||
* #region pull:Function [TYPE Function]
|
||||
* @purpose Pulls changes from the remote repository.
|
||||
* @pre Remote must be configured and accessible.
|
||||
* @post Local repository is updated with remote changes.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @returns {Promise<Object>} Pull result.
|
||||
*/
|
||||
// #region pull [C:2] [TYPE Function]
|
||||
// @BRIEF Pull changes from the remote repository.
|
||||
// @PRE Remote 'origin' is configured and accessible; envId required when ref is slug.
|
||||
// @POST Local repository is updated with remote changes.
|
||||
async pull(dashboardRef, envId = null) {
|
||||
console.log(`[pull][Action] Pulling changes for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/pull', envId), 'POST');
|
||||
},
|
||||
// #endregion pull
|
||||
|
||||
/**
|
||||
* #region getMergeStatus:Function [TYPE Function]
|
||||
* @purpose Retrieves unfinished-merge status for repository.
|
||||
* @pre Repository must exist.
|
||||
* @post Returns merge status payload.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @returns {Promise<Object>} Merge status details.
|
||||
*/
|
||||
// #region getMergeStatus [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch unfinished-merge status for a repository.
|
||||
// @PRE Repository must exist; envId required when ref is slug.
|
||||
// @POST Returns merge status payload with has_unfinished_merge flag.
|
||||
async getMergeStatus(dashboardRef, envId = null) {
|
||||
console.log(`[getMergeStatus][Action] Fetching merge status for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/merge/status', envId));
|
||||
},
|
||||
// #endregion getMergeStatus
|
||||
|
||||
/**
|
||||
* #region getMergeConflicts:Function [TYPE Function]
|
||||
* @purpose Retrieves merge conflicts list for repository.
|
||||
* @pre Unfinished merge should be in progress.
|
||||
* @post Returns conflict files with mine/theirs previews.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @returns {Promise<Array>} List of conflict files.
|
||||
*/
|
||||
// #region getMergeConflicts [C:2] [TYPE Function]
|
||||
// @BRIEF List merge conflicts for a repository with unresolved merge.
|
||||
// @PRE Unfinished merge is in progress; envId required when ref is slug.
|
||||
// @POST Returns array of conflict file entries with mine/theirs previews.
|
||||
async getMergeConflicts(dashboardRef, envId = null) {
|
||||
console.log(`[getMergeConflicts][Action] Fetching merge conflicts for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/merge/conflicts', envId));
|
||||
},
|
||||
// #endregion getMergeConflicts
|
||||
|
||||
/**
|
||||
* #region resolveMergeConflicts:Function [TYPE Function]
|
||||
* @purpose Applies conflict resolution strategies and stages resolved files.
|
||||
* @pre resolutions contains file_path/resolution entries.
|
||||
* @post Conflicts are resolved and staged.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @param {Array} resolutions - Resolution entries.
|
||||
* @returns {Promise<Object>} Resolve result.
|
||||
*/
|
||||
// #region resolveMergeConflicts [C:2] [TYPE Function]
|
||||
// @BRIEF Apply conflict resolution strategies and stage resolved files.
|
||||
// @PRE resolutions array contains file_path and resolution entries; envId required when ref is slug.
|
||||
// @POST Conflicts are resolved and staged.
|
||||
async resolveMergeConflicts(dashboardRef, resolutions, envId = null) {
|
||||
console.log(`[resolveMergeConflicts][Action] Resolving ${Array.isArray(resolutions) ? resolutions.length : 0} conflicts for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/merge/resolve', envId), 'POST', {
|
||||
resolutions: Array.isArray(resolutions) ? resolutions : []
|
||||
});
|
||||
},
|
||||
// #endregion resolveMergeConflicts
|
||||
|
||||
/**
|
||||
* #region abortMerge:Function [TYPE Function]
|
||||
* @purpose Aborts current unfinished merge.
|
||||
* @pre Repository exists.
|
||||
* @post Merge state is aborted or reported as absent.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @returns {Promise<Object>} Abort operation result.
|
||||
*/
|
||||
// #region abortMerge [C:2] [TYPE Function]
|
||||
// @BRIEF Abort current unfinished merge.
|
||||
// @PRE Repository exists; envId required when ref is slug.
|
||||
// @POST Merge state is aborted or reported as absent.
|
||||
async abortMerge(dashboardRef, envId = null) {
|
||||
console.log(`[abortMerge][Action] Aborting merge for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/merge/abort', envId), 'POST');
|
||||
},
|
||||
// #endregion abortMerge
|
||||
|
||||
/**
|
||||
* #region continueMerge:Function [TYPE Function]
|
||||
* @purpose Finalizes unfinished merge by creating merge commit.
|
||||
* @pre All conflicts are resolved.
|
||||
* @post Merge commit is created.
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @param {string} message - Optional commit message.
|
||||
* @returns {Promise<Object>} Continue result.
|
||||
*/
|
||||
// #region continueMerge [C:2] [TYPE Function]
|
||||
// @BRIEF Finalize unfinished merge by creating a merge commit.
|
||||
// @PRE All conflicts are resolved; envId required when ref is slug.
|
||||
// @POST Merge commit is created.
|
||||
async continueMerge(dashboardRef, message = '', envId = null) {
|
||||
console.log(`[continueMerge][Action] Continuing merge for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/merge/continue', envId), 'POST', {
|
||||
message: String(message || '').trim() || null
|
||||
});
|
||||
},
|
||||
// #endregion continueMerge
|
||||
|
||||
/**
|
||||
* #region getEnvironments:Function [TYPE Function]
|
||||
* @purpose Retrieves available deployment environments.
|
||||
* @post Returns a list of environments.
|
||||
* @returns {Promise<Array>} List of environments.
|
||||
*/
|
||||
// #region getEnvironments [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch available deployment environments from Git config.
|
||||
// @POST Returns list of environment objects.
|
||||
async getEnvironments() {
|
||||
console.log('[getEnvironments][Action] Fetching environments');
|
||||
return requestApi(`${API_BASE}/environments`);
|
||||
},
|
||||
// #endregion getEnvironments
|
||||
|
||||
/**
|
||||
* #region deploy:Function [TYPE Function]
|
||||
* @purpose Deploys a dashboard to a target environment.
|
||||
* @pre Environment must be active and accessible.
|
||||
* @post Dashboard is imported into the target Superset instance.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @param {string} environmentId - ID of the target environment.
|
||||
* @returns {Promise<Object>} Deployment result.
|
||||
*/
|
||||
// #region deploy [C:2] [TYPE Function]
|
||||
// @BRIEF Deploy a dashboard to a target environment.
|
||||
// @PRE Environment must be active and accessible; envId required when ref is slug.
|
||||
// @POST Dashboard is imported into target Superset instance.
|
||||
async deploy(dashboardRef, environmentId, envId = null) {
|
||||
console.log(`[deploy][Action] Deploying dashboard ${dashboardRef} to environment ${environmentId}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/deploy', envId), 'POST', {
|
||||
environment_id: environmentId
|
||||
});
|
||||
},
|
||||
// #endregion deploy
|
||||
|
||||
/**
|
||||
* #region getHistory:Function [TYPE Function]
|
||||
* @purpose Retrieves the commit history for a dashboard.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @param {number} limit - Maximum number of commits to return.
|
||||
* @returns {Promise<Array>} List of commits.
|
||||
*/
|
||||
// #region getHistory [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch commit history for a dashboard repository.
|
||||
// @POST Returns list of commits with author, date, message.
|
||||
async getHistory(dashboardRef, limit = 50, envId = null) {
|
||||
console.log(`[getHistory][Action] Fetching history for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, `/history?limit=${limit}`, envId));
|
||||
},
|
||||
// #endregion getHistory
|
||||
|
||||
/**
|
||||
* #region sync:Function [TYPE Function]
|
||||
* @purpose Synchronizes the local dashboard state with the Git repository.
|
||||
* @param {number} dashboardId - ID of the dashboard.
|
||||
* @param {string|null} sourceEnvId - Optional source environment ID.
|
||||
* @returns {Promise<Object>} Sync result.
|
||||
*/
|
||||
// #region sync [C:2] [TYPE Function]
|
||||
// @BRIEF Synchronize local dashboard state with Git repository.
|
||||
// @POST Dashboard state is synced to Git workspace.
|
||||
async sync(dashboardRef, sourceEnvId = null, envId = null) {
|
||||
console.log(`[sync][Action] Syncing dashboard ${dashboardRef}`);
|
||||
const params = new URLSearchParams();
|
||||
@@ -402,45 +314,34 @@ export const gitService = {
|
||||
const endpoint = `${API_BASE}/repositories/${encodeURIComponent(String(dashboardRef))}/sync${query ? `?${query}` : ''}`;
|
||||
return requestApi(endpoint, 'POST');
|
||||
},
|
||||
// #endregion sync
|
||||
|
||||
/**
|
||||
* #region getStatus:Function [TYPE Function]
|
||||
* @purpose Fetches the current Git status for a dashboard repository.
|
||||
* @pre dashboardId must be a valid integer.
|
||||
* @post Returns a status object with dirty files and branch info.
|
||||
* @param {number} dashboardId - The ID of the dashboard.
|
||||
* @returns {Promise<Object>} Status details.
|
||||
*/
|
||||
// #region getStatus [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch current Git status for a dashboard repository (dirty files, branch info).
|
||||
// @PRE Repository path exists on disk; envId required when ref is slug.
|
||||
// @POST Returns status payload with is_dirty, staged_files, modified_files, current_branch.
|
||||
async getStatus(dashboardRef, envId = null) {
|
||||
console.log(`[getStatus][Action] Fetching status for dashboard ${dashboardRef}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/status', envId));
|
||||
},
|
||||
// #endregion getStatus
|
||||
|
||||
/**
|
||||
* #region getStatusesBatch:Function [TYPE Function]
|
||||
* @purpose Fetches Git statuses for multiple dashboards in a single request.
|
||||
* @pre dashboardIds must be an array of dashboard IDs.
|
||||
* @post Returns a map of dashboard_id -> status payload.
|
||||
* @param {Array<number>} dashboardIds - Dashboard IDs.
|
||||
* @returns {Promise<Object>} Batch status response.
|
||||
*/
|
||||
// #region getStatusesBatch [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch Git statuses for multiple dashboards in one batch request.
|
||||
// @PRE dashboardIds is a non-empty array of numeric IDs.
|
||||
// @POST Returns a map of dashboard_id -> status payload (with NO_REPO for uninitialized).
|
||||
async getStatusesBatch(dashboardIds) {
|
||||
console.log(`[getStatusesBatch][Action] Fetching statuses for ${dashboardIds.length} dashboards`);
|
||||
return requestApi(`${API_BASE}/repositories/status/batch`, 'POST', {
|
||||
dashboard_ids: dashboardIds
|
||||
});
|
||||
},
|
||||
// #endregion getStatusesBatch
|
||||
|
||||
/**
|
||||
* #region getDiff:Function [TYPE Function]
|
||||
* @purpose Retrieves the diff for specific files or the whole repository.
|
||||
* @pre dashboardId must be a valid integer.
|
||||
* @post Returns the Git diff string.
|
||||
* @param {number} dashboardId - The ID of the dashboard.
|
||||
* @param {string|null} filePath - Optional specific file path.
|
||||
* @param {boolean} staged - Whether to show staged changes.
|
||||
* @returns {Promise<string>} The diff content.
|
||||
*/
|
||||
// #region getDiff [C:2] [TYPE Function]
|
||||
// @BRIEF Fetch Git diff for a dashboard repository (staged or unstaged).
|
||||
// @PRE Repository path exists; envId required when ref is slug.
|
||||
// @POST Returns unified diff string.
|
||||
async getDiff(dashboardRef, filePath = null, staged = false, envId = null) {
|
||||
console.log(`[getDiff][Action] Fetching diff for dashboard ${dashboardRef} (file: ${filePath}, staged: ${staged})`);
|
||||
let endpoint = `${API_BASE}/repositories/${encodeURIComponent(String(dashboardRef))}/diff`;
|
||||
@@ -451,23 +352,17 @@ export const gitService = {
|
||||
if (params.toString()) endpoint += `?${params.toString()}`;
|
||||
return requestApi(endpoint);
|
||||
},
|
||||
// #endregion getDiff
|
||||
|
||||
/**
|
||||
* #region promote:Function [TYPE Function]
|
||||
* @purpose Promotes changes between branches via MR or direct merge.
|
||||
* @pre Dashboard repository must be initialized.
|
||||
* @post Returns promotion metadata (MR URL or direct merge status).
|
||||
* @param {string|number} dashboardRef - Dashboard slug or id.
|
||||
* @param {Object} payload - {from_branch,to_branch,mode,title,description,reason,draft,remove_source_branch}
|
||||
* @param {string|null} envId - Environment id for slug resolution.
|
||||
* @returns {Promise<Object>} Promotion result.
|
||||
*/
|
||||
// #region promote [C:2] [TYPE Function]
|
||||
// @BRIEF Promote changes between branches via MR or direct merge.
|
||||
// @PRE Dashboard repository initialized; from_branch and to_branch differ; envId required when ref is slug.
|
||||
// @POST Returns MR URL (MR mode) or merge status (direct mode).
|
||||
async promote(dashboardRef, payload, envId = null) {
|
||||
console.log(`[promote][Action] Promoting ${payload?.from_branch} -> ${payload?.to_branch} for dashboard ${dashboardRef} mode=${payload?.mode}`);
|
||||
return requestApi(buildDashboardRepoEndpoint(dashboardRef, '/promote', envId), 'POST', payload);
|
||||
}
|
||||
// #endregion promote
|
||||
};
|
||||
// #endregion gitService:Action
|
||||
|
||||
// #endregion GitServiceClient:Module
|
||||
// #endregion gitService
|
||||
// #endregion GitServiceClient
|
||||
|
||||
Reference in New Issue
Block a user