2026-03-06 22:15:53 +08:00
|
|
|
|
<!doctype html>
|
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<title>Issue-Driven DevOps Agent | Branch-Scoped Delivery Platform</title>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
<style>
|
|
|
|
|
|
:root {
|
2026-03-06 22:28:20 +08:00
|
|
|
|
--bg-0: #070b18;
|
|
|
|
|
|
--bg-1: #101936;
|
|
|
|
|
|
--bg-2: #13274f;
|
|
|
|
|
|
--line: #30406b;
|
|
|
|
|
|
--text: #ecf3ff;
|
|
|
|
|
|
--text-soft: #b9c7e6;
|
|
|
|
|
|
--brand: #36d1ff;
|
|
|
|
|
|
--brand-2: #56f6c8;
|
|
|
|
|
|
--warn: #ffd86b;
|
|
|
|
|
|
--panel: rgba(16, 25, 54, 0.76);
|
|
|
|
|
|
--panel-strong: rgba(10, 17, 38, 0.82);
|
|
|
|
|
|
--ok: #56f6c8;
|
|
|
|
|
|
--danger: #ff7f8f;
|
|
|
|
|
|
--shadow: 0 20px 60px rgba(3, 8, 26, 0.45);
|
2026-03-06 22:15:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
* { box-sizing: border-box; }
|
2026-03-06 22:28:20 +08:00
|
|
|
|
html, body { margin: 0; padding: 0; }
|
2026-03-06 22:15:53 +08:00
|
|
|
|
body {
|
2026-03-06 22:28:20 +08:00
|
|
|
|
color: var(--text);
|
|
|
|
|
|
font-family: "Space Grotesk", "PingFang SC", "Microsoft YaHei", sans-serif;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
background:
|
2026-03-06 22:28:20 +08:00
|
|
|
|
radial-gradient(circle at 0% 0%, rgba(54, 209, 255, 0.22), transparent 30%),
|
|
|
|
|
|
radial-gradient(circle at 100% 10%, rgba(86, 246, 200, 0.18), transparent 28%),
|
|
|
|
|
|
linear-gradient(140deg, var(--bg-0) 0%, var(--bg-1) 42%, var(--bg-2) 100%);
|
|
|
|
|
|
line-height: 1.58;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.page {
|
|
|
|
|
|
max-width: 1140px;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
margin: 0 auto;
|
2026-03-06 22:28:20 +08:00
|
|
|
|
padding: 24px 20px 80px;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.nav {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.logo {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
letter-spacing: 0.2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.logo-dot {
|
|
|
|
|
|
width: 12px;
|
|
|
|
|
|
height: 12px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: linear-gradient(120deg, var(--brand), var(--brand-2));
|
|
|
|
|
|
box-shadow: 0 0 0 5px rgba(86, 246, 200, 0.18);
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav-links {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 14px;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav a {
|
|
|
|
|
|
color: var(--text-soft);
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
|
padding: 8px 12px;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.nav a:hover {
|
|
|
|
|
|
color: var(--text);
|
|
|
|
|
|
border-color: var(--line);
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero {
|
2026-03-06 22:15:53 +08:00
|
|
|
|
border: 1px solid var(--line);
|
2026-03-06 22:28:20 +08:00
|
|
|
|
background:
|
|
|
|
|
|
linear-gradient(145deg, rgba(86, 246, 200, 0.12), transparent 35%),
|
|
|
|
|
|
linear-gradient(325deg, rgba(54, 209, 255, 0.18), transparent 40%),
|
|
|
|
|
|
var(--panel-strong);
|
|
|
|
|
|
border-radius: 24px;
|
|
|
|
|
|
padding: 34px 28px 28px;
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
overflow: hidden;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.hero::after {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: -60px;
|
|
|
|
|
|
top: -65px;
|
|
|
|
|
|
width: 180px;
|
|
|
|
|
|
height: 180px;
|
|
|
|
|
|
background: radial-gradient(circle, rgba(86, 246, 200, 0.35), transparent 70%);
|
|
|
|
|
|
pointer-events: none;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.hero h1 {
|
|
|
|
|
|
margin: 0 0 10px;
|
|
|
|
|
|
font-size: clamp(30px, 4.4vw, 52px);
|
|
|
|
|
|
line-height: 1.05;
|
|
|
|
|
|
letter-spacing: -0.6px;
|
|
|
|
|
|
max-width: 880px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero p {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: clamp(15px, 2.2vw, 19px);
|
|
|
|
|
|
max-width: 880px;
|
|
|
|
|
|
color: var(--text-soft);
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-cta {
|
|
|
|
|
|
margin-top: 18px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.btn {
|
|
|
|
|
|
border: 1px solid var(--line);
|
2026-03-06 22:15:53 +08:00
|
|
|
|
border-radius: 12px;
|
2026-03-06 22:28:20 +08:00
|
|
|
|
padding: 10px 14px;
|
|
|
|
|
|
color: var(--text);
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.btn.primary {
|
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
|
background: linear-gradient(120deg, #2db6ff, #49f2ca);
|
|
|
|
|
|
color: #06253a;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
}
|
|
|
|
|
|
.btn:hover { filter: brightness(1.06); }
|
|
|
|
|
|
.stats {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stat {
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 14px;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
padding: 12px;
|
2026-03-06 22:28:20 +08:00
|
|
|
|
background: rgba(18, 30, 60, 0.58);
|
|
|
|
|
|
}
|
|
|
|
|
|
.stat .v {
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
letter-spacing: -0.3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stat .k {
|
|
|
|
|
|
color: var(--text-soft);
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
margin-top: 2px;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
section {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 18px;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background: var(--panel);
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
h2 {
|
|
|
|
|
|
margin: 0 0 12px;
|
|
|
|
|
|
font-size: 26px;
|
|
|
|
|
|
line-height: 1.12;
|
|
|
|
|
|
letter-spacing: -0.25px;
|
|
|
|
|
|
}
|
|
|
|
|
|
h3 {
|
|
|
|
|
|
margin: 0 0 8px;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
|
}
|
|
|
|
|
|
p { margin: 0; color: var(--text-soft); }
|
|
|
|
|
|
.value-grid, .install-grid, .tool-grid {
|
2026-03-06 22:15:53 +08:00
|
|
|
|
display: grid;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.value-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
|
|
|
|
.install-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
|
|
|
|
.tool-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
2026-03-06 22:15:53 +08:00
|
|
|
|
.card {
|
2026-03-06 22:28:20 +08:00
|
|
|
|
border: 1px solid #385082;
|
|
|
|
|
|
background: rgba(20, 34, 68, 0.82);
|
2026-03-06 22:15:53 +08:00
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
padding: 14px;
|
|
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.card p { margin-top: 4px; }
|
|
|
|
|
|
.flow {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
.step {
|
|
|
|
|
|
border: 1px dashed #4f6796;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
background: rgba(20, 34, 68, 0.55);
|
|
|
|
|
|
}
|
|
|
|
|
|
.step strong {
|
2026-03-06 22:15:53 +08:00
|
|
|
|
display: inline-block;
|
2026-03-06 22:28:20 +08:00
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
|
color: #dff5ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.step p { font-size: 13px; }
|
|
|
|
|
|
.install-card code, pre, .tool-card code {
|
|
|
|
|
|
font-family: "Cascadia Code", Consolas, Menlo, monospace;
|
|
|
|
|
|
font-size: 12.8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre {
|
|
|
|
|
|
margin: 8px 0 0;
|
|
|
|
|
|
border: 1px solid #415983;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
background: #081126;
|
|
|
|
|
|
color: #dcf3ff;
|
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
.copy {
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
border: 1px solid #4e6899;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.03);
|
|
|
|
|
|
color: var(--text);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 6px 10px;
|
|
|
|
|
|
cursor: pointer;
|
2026-03-06 22:15:53 +08:00
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
2026-03-06 22:28:20 +08:00
|
|
|
|
.copy.ok { border-color: #4fcd99; color: var(--ok); }
|
|
|
|
|
|
.list {
|
|
|
|
|
|
margin: 10px 0 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
list-style: none;
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.list li {
|
|
|
|
|
|
border: 1px solid #3b4f78;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
padding: 9px 10px;
|
|
|
|
|
|
color: #d2e0f9;
|
|
|
|
|
|
background: rgba(15, 25, 49, 0.7);
|
|
|
|
|
|
}
|
|
|
|
|
|
.tagline {
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
color: var(--warn);
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
.footer {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
padding: 14px;
|
|
|
|
|
|
background: rgba(6, 11, 25, 0.66);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.footer a {
|
|
|
|
|
|
color: var(--brand);
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
.footer a:hover { text-decoration: underline; }
|
|
|
|
|
|
@media (max-width: 1040px) {
|
|
|
|
|
|
.stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
|
|
|
|
.value-grid, .install-grid, .tool-grid { grid-template-columns: 1fr; }
|
|
|
|
|
|
.flow { grid-template-columns: 1fr; }
|
|
|
|
|
|
}
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<main class="page">
|
|
|
|
|
|
<nav class="nav">
|
|
|
|
|
|
<div class="logo"><span class="logo-dot"></span> Issue-Driven DevOps Agent</div>
|
|
|
|
|
|
<div class="nav-links">
|
|
|
|
|
|
<a href="#install">安装</a>
|
|
|
|
|
|
<a href="#tools">工具</a>
|
|
|
|
|
|
<a href="#workflow">工作流</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
2026-03-06 22:15:53 +08:00
|
|
|
|
<header class="hero">
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<h1>把 Issue 变成可追踪、可复用、可规模化的交付流水线</h1>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
<p>
|
2026-03-06 22:28:20 +08:00
|
|
|
|
我们不是“会修 bug 的脚本”,而是一个面向真实研发组织的 DevOps 交付平台:
|
|
|
|
|
|
<strong>Issue → Branch → Preview Slot → 提测闭环</strong>,并且始终保留工程师对最终合并的控制权。
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</p>
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<div class="hero-cta">
|
|
|
|
|
|
<a class="btn primary" href="https://fun-md.com/Fun_MD/devops-skills" target="_blank" rel="noopener noreferrer">访问仓库</a>
|
|
|
|
|
|
<a class="btn" href="#install">一键安装</a>
|
|
|
|
|
|
<a class="btn" href="../skills/gitea-issue-devops-agent/SKILL.md">查看 Skill 规范</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="stats">
|
|
|
|
|
|
<article class="stat"><div class="v">3</div><div class="k">执行模式(自动/半自动/人工)</div></article>
|
|
|
|
|
|
<article class="stat"><div class="v">5</div><div class="k">部署范围策略(skip→full_stack)</div></article>
|
|
|
|
|
|
<article class="stat"><div class="v">1:1</div><div class="k">Issue/Branch/Preview Slot 绑定</div></article>
|
|
|
|
|
|
<article class="stat"><div class="v">24h+</div><div class="k">可配置 TTL 自动回收</div></article>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<section id="value">
|
2026-03-06 22:15:53 +08:00
|
|
|
|
<h2>核心价值</h2>
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<div class="value-grid">
|
2026-03-06 22:15:53 +08:00
|
|
|
|
<article class="card">
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<h3>分支隔离,主干稳定</h3>
|
|
|
|
|
|
<p>每个 issue 分配独立分支和预览槽位,不再发生“提测相互覆盖”,主干环境用于稳定回归。</p>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</article>
|
|
|
|
|
|
<article class="card">
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<h3>资源智能节流</h3>
|
|
|
|
|
|
<p>根据代码变更范围自动判定部署策略。仅前端改动时不重启服务端,直接复用共享后端。</p>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</article>
|
|
|
|
|
|
<article class="card">
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<h3>证据驱动闭环</h3>
|
|
|
|
|
|
<p>自动沉淀 commit、测试结果、环境链接、验证步骤。Issue 可关闭、可回溯、可审计。</p>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</article>
|
|
|
|
|
|
</div>
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<p class="tagline">这是一套用于长期演进的研发基础设施,不是临时脚本集合。</p>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<section id="workflow">
|
|
|
|
|
|
<h2>工作流拓扑</h2>
|
|
|
|
|
|
<div class="flow">
|
|
|
|
|
|
<div class="step"><strong>1. 引导连接</strong><p>输入 repo_url、api_key、mode,完成连通性校验。</p></div>
|
|
|
|
|
|
<div class="step"><strong>2. 质量审计</strong><p>拉取 issue 与图片附件,做质量评分与去重分组。</p></div>
|
|
|
|
|
|
<div class="step"><strong>3. 分支执行</strong><p>严格在 issue 指定分支改动,保留变更可追踪性。</p></div>
|
|
|
|
|
|
<div class="step"><strong>4. 按范围部署</strong><p>change_scope 自动判断 skip/client/server/full_stack。</p></div>
|
|
|
|
|
|
<div class="step"><strong>5. 自动回收</strong><p>槽位 TTL + 关闭释放,减少预览环境资源占用。</p></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<ul class="list">
|
|
|
|
|
|
<li>工作流模板:<code>.gitea/workflows/issue-branch-preview.yml</code></li>
|
|
|
|
|
|
<li>回收模板:<code>.gitea/workflows/preview-slot-reclaim.yml</code></li>
|
|
|
|
|
|
<li>合并策略:所有模式下都要求工程师人工确认最终合并</li>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</ul>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<section id="install">
|
|
|
|
|
|
<h2>一键安装(Windows / macOS / Linux)</h2>
|
|
|
|
|
|
<p>以下命令会把技能安装到本机 <code>~/.codex/skills/gitea-issue-devops-agent</code>。</p>
|
|
|
|
|
|
<div class="install-grid">
|
|
|
|
|
|
<article class="card install-card">
|
|
|
|
|
|
<h3>Linux</h3>
|
|
|
|
|
|
<pre id="cmd-linux">curl -fsSL https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.sh | bash</pre>
|
|
|
|
|
|
<button class="copy" data-target="cmd-linux">复制命令</button>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
<article class="card install-card">
|
|
|
|
|
|
<h3>macOS</h3>
|
|
|
|
|
|
<pre id="cmd-macos">curl -fsSL https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.sh | bash</pre>
|
|
|
|
|
|
<button class="copy" data-target="cmd-macos">复制命令</button>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
<article class="card install-card">
|
|
|
|
|
|
<h3>Windows (PowerShell)</h3>
|
|
|
|
|
|
<pre id="cmd-win">powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.ps1 | iex"</pre>
|
|
|
|
|
|
<button class="copy" data-target="cmd-win">复制命令</button>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
</div>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<section id="tools">
|
|
|
|
|
|
<h2>核心工具</h2>
|
|
|
|
|
|
<div class="tool-grid">
|
|
|
|
|
|
<article class="card tool-card">
|
|
|
|
|
|
<h3>issue_audit.py</h3>
|
|
|
|
|
|
<p>抓取 issue、评论和图片附件,完成质量评分、去重与回归候选识别。</p>
|
|
|
|
|
|
<pre>python skills/gitea-issue-devops-agent/scripts/issue_audit.py --base-url https://fun-md.com --repo FunMD/document-collab --token <TOKEN> --state all --download-attachments --output-dir .tmp/issue-audit</pre>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
<article class="card tool-card">
|
|
|
|
|
|
<h3>change_scope.py</h3>
|
|
|
|
|
|
<p>输出部署范围建议,决定是否需要服务端重启。</p>
|
|
|
|
|
|
<pre>python skills/gitea-issue-devops-agent/scripts/change_scope.py --repo-path . --base-ref origin/main --head-ref HEAD</pre>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
<article class="card tool-card">
|
|
|
|
|
|
<h3>preview_slot_allocator.py</h3>
|
|
|
|
|
|
<p>管理 preview 槽位:分配、复用、释放、TTL 回收。</p>
|
|
|
|
|
|
<pre>python skills/gitea-issue-devops-agent/scripts/preview_slot_allocator.py --state-file .tmp/preview-slots.json --slots preview-a,preview-b --repo FunMD/document-collab --issue 48 --branch dev --ttl-hours 24 --url-template https://{slot}.qa.example.com --evict-oldest</pre>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
</div>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-03-06 22:28:20 +08:00
|
|
|
|
<footer class="footer">
|
|
|
|
|
|
<span>Skill Path: <code>skills/gitea-issue-devops-agent/SKILL.md</code></span>
|
|
|
|
|
|
<span><a href="https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/site/index.html" target="_blank" rel="noopener noreferrer">公网页面链接</a></span>
|
|
|
|
|
|
</footer>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</main>
|
2026-03-06 22:28:20 +08:00
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
const copyButtons = document.querySelectorAll(".copy");
|
|
|
|
|
|
copyButtons.forEach((btn) => {
|
|
|
|
|
|
btn.addEventListener("click", async () => {
|
|
|
|
|
|
const targetId = btn.getAttribute("data-target");
|
|
|
|
|
|
const el = document.getElementById(targetId);
|
|
|
|
|
|
if (!el) return;
|
|
|
|
|
|
try {
|
|
|
|
|
|
await navigator.clipboard.writeText(el.textContent.trim());
|
|
|
|
|
|
btn.classList.add("ok");
|
|
|
|
|
|
btn.textContent = "已复制";
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
btn.classList.remove("ok");
|
|
|
|
|
|
btn.textContent = "复制命令";
|
|
|
|
|
|
}, 1400);
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
btn.textContent = "复制失败";
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
btn.textContent = "复制命令";
|
|
|
|
|
|
}, 1400);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
2026-03-06 22:15:53 +08:00
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|