Skip to main content
Glama
release.ts11.8 kB
/** * Release 管理命令 */ import { createClient, createContextManager, resolveOwnerRepo, ClientOptions } from '../utils/client.js'; import { success, error, outputDetails, outputList, info } from '../utils/output.js'; import { listReleases, getRelease, getReleaseByTag, createRelease, updateRelease, deleteRelease, listReleaseAttachments, getReleaseAttachment, deleteReleaseAttachment, } from '../../tools/release.js'; /** * 列出发布版本 */ export async function releaseList(options: ClientOptions & { owner?: string; repo?: string; limit?: string; page?: string; draft?: boolean; prerelease?: boolean; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const result = await listReleases({ client, contextManager }, { owner, repo, limit: parseInt(options.limit || '30'), page: parseInt(options.page || '1'), draft: options.draft, prerelease: options.prerelease, }) as any[]; if (result.length === 0) { info('没有找到发布版本', options); return; } const releases = result.map((release: any) => ({ id: release.id, tag: release.tag_name, name: release.name || '-', draft: release.draft ? 'Yes' : 'No', prerelease: release.prerelease ? 'Yes' : 'No', author: release.author?.login || '-', published: release.published_at?.split('T')[0] || release.created_at?.split('T')[0] || '-', })); outputList(releases, options); } catch (err: any) { error(`列出发布版本失败: ${err.message}`); process.exit(1); } } /** * 获取发布版本详情(按 ID) */ export async function releaseGet(id: string, options: ClientOptions & { owner?: string; repo?: string; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const releaseId = parseInt(id); if (isNaN(releaseId)) { error('发布 ID 必须是数字'); process.exit(1); } const release = await getRelease({ client, contextManager }, { owner, repo, id: releaseId, }) as any; outputDetails({ ID: release.id, Tag: release.tag_name, Name: release.name || '-', Draft: release.draft ? 'Yes' : 'No', Prerelease: release.prerelease ? 'Yes' : 'No', Author: release.author?.login || '-', Target: release.target_commitish || '-', Published: release.published_at || release.created_at || '-', URL: release.html_url || '-', Body: release.body || '(无描述)', }, options); } catch (err: any) { error(`获取发布版本失败: ${err.message}`); process.exit(1); } } /** * 获取发布版本详情(按 Tag) */ export async function releaseGetByTag(tag: string, options: ClientOptions & { owner?: string; repo?: string; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const release = await getReleaseByTag({ client, contextManager }, { owner, repo, tag, }) as any; outputDetails({ ID: release.id, Tag: release.tag_name, Name: release.name || '-', Draft: release.draft ? 'Yes' : 'No', Prerelease: release.prerelease ? 'Yes' : 'No', Author: release.author?.login || '-', Target: release.target_commitish || '-', Published: release.published_at || release.created_at || '-', URL: release.html_url || '-', Body: release.body || '(无描述)', }, options); } catch (err: any) { error(`获取发布版本失败: ${err.message}`); process.exit(1); } } /** * 创建发布版本 */ export async function releaseCreate(options: ClientOptions & { owner?: string; repo?: string; tag: string; name?: string; body?: string; draft?: boolean; prerelease?: boolean; target?: string; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const release = await createRelease({ client, contextManager }, { owner, repo, tag_name: options.tag, name: options.name, body: options.body, draft: options.draft, prerelease: options.prerelease, target_commitish: options.target, }) as any; success(`发布版本创建成功: ${release.tag_name}`, options); outputDetails({ ID: release.id, Tag: release.tag_name, Name: release.name || '-', Draft: release.draft ? 'Yes' : 'No', Prerelease: release.prerelease ? 'Yes' : 'No', URL: release.html_url || '-', }, options); } catch (err: any) { error(`创建发布版本失败: ${err.message}`); process.exit(1); } } /** * 更新发布版本 */ export async function releaseUpdate(id: string, options: ClientOptions & { owner?: string; repo?: string; tag?: string; name?: string; body?: string; draft?: boolean; prerelease?: boolean; target?: string; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const releaseId = parseInt(id); if (isNaN(releaseId)) { error('发布 ID 必须是数字'); process.exit(1); } const release = await updateRelease({ client, contextManager }, { owner, repo, id: releaseId, tag_name: options.tag, name: options.name, body: options.body, draft: options.draft, prerelease: options.prerelease, target_commitish: options.target, }) as any; success(`发布版本更新成功: ${release.tag_name}`, options); outputDetails({ ID: release.id, Tag: release.tag_name, Name: release.name || '-', Draft: release.draft ? 'Yes' : 'No', Prerelease: release.prerelease ? 'Yes' : 'No', URL: release.html_url || '-', }, options); } catch (err: any) { error(`更新发布版本失败: ${err.message}`); process.exit(1); } } /** * 删除发布版本 */ export async function releaseDelete(id: string, options: ClientOptions & { owner?: string; repo?: string; yes?: boolean; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const releaseId = parseInt(id); if (isNaN(releaseId)) { error('发布 ID 必须是数字'); process.exit(1); } // 确认删除 if (!options.yes) { const readline = await import('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const answer = await new Promise<string>((resolve) => { rl.question(`确认删除发布版本 #${releaseId}? (y/N) `, resolve); }); rl.close(); if (answer.toLowerCase() !== 'y') { info('已取消删除', options); return; } } await deleteRelease({ client, contextManager }, { owner, repo, id: releaseId, }); success(`发布版本 #${releaseId} 已删除`, options); } catch (err: any) { error(`删除发布版本失败: ${err.message}`); process.exit(1); } } /** * 列出发布版本附件 */ export async function releaseAttachments(id: string, options: ClientOptions & { owner?: string; repo?: string; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const releaseId = parseInt(id); if (isNaN(releaseId)) { error('发布 ID 必须是数字'); process.exit(1); } const result = await listReleaseAttachments({ client, contextManager }, { owner, repo, id: releaseId, }) as any[]; if (result.length === 0) { info(`发布版本 #${releaseId} 没有附件`, options); return; } const attachments = result.map((attachment: any) => ({ id: attachment.id, name: attachment.name, size: formatFileSize(attachment.size || 0), downloads: attachment.download_count || 0, created: attachment.created_at?.split('T')[0] || '-', })); outputList(attachments, options); } catch (err: any) { error(`列出发布附件失败: ${err.message}`); process.exit(1); } } /** * 获取发布附件详情 */ export async function releaseAttachmentGet(releaseId: string, attachmentId: string, options: ClientOptions & { owner?: string; repo?: string; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const relId = parseInt(releaseId); const attId = parseInt(attachmentId); if (isNaN(relId) || isNaN(attId)) { error('发布 ID 和附件 ID 必须是数字'); process.exit(1); } const attachment = await getReleaseAttachment({ client, contextManager }, { owner, repo, id: relId, attachment_id: attId, }) as any; outputDetails({ ID: attachment.id, Name: attachment.name, Size: formatFileSize(attachment.size || 0), Downloads: attachment.download_count || 0, Created: attachment.created_at || '-', URL: attachment.browser_download_url || '-', }, options); } catch (err: any) { error(`获取发布附件失败: ${err.message}`); process.exit(1); } } /** * 删除发布附件 */ export async function releaseAttachmentDelete(releaseId: string, attachmentId: string, options: ClientOptions & { owner?: string; repo?: string; yes?: boolean; }) { try { const client = await createClient(options); const contextManager = await createContextManager(client, options); const { owner, repo } = resolveOwnerRepo(contextManager, options); const relId = parseInt(releaseId); const attId = parseInt(attachmentId); if (isNaN(relId) || isNaN(attId)) { error('发布 ID 和附件 ID 必须是数字'); process.exit(1); } // 确认删除 if (!options.yes) { const readline = await import('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const answer = await new Promise<string>((resolve) => { rl.question(`确认删除发布 #${relId} 的附件 #${attId}? (y/N) `, resolve); }); rl.close(); if (answer.toLowerCase() !== 'y') { info('已取消删除', options); return; } } await deleteReleaseAttachment({ client, contextManager }, { owner, repo, id: relId, attachment_id: attId, }); success(`附件 #${attId} 已删除`, options); } catch (err: any) { error(`删除发布附件失败: ${err.message}`); process.exit(1); } } /** * 格式化文件大小 */ function formatFileSize(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SupenBysz/gitea-mcp-tool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server