ci: fix workflow branch and deploy config
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
// Gitea API integration for XFlow canvas sync
|
||||
// Uses Gitea REST API to store mind maps in MMAVTEX repo
|
||||
// Structure:
|
||||
// Personal canvases → AVTEX/user-{username} (created on first save)
|
||||
// Group canvases → AVTEX/group-{groupId} (created on group creation)
|
||||
// Public canvases → AVTEX/MMAVTEX (shared org repo)
|
||||
|
||||
interface GiteaFile {
|
||||
content: string // base64
|
||||
@@ -17,19 +20,58 @@ const getConfig = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const headers = (token: string) => ({
|
||||
const apiHeaders = (token: string) => ({
|
||||
'Authorization': `token ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
})
|
||||
|
||||
// Resolve which repo to use based on canvas ownership
|
||||
export function resolveRepo(opts: { username?: string; groupId?: string; isPublic?: boolean }): string {
|
||||
const { org, mindmapRepo } = getConfig()
|
||||
if (opts.groupId) return `group-${opts.groupId}`
|
||||
if (opts.username && !opts.isPublic) return `user-${opts.username}`
|
||||
return mindmapRepo
|
||||
}
|
||||
|
||||
// Ensure repository exists in org, create if not
|
||||
export async function ensureRepo(repoName: string, description = ''): Promise<boolean> {
|
||||
const { url, token, org } = getConfig()
|
||||
const h = apiHeaders(token)
|
||||
|
||||
// Check if exists
|
||||
try {
|
||||
await $fetch(`${url}/api/v1/repos/${org}/${repoName}`, { headers: h })
|
||||
return true
|
||||
} catch { }
|
||||
|
||||
// Create
|
||||
try {
|
||||
await $fetch(`${url}/api/v1/orgs/${org}/repos`, {
|
||||
method: 'POST',
|
||||
headers: h,
|
||||
body: {
|
||||
name: repoName,
|
||||
description: description || `XFlow canvas repo: ${repoName}`,
|
||||
private: !repoName.startsWith('group-') && repoName !== getConfig().mindmapRepo,
|
||||
auto_init: true,
|
||||
default_branch: 'main'
|
||||
}
|
||||
})
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error(`Gitea ensureRepo(${repoName}) error:`, e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Get file from Gitea (returns null if not found)
|
||||
export async function giteaGetFile(path: string, repo?: string): Promise<GiteaFile | null> {
|
||||
const { url, token, org, mindmapRepo } = getConfig()
|
||||
const repoName = repo || mindmapRepo
|
||||
try {
|
||||
const res = await $fetch<any>(`${url}/api/v1/repos/${org}/${repoName}/contents/${path}`, {
|
||||
headers: headers(token)
|
||||
headers: apiHeaders(token)
|
||||
})
|
||||
return { content: res.content, sha: res.sha }
|
||||
} catch {
|
||||
@@ -46,7 +88,7 @@ export async function giteaPutFile(path: string, content: string, message: strin
|
||||
try {
|
||||
await $fetch(`${url}/api/v1/repos/${org}/${repoName}/contents/${path}`, {
|
||||
method: sha ? 'PUT' : 'POST',
|
||||
headers: headers(token),
|
||||
headers: apiHeaders(token),
|
||||
body: {
|
||||
message,
|
||||
content: encoded,
|
||||
@@ -60,37 +102,46 @@ export async function giteaPutFile(path: string, content: string, message: strin
|
||||
}
|
||||
}
|
||||
|
||||
// Save canvas to Gitea MMAVTEX repo
|
||||
export async function saveCanvasToGitea(canvasId: string, canvasData: any, commitMessage?: string): Promise<boolean> {
|
||||
const path = `canvases/${canvasId}.canvas`
|
||||
// Save canvas to correct repo based on ownership
|
||||
export async function saveCanvasToGitea(
|
||||
canvasId: string,
|
||||
canvasData: any,
|
||||
opts: { username?: string; groupId?: string; isPublic?: boolean } = {},
|
||||
commitMessage?: string
|
||||
): Promise<boolean> {
|
||||
const repo = resolveRepo(opts)
|
||||
const path = `${canvasId}.canvas`
|
||||
const content = JSON.stringify(canvasData, null, 2)
|
||||
const message = commitMessage || `Update canvas ${canvasId} at ${new Date().toLocaleString('ru-RU')}`
|
||||
const message = commitMessage || `Update ${canvasId} at ${new Date().toLocaleString('ru-RU')}`
|
||||
|
||||
// Get existing file SHA if exists (required for update)
|
||||
const existing = await giteaGetFile(path)
|
||||
return giteaPutFile(path, content, message, existing?.sha)
|
||||
await ensureRepo(repo)
|
||||
const existing = await giteaGetFile(path, repo)
|
||||
return giteaPutFile(path, content, message, existing?.sha, repo)
|
||||
}
|
||||
|
||||
// Load canvas from Gitea
|
||||
export async function loadCanvasFromGitea(canvasId: string): Promise<any | null> {
|
||||
const path = `canvases/${canvasId}.canvas`
|
||||
const file = await giteaGetFile(path)
|
||||
export async function loadCanvasFromGitea(
|
||||
canvasId: string,
|
||||
opts: { username?: string; groupId?: string; isPublic?: boolean } = {}
|
||||
): Promise<any | null> {
|
||||
const repo = resolveRepo(opts)
|
||||
const file = await giteaGetFile(`${canvasId}.canvas`, repo)
|
||||
if (!file) return null
|
||||
|
||||
try {
|
||||
const decoded = Buffer.from(file.content, 'base64').toString('utf-8')
|
||||
return JSON.parse(decoded)
|
||||
return JSON.parse(Buffer.from(file.content, 'base64').toString('utf-8'))
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// List all canvases in Gitea
|
||||
export async function listCanvasesFromGitea(): Promise<string[]> {
|
||||
// List canvases in a repo
|
||||
export async function listCanvasesFromGitea(repo?: string): Promise<string[]> {
|
||||
const { url, token, org, mindmapRepo } = getConfig()
|
||||
const repoName = repo || mindmapRepo
|
||||
try {
|
||||
const res = await $fetch<any[]>(`${url}/api/v1/repos/${org}/${mindmapRepo}/contents/canvases`, {
|
||||
headers: headers(token)
|
||||
const res = await $fetch<any[]>(`${url}/api/v1/repos/${org}/${repoName}/contents/`, {
|
||||
headers: apiHeaders(token)
|
||||
})
|
||||
return res
|
||||
.filter((f: any) => f.name.endsWith('.canvas'))
|
||||
|
||||
Reference in New Issue
Block a user