构建记录长期留存
Jenkins 的 Build Record 被清理后,归档里的分支、Commit 和镜像信息依然在。
Jenkins 为了省空间会清理旧构建,而排查线上问题时,恰恰需要知道某个镜像来自哪次提交。它把这些信息存到一个独立的小服务里。
| 定位 | 独立于 Jenkins 的构建元数据归档,构建记录被清理后仍可追溯 |
|---|---|
| 记录什么 | Job、构建号、Git 仓库 / 分支 / Commit、Commit 作者与改动文件、Docker 镜像 Tag 与 Digest、构建结果和耗时 |
| 怎么写入 | 流水线结束时由 Shared Library 的 buildArchive() 或一条 curl POST 过来,(jobName, buildId) 幂等 |
| 怎么查 | 内置 Web 页面和 REST API,支持 Job / 分支 / Commit / Tag 搜索与日期筛选 |
| 技术 | Python + FastAPI + SQLite,Docker Compose 部署,MIT 开源 |
Jenkins 的 Build Record 被清理后,归档里的分支、Commit 和镜像信息依然在。
记录分支、Commit SHA、提交信息、作者和改动文件,详情页一眼看全。
Tag 可能被覆盖,Digest 不会。同时记录两者,长期追溯才靠得住。
按 Job、分支、Commit、镜像 Tag、结果和日期筛选。列表默认显示当天,「全部历史」一键切换。
在 post { always { } } 里调用 buildArchive();不想用 Shared Library,直接 curl 也行。
归档调用出错只打印警告,不会让流水线变红;成功或失败的构建都会入库。
可设置最长保留天数、每个 Job 最多保留条数;删除需要管理密码并输入确认词。
写接口用 API_TOKEN,Web 管理用 ADMIN_PASSWORD;两者没配置时一律拒绝。
一个容器加一个 SQLite 文件,Docker Compose 启动;表结构自动初始化,升级只要重新构建。
在内网服务器上用 Docker Compose 启动,配置 API_TOKEN 和管理密码。
设置 BUILD_ARCHIVE_URL 和 Token,并把本仓库登记为名为 build-archive 的 Shared Library。
在 post { always { buildArchive() } } 中调用一次,之后每次构建都会自动入库。
推荐用 Shared Library;也可以不装库,直接在 Jenkinsfile 里 curl。
先在 Manage Jenkins 里配置全局环境变量 BUILD_ARCHIVE_URL、BUILD_ARCHIVE_TOKEN,并把本仓库登记为名为 build-archive 的 Global Pipeline Library。然后:
@Library('build-archive') _
pipeline {
agent any
stages {
stage('Build') {
steps { sh 'echo build...' }
}
}
post {
always {
buildArchive() // 必须 always,失败的构建也会入库
}
}
}Agent 需要装有 curl。
在调用 buildArchive() 前,把镜像信息放进环境变量即可:
stage('Push image') {
steps {
script {
def tag = "registry.example.com/dev/my-app:${env.BUILD_NUMBER}"
env.DOCKER_IMAGE_TAG = tag
sh "docker build -t ${tag} . && docker push ${tag}"
env.DOCKER_IMAGE_DIGEST = sh(
script: "docker inspect --format='{{index .RepoDigests 0}}' ${tag} | awk -F@ '{print \$2}'",
returnStdout: true
).trim()
}
}
}服务不会主动去查 Registry,Digest 由流水线传入。
写入接口是 POST /api/v1/builds,用 Bearer Token 鉴权,(jobName, buildId) 相同则更新。先手工验证一次:
curl -X POST http://127.0.0.1:8080/api/v1/builds \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{"jobName":"demo","buildId":1,"buildDate":"2026-08-14T10:00:00+08:00","buildResult":"SUCCESS","buildUrl":"https://jenkins.example/job/demo/1/"}'
| 归档字段 | Jenkins 来源 |
|---|---|
jobName | JOB_NAME |
buildId | BUILD_NUMBER |
gitBranch | GIT_BRANCH / BRANCH_NAME |
gitCommit | GIT_COMMIT |
commitMsg / commitAuthor / commitFiles | 同名环境变量,或 buildArchive(...) 参数 |
dockerImageTag / dockerImageDigest | DOCKER_IMAGE_TAG / DOCKER_IMAGE_DIGEST |
buildResult | currentBuild.currentResult |
buildUrl / durationMs | BUILD_URL / currentBuild.duration |
读接口默认开放,写入与管理接口必须带 Bearer Token。
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | /health | 无 | 健康检查 |
| GET | /api/v1/stats | 无 | 统计 |
| GET | /api/v1/builds | 无 | 列表,支持 q / job / branch / result / dateFrom / dateTo / page / pageSize |
| GET | /api/v1/builds/{id} | 无 | 详情(含 Commit 信息) |
| POST | /api/v1/builds | Bearer | 创建或更新(幂等) |
| DELETE | /api/v1/builds/{id} | Bearer | 删除 |
| GET | /api/v1/admin/retention | Bearer | 查看保留策略 |
| POST | /api/v1/admin/retention/run | Bearer | 立即执行清理 |
说明:API 列表默认不过滤日期;Web 列表默认只显示当天,访问 /?all=1 查看全部历史。
需要一台内网服务器,装有 Docker 与 Docker Compose。数据只有一个 SQLite 文件。
克隆仓库并进入目录,复制环境变量模板。
git clone https://github.com/AlexWuYh/jenkins-build-archive.git cd jenkins-build-archive cp .env.example .env
把 API_TOKEN 和 ADMIN_PASSWORD 换成你自己的值,不要使用示例里的占位符。
API_TOKEN=请替换成足够长的随机字符串 ADMIN_PASSWORD=请设置管理密码 TZ=Asia/Shanghai RETENTION_DAYS=365 RETENTION_MAX_PER_JOB=0
启动后访问健康检查接口,再用浏览器打开 http://服务器IP:8080。
docker compose up -d --build curl http://127.0.0.1:8080/health
数据在 ./data/build_archive.db。在线备份用 SQLite 的 backup 接口;升级则拉取新代码后重新构建,表结构会自动初始化。
docker exec jenkins-build-archive python -c \
"import sqlite3; s=sqlite3.connect('/data/build_archive.db'); d=sqlite3.connect('/data/backup.db'); s.backup(d); d.close(); s.close()"
git pull
docker compose up -d --build| 变量 | 含义 |
|---|---|
API_TOKEN | 写接口的 Bearer Token,Jenkins 侧的 BUILD_ARCHIVE_TOKEN 要与它一致 |
ADMIN_PASSWORD | Web 管理(删除、保留策略)的密码 |
TZ | 时区,决定列表“当天”的范围 |
RETENTION_DAYS | 最长保留天数,0 表示关闭;在 UI 保存后以数据库中的值为准 |
RETENTION_MAX_PER_JOB | 每个 Job 最多保留条数,0 表示关闭 |
仅限内网使用:读接口默认不需要登录,请不要把服务映射到公网,或在反向代理处限制来源。清理策略不可恢复,收紧之前先备份数据库。
完整说明见 GitHub README、 Shared Library 文档。