尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

GitLab Wiki 工程化:从文档仓库到 CI 自动检查

GitLab Wiki 工程化:从文档仓库到 CI 自动检查 手里同时养着七八个 GitLab 项目的时候最容易失控的往往不是代码而是文档。需求讨论散在 Issue 评论里部署说明挤在 README 的末尾运维同学的心得躺在自己电脑某个叫“临时笔记.md”的文件里新人接手第一周基本靠问人。后来我把这些内容统一搬进 GitLab Wiki才算真正把“文档跟着仓库走”这件事落地了。这篇梳理就是把我这几年从“把 Wiki 当 Word 用”到“把 Wiki 当代码仓库管”的完整过程讲清楚它底层是怎么组织的、怎么在本地克隆编辑、侧边栏和目录怎么设计、怎么接 CI 做自动检查、权限怎么分、以及那些只有天天用才会踩到的坑。不管你是刚接触 GitLab 的新人还是已经在团队里负责知识库维护的老手都能从里面挑到能直接用的部分。1. 先弄清楚 GitLab Wiki 的真实定位1.1 它到底是页面还是一个 Git 仓库很多人第一次用 GitLab Wiki是点进项目左侧那个像书本一样的图标然后在网页上敲富文本感觉跟在线文档工具没区别。这个认知会让你在遇到批量迁移、历史回溯、多人协作的时候非常被动。真实情况是每个项目的 Wiki 都是一套独立的 Git 仓库仓库名就是在原项目名后面加.wiki克隆地址形如https://gitlab.example.com/你的命名空间/项目名.wiki.git。它和主代码仓库在存储层面是分开的版本历史完全独立你往主仓库推代码不会顺带更新 Wiki反过来也一样。这个设计带来两个非常实用的后果。第一Wiki 的每一次网页编辑其实都是一次 commit谁在什么时候改了哪一行历史里清清楚楚可以一键回滚到某个版本跟代码的追溯能力是一个级别的。第二既然它是 Git 仓库就意味着你能在本地用编辑器写、能用分支做草稿、能写脚本批量处理文件、能接 CI 做自动检查这些在纯网页文档工具里都是要付费才有的能力。我个人的习惯是短改动直接在网页上改超过三处页面的调整一律本地克隆后用编辑器批量改效率差好几倍。还有一点值得单独说GitLab 除了项目级 Wiki还有群组级 WikiGroup Wiki。群组 Wiki 适合放跨项目的规范、技术选型记录、值班手册这类不属于某一个仓库的内容它的克隆地址是把.wiki.git加在群组路径后面。很多团队只知道项目 Wiki结果把一堆全局规范塞在某个项目里项目一归档文档就跟着“失踪”了这个坑我见得太多了。1.2 什么内容该放 Wiki什么内容不该放Wiki 不是万能筐往里什么都装最后会变成一个没人愿意打开的垃圾场。我一般按“变更频率”和“责任归属”两个维度来判断。变更频率高、和某次具体改动强绑定的内容比如某个接口的参数说明更适合放在代码仓库里的文档目录跟代码一起评审、一起合并代码改了文档忘改的风险最低。变更频率低、偏背景和约定的内容比如环境说明、发布流程、故障处理套路、术语表才适合放 Wiki。下面这张表是我自己团队一直在用的判断标准可以直接拿去对照。内容类型推荐位置理由接口参数、字段说明代码仓库内文档目录需随代码同步评审避免过期环境拓扑、部署流程项目 Wiki变更频率低跨角色都要看需求讨论与决策过程Issue Wiki 归档讨论留 Issue结论沉淀 Wiki新人上手指南群组 Wiki跨项目复用不随单项目归档会议纪要不适合 Wiki时效性强容易堆积成噪声一次性脚本和临时命令代码仓库或片段功能需要被版本管理不是知识判断的土办法很简单如果一段内容三个月内大概率不会变而且换个人接手也必须先读它那就放 Wiki如果它跟某次提交强相关那就跟着代码走。这个标准并不精确但比“凭感觉放”要可靠得多。1.3 和常见文档形态的差异在哪有人问既然团队已经有共享盘或者在线文档为什么还要折腾 GitLab Wiki。我的回答通常是三个关键词靠近代码、可追溯、可自动化。靠近代码意味着你看 MR 的时候顺手就能跳到对应 Wiki 页面不用在两个系统之间来回切可追溯意味着任何一句“这条规定是谁定的”都能查到可自动化意味着你能用流水线检查文档里的死链、格式错误、缺失的元信息。但它也有明显的短板得提前说清楚免得后面失望。Wiki 的全文搜索能力相比专业文档系统偏弱跨项目检索尤其吃力侧边栏需要手工维护页面多了之后整理成本不低网页编辑器的表格和复杂排版体验一般重度排版还是得在本地写 Markdown。所以我的建议是把 Wiki 定位成“工程知识的主干”而不是“所有文档的唯一去处”需要强排版、强检索的场景该用别的工具就用别的工具别硬扛。2. Wiki 仓库的组织结构与本地克隆实操2.1 页面、文件与层级的对应关系Wiki 的页面标题其实来自文件名这一点必须记牢。你在网页上看到的页面名字就是文件名去掉.md后缀的结果页面标题和 URL 路径都由它决定改文件名等于改 URL老的链接就会失效。默认首页固定是home.md如果这个文件不存在Wiki 打开就是空的。页面里的层级靠目录实现docs/install.md在界面上会显示成docs下面的install页面侧边栏里也会自然分层不需要你手动维护父子关系。Markdown 文件第一行的 H1 标题不会覆盖页面标题它只是正文里的一级标题位置在正文顶部。很多人喜欢在文件里写一个 H1结果界面上出现“文件名标题 H1 标题”两个标题看起来非常重复。我的做法是文件名写清楚业务含义正文里不再重复写 H1直接从 H2 开始页面看起来干净很多。命名规范上我踩过的坑足够写一页纸。文件名尽量避免空格和特殊符号用短横线连接单词全小写中文文件名技术上能用但在不同客户端和 URL 编码上容易出问题尤其是附件路径和脚本处理的时候。团队里如果有人习惯用中文文件名早点统一规范省得后期批量改名还得处理失效链接。2.2 克隆地址为什么显示的是机器 ID这个问题我被问过不止一次“网页上给的克隆地址怎么是机器 ID 或者内网 IP不是我们的域名”根因几乎都出在实例配置上。GitLab 生成克隆地址时用的是实例的external_url配置项如果安装时没改或者改完没有重新加载配置它就会拿默认值或者主机名去拼地址于是你在网页上看到的就是一串不好看也不便分享的标识。处理方式不复杂找到配置文件修改external_url为你的正式访问地址然后执行重新加载配置的命令等实例重启完成后再刷新 Wiki 页面克隆地址就会变成域名形式。需要提醒的是改这个配置会影响整站所有链接包含邮件通知、回调地址、Webhook动手之前最好确认没有其他服务依赖旧地址并且在工作时间之外操作。我在测试环境验证过一次这个流程确认没问题再动生产这是基本纪律。另外还有一种情况是反向代理层没有正确传递主机头导致后端拼出来的地址不对。这种就要去看代理配置里的主机头相关设置别只盯着 GitLab 自己的配置文件否则改半天没效果。2.3 HTTP 与 SSH 两条路怎么选克隆方式无非两种HTTPS 和 SSH各有各的适用场景。SSH 需要先在本地生成密钥对把公钥填进 GitLab 账号的 SSH 密钥设置里配好之后一次配置长期有效推送不需要反复输密码适合个人长期开发。HTTPS 不需要额外配置但每次推送都要凭证适合临时机器、共享环境或者做自动化的场景。我通常这样分工个人开发机用 SSHCI 里推送用令牌走 HTTPS。原因是 CI 环境里的密钥管理比令牌管理麻烦得多而令牌可以设置过期时间、可以按需撤销、权限范围也能限制到只读或者只写仓库安全性和可维护性都更好。有一点必须强调令牌等同于密码不要明文写在配置文件里提交到仓库哪怕那个仓库是私有的。正确的做法是放进 CI 的受保护变量里只在运行时注入。对刚开始用的同学给一个最小流程本地生成密钥复制公钥内容打开账号设置里的 SSH 密钥页面粘贴保存然后用git clone git你的域名:命名空间/项目名.wiki.git拉下来往里面加一个 Markdown 文件提交推送回到网页刷新看效果。整个过程十分钟以内能跑通跑通之后你对 Wiki 的理解就从“网页编辑器”升级成“可编程的文档仓库”了。3. 内容编写Markdown 规范、侧边栏与附件处理3.1 实用的 Markdown 语法清单GitLab 对 Markdown 的支持相当完整但真正在日常文档里高频使用的其实就那么十来种。表格用来对比方案代码块用来贴配置任务列表用来跟踪进度折叠块用来收起长日志目录标记用来生成本页大纲。我这里按使用频率排一下方便你抓重点。表格写方案对比、参数说明、排查速查比大段文字高效得多。代码块务必标注语言否则不会有语法高亮读起来很累。折叠块长日志、大段报错、附录内容收进去正文清爽很多。任务列表上线清单、迁移步骤、评审待办都适用勾选状态一目了然。目录标记写在本页顶部自动生成本页锚点目录长文档必备。引用块用来标注意事项和风险提醒视觉上和正文区分明显。行内代码命令、参数名、字段名一律用它包起来避免歧义。锚点链接跨页跳转写清楚相对路径方便串起一整套文档。有两条经验值得单独讲。第一代码块一定要标语言哪怕标错也比不标好因为渲染器会按最接近的规则高亮不标就是一片灰读者找关键行很费劲。第二跨页链接尽量用相对路径而不是完整 URL这样域名变了、实例迁移了链接还能正常工作用完整 URL 的话迁移一次就得批量替换非常痛苦。3.2 侧边栏是 Wiki 的门面也最容易被忽略侧边栏文件_sidebar.md放在仓库最外层用无序列表加链接的方式写渲染出来就是左侧的导航树。这个文件不写的话Wiki 只有默认的页面列表页面一多就完全找不到北。我见过不少团队 Wiki 内容写得不错但侧边栏一直是空的结果好内容没人看得见非常可惜。写法上是这样的结构一级列表项对应顶层分类缩进的列表项对应分组每一项后面跟页面链接链接地址用页面相对路径前面的斜杠表示从 Wiki 根目录开始找。这里有两个坑。第一个坑是文件名必须精确大小写敏感写成_Sidebar.md或者_sidebar.MD都可能不生效我建议直接从网页端新建页面时会自动生成的写法里复制过来别手敲。第二个坑是链接路径写错不会报错只是在侧边栏里点不开或者跳到空页面所以每次调整侧边栏之后最好挨个点一遍验证。维护策略上我推荐两类页面区分处理稳定的主干页面放在侧边栏固定位置按业务域分组临时性的页面不放进侧边栏靠搜索或者正文链接进入。这样侧边栏始终保持精简不会随着内容增长变成一长串谁也读不完的清单。如果页面确实很多可以考虑在侧边栏里只放分类入口具体页面靠分类页里的正文链接串起来层级更清楚。3.3 图片、附件与相对路径的坑在网页编辑器里插入图片系统会把文件提交到 Wiki 仓库里通常是放在一个专门的附件目录下然后自动生成一个相对链接。这个机制本身没问题但有几个细节要注意。第一同一张图不要重复上传多次仓库里会堆一堆重名加后缀的文件历史越来越臃肿。第二图片文件名尽量用有意义的英文短名便于在仓库里检索也避免 URL 编码出问题。第三截图尽量压缩直接粘一张几兆的原图上去仓库克隆速度会明显变慢尤其对网络条件一般的同事很不友好。放在子目录里的页面引用图片相对路径要按页面所在位置来算不能想当然地按仓库根目录写。我建议的做法是给每个分类目录建一个自己的资源目录图片和页面放在同一个层级体系下引用路径短且稳定也不容易在页面移动时断链。对大体积附件的处理我自己的原则是能不提就不提。讲义视频、安装包、设计源文件这类东西不适合塞进 Wiki 仓库仓库的定位是文本知识二进制大文件应该走专门的存储服务在 Wiki 里留一个说明和链接就够了。要是发现仓库已经变得很大先看看历史里有没有误提交的大文件必要时考虑重建仓库并清洗历史但这属于比较重的手术动手前一定先完整镜像备份一份。4. 协作流程与权限控制怎么落地4.1 权限模型和角色分配思路Wiki 的权限依附于项目权限不同角色的读写能力在不同版本上有差异这一点一定要知道不要照着某篇旧文章死记结论。稳妥的做法是在你自己的实例上用测试账号试一遍把结论记进团队规范里版本升级后再复核一次。总体思路是只读的人给到能看见内容的级别参与维护的人给到能编辑的级别决定结构和删改的人控制在少数几个负责人手里避免出现“人人可改、无人负责”的局面。对于内容涉及内部敏感信息的 Wiki我强烈建议把项目可见性设置为私有而不是依赖内部可见性因为内部可见性意味着同实例所有登录用户都能看到这个范围常常比你想的大很多。同时定期清理离职和转岗人员的成员关系这个动作看起来琐碎但它是知识库安全的第一道防线我在审计里见过太多“人都走了一年权限还在”的例子。还有一点容易被忽略Wiki 的权限和主仓库权限是联动的你在 Wiki 上的编辑历史里能看到账号信息所以不要把测试账号、共享账号用来编辑文档否则历史记录里一堆“同一个人”追溯就等于失效了。4.2 并发编辑、冲突与历史回溯网页端编辑是即时提交的两个人同时改同一页后保存的人有可能覆盖先保存的内容而且不会有明显的冲突提示这是最容易丢内容的地方。我在团队里定的规矩是任何超过两百字的结构性修改一律走本地克隆加分支的方式改完再合并避免网页端的盲目覆盖只有错别字、小补充这类几秒钟的改动才允许直接网页编辑。本地编辑的流程其实和写代码一样拉取最新、建分支、修改、提交、推送、合并。冲突处理用常见的拉取变基方式就能解决冲突文件里的标记照着删掉多余的部分即可解决完提交推送。关键是培养习惯动手之前先拉一次改完提交之前再拉一次这两步能挡掉八成以上的争议。历史回溯是 Wiki 的一大优势尤其适合追查“这条规定什么时候加的、为什么加”。在页面的历史里能看到每一版的提交信息点开对比可以看到具体差异行需要的话可以直接恢复某个版本。为了让这个能力真正可用写提交信息的时候请认真一点用“更新文档”这种信息等于把历史功能废掉了。我的习惯是提交信息写成“补充部署前检查项”这种能看懂的短句简单但救命。4.3 把文档评审做成常态较新版本的 GitLab 支持对 Wiki 仓库开合并请求这个能力值得用起来。做法是本地建一个描述性的分支名把改动推上去然后在界面上创建合并请求走一遍评审再合并进主分支。它的价值在于结构性改动有人把关讨论留在 MR 里决策过程可追溯而且评审痕迹和代码评审是同一套习惯团队接受度高。如果你的版本上试了之后发现跑不通也不要卡在这里。退而求其次的方案是在群里贴出改动清单让负责人过一眼然后直接推主分支同时保证每次改动的提交信息足够清晰必要时用历史回滚兜底。我个人的判断是评审流程的价值在文档结构大调整时最明显日常小修小补不值得上完整流程否则维护成本高到没人愿意写文档那就本末倒置了。5. 让 Wiki 接上 CI 做自动检查5.1 值得自动化的是哪几件事Wiki 一旦变成仓库可以自动化的东西就多了。按照投入产出比排序我认为最值得做的三件事是Markdown 格式检查、内部链接有效性检查、侧边栏与页面清单的一致性检查。格式检查能统一标点和标题层级避免同一份文档里三种风格混用链接检查能提前发现页面改名导致的死链这是 Wiki 最容易积累的问题侧边栏一致性检查能揪出“页面建了但没人能导航到”的孤儿页面。提示Wiki 仓库能不能跑流水线不同版本和实例配置下表现不一致有的实例默认不触发。最稳的方案是把 Wiki 仓库镜像到一个普通项目里跑检查检查通过后再同步回去代价是多一层同步逻辑但可控性高很多。这个镜像方案我是踩过坑之后才定下来的。最初我直接在 Wiki 仓库里加配置文件本地测试环境能跑起来换到正式实例就完全没反应排查半天也找不到明确原因。后来改成镜像方案把 Wiki 内容定时拉到一个普通文档项目里所有检查都在那边跑结果稳定得让人安心同时那个项目还能承担搜索、归档等额外职责。5.2 一份可直接抄的流水线配置下面这份配置是简化版主要做格式和链接两类检查你可以按需删减。注意示例里的地址、令牌变量都是占位符实际使用时换成自己的。stages: - lint - check variables: GIT_STRATEGY: clone markdown-lint: stage: lint image: node:20-alpine script: - npm install -g markdownlint-cli - markdownlint **/*.md --ignore node_modules || true rules: - if: $CI_PIPELINE_SOURCE push link-check: stage: check image: alpine:3.19 before_script: - apk add --no-cache curl bash script: - bash scripts/check-links.sh rules: - if: $CI_PIPELINE_SOURCE push - if: $CI_PIPELINE_SOURCE schedule链接检查脚本本身很简单遍历所有 Markdown 文件把相对路径链接提取出来逐个判断目标文件是否存在不存在的就输出文件和行号并让任务失败。规则设为失败即报警但先不要卡合并跑一两个月把存量死链清干净之后再收紧否则第一个月大家都在抱怨。这里补一句实测经验格式检查任务里我加了|| true让它只提示不阻断。原因很现实历史文档格式五花八门一开始就硬卡会直接劝退所有人。等存量清理得差不多了再把这个后缀去掉逐步变严格团队接受度会好很多。5.3 令牌使用与触发方式做定时同步或者回推的流水线绕不开认证问题。推荐用项目访问令牌或者部署令牌权限范围按最小必要原则给只读仓库内容就够的场景绝不给写权限需要回推的才开写权限并且设置合理的有效期到期轮换。令牌放进 CI 的受保护变量里不要写进配置文件的明文里这一点无论团队大小都不能妥协。推送时常见的坑是认证信息拼接方式不对导致 403 或者要求交互式输入密码。用令牌走 HTTPS 推送时用户名位置一般填固定标识密码位置填令牌不是填账号密码。另外要注意CI 内置的任务令牌在某些场景下推送到同一个仓库是被限制的不同版本行为还不一样如果你发现推送一直失败先换成项目访问令牌试一次能快速判断问题出在令牌类型还是别的地方。触发方式上除了常规的推送触发定时任务很适合做周期性链接巡检和内容归档。定时任务的好处是和人的操作解耦不会因为某天没人写文档就停止检查能持续暴露存量问题。我一般设成每周跑一次失败就发通知既不打扰人也不至于问题堆积太久。6. 常见问题与排查速查表6.1 克隆与推送类问题这类问题的排查思路是先分清是认证问题还是网络与配置问题别一上来就删密钥重配浪费时间。判断方法很简单如果是认证失败报错里通常会出现权限拒绝或者认证相关的关键词如果是配置问题往往表现为地址不对、能连上但找不到仓库。现象常见原因处理方向克隆地址显示机器标识或内网地址实例访问地址配置未生效修正配置并重新加载确认代理传递正确权限拒绝公钥被拒本地密钥未加入账号或密钥不匹配核对密钥指纹重新添加公钥推送时反复要求输入密码未配置凭证或使用方式不对改用 SSH或按令牌方式配置凭证找不到仓库路径或命名空间写错从页面复制克隆地址不要手敲网页能看命令行打不开网络策略或证书不被信任确认网络可达处理证书信任链提交成功但页面没变化推到了非默认分支确认推送目标为 Wiki 默认分支另外提一个关联场景有人会在持续集成工具里配置代码平台连接时遇到提示检查访问令牌或版本这类报错的典型原因是令牌被撤销或者插件版本过旧与平台接口不兼容。处理方向就两条重新生成令牌并更新配置以及升级插件到与平台版本匹配的版本。顺序上先更新令牌成本最低绝大多数情况一次就好。6.2 页面渲染与导航类问题渲染问题大多有三类侧边栏不生效、图片不显示、链接跳错页。侧边栏优先检查文件名和层级它必须放在最外层命名要完全一致。图片不显示优先检查相对路径是否按页面所在位置计算其次检查文件名大小写再其次强制刷新排除缓存影响。链接跳错页则是页面改名导致的这也是为什么我反复强调改名前要搜索引用。还有一类问题是页面内容显示为纯文本常见原因是文件扩展名不对或者内容里存在影响解析的字符。Markdown 文件必须以正确的扩展名保存从其他系统复制内容时留意隐藏字符和全角符号。表格排版乱掉也经常是全角字符造成的这个坑很隐蔽建议在编辑器里开一个显示不可见字符的功能一眼就能看出来。6.3 安全维护与备份策略知识库的价值随时间增长可靠性投入也要跟上。实例版本维护这件事不能拖官方发布的安全公告和修复版本要及时跟进尤其是涉及外部可访问接口的修复。升级前务必备份数据备份和配置文件备份都要做配置文件里包含密钥信息备份文件的存放权限要收紧不要随手放在共享目录里。注意升级前先在测试环境验证完整的升级路径跨版本升级要注意官方的版本跳跃限制不要一步跳太多回滚成本会高得难以接受。Wiki 的备份除了常规的实例级备份我建议再加一条“仓库级镜像备份”把重要的 Wiki 仓库用镜像方式拉到另一个存储位置保留完整历史。这个备份的好处是不依赖实例的备份格式真出事的时候可以直接从镜像恢复内容用一条命令就能重新建仓非常干脆。7. 我自己的一线使用心得写到这里分享几个我踩过坑之后固化下来的习惯都是能立刻用上的。第一先定结构再写内容。Wiki 最容易失控的地方不是质量而是结构。我现在的做法是每个新项目建 Wiki 的第一件事就是先把侧边栏骨架搭出来把页面文件建好、内容留空让每个人知道东西该往哪个格子里放再开始写。这个顺序看起来只是调了个头实际效果差得远后期几乎不用大改结构。第二把“决策记录”和“使用说明”分开。使用说明是描述现状的决策记录是描述当时为什么这么选的两者的更新频率和维护方式完全不同。混在一起的结果就是有人改使用说明的时候顺手删掉了历史背景半年后谁也说不清当时为什么定这个方案。我的做法是决策记录单独一个目录只增不改加修改说明可以但原文保留。第三定期做一次内容体检。我一般一个季度做一轮项目包括死链清理、过期内容标注、孤儿页面挂进侧边栏、超长页面拆分。体检不用很复杂一个下午就够了效果比想象中明显。文档这种东西和房间一样不定期整理就会慢慢变成杂物间。第四写文档的时候多想一步“读者是谁”。给运维看的页面和给新人看的页面信息密度和前置知识完全不同。我的习惯是在页面顶部用一两句话写清楚“这篇适合谁读、读完能做什么”成本极低但对读者的帮助远超预期。这个小习惯我坚持了两年多收到的正面反馈是最多的。最后再分享一个扩展方向如果你已经跑通了基本的检查和定时任务下一步可以做内容质量看板比如统计各项目的文档更新频率、孤儿页面数量、近三十天无人维护的页面清单把这些指标定期发给团队。不用做成复杂的系统一个定时任务生成一份清单就够了关键是让文档维护这件事从“没人管”变成“有人看得见”。
返回列表