# https://github.com/badges/shields 项目说明书

生成时间：2026-06-15 00:09:38 UTC

## 目录

- [shields.io 系统概览与架构](#page-1)
- [GitHub 服务与 Token Pool 管理](#page-2)
- [徽章服务开发与扩展](#page-3)
- [部署、自托管与故障排查](#page-4)

<a id='page-1'></a>

## shields.io 系统概览与架构

### 相关页面

相关主题：[GitHub 服务与 Token Pool 管理](#page-2), [徽章服务开发与扩展](#page-3), [部署、自托管与故障排查](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/badges/shields/blob/master/README.md)
- [package.json](https://github.com/badges/shields/blob/master/package.json)
- [frontend/package.json](https://github.com/badges/shields/blob/master/frontend/package.json)
- [badge-maker/package.json](https://github.com/badges/shields/blob/master/badge-maker/package.json)
- [badge-maker/README.md](https://github.com/badges/shields/blob/master/badge-maker/README.md)
- [frontend/src/components/homepage-features.js](https://github.com/badges/shields/blob/master/frontend/src/components/homepage-features.js)
- [frontend/blog/2023-07-03-new-frontend.md](https://github.com/badges/shields/blob/master/frontend/blog/2023-07-03-new-frontend.md)
- [frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/master/frontend/blog/2024-11-14-token-pool.md)
- [frontend/blog/2023-07-29-tag-filter.md](https://github.com/badges/shields/blob/master/frontend/blog/2023-07-29-tag-filter.md)
- [frontend/src/pages/community.md](https://github.com/badges/shields/blob/master/frontend/src/pages/community.md)
- [core/server/test-public/index.html](https://github.com/badges/shields/blob/master/core/server/test-public/index.html)
- [core/server/error-pages/404.html](https://github.com/badges/shields/blob/master/core/server/error-pages/404.html)

</details>

# shields.io 系统概览与架构

## 一、项目定位与核心价值

shields.io 是一个为开源项目提供简洁、一致、可读性强的徽章（badge）服务的平台。仓库主目录下的 [README.md](https://github.com/badges/shields/blob/master/README.md) 明确指出，Shields.io 支持数十种持续集成服务、软件包仓库、发行版、应用商店、社交网络、代码覆盖率与代码分析服务，每月服务超过 16 亿次图片请求，被 VS Code、Vue.js、Bootstrap 等知名项目广泛使用。

整个 monorepo 由三大组件构成：

| 组件 | 路径 | 职责 |
| --- | --- | --- |
| 服务器（Server） | 根目录 `package.json` | 处理徽章请求、调用上游 API、生成图像 |
| 前端（Frontend） | `frontend/` | 文档站、徽章构建器、搜索、主题切换 |
| badge-maker 库 | `badge-maker/` | 可独立发布的 NPM 徽章渲染库 |

[package.json](https://github.com/badges/shields/blob/master/package.json) 显示服务器依赖包含 `@shields_io/camp`（HTTP 框架）、`badge-maker`（本地链接的徽章库）、`cloudflare-middleware`、`@sentry/node-core` 等，体现了生产级部署对缓存中间件与错误监控的依赖。

## 二、系统架构

下图展示了 shields.io 三大模块与外部服务的协作关系：

```mermaid
graph TB
    User[终端用户 / README]
    FE[Frontend 文档站<br/>frontend/]
    Server[Badge Server<br/>核心服务]
    BM[badge-maker 库<br/>badge-maker/]
    Cache[缓存层<br/>Cloudflare]
    Upstream[上游 API<br/>GitHub/NPM/Docker 等]

    User -->|浏览文档| FE
    User -->|请求 /badge/* URL| Cache
    Cache --> Server
    Server -->|makeBadge| BM
    Server -->|HTTP 调用| Upstream
    Upstream --> Server
    Server --> Cache
    Cache --> User
    FE -.文档生成.-> Server
```

服务器负责路由匹配、数据抓取与徽章渲染；前端使用 Docusaurus 提供徽章文档与可视化构建器。`frontend/blog/2023-07-03-new-frontend.md` 提到，新前端基于 `docusaurus`、`docusaurus-openapi` 与 `docusaurus-search-local`，使每一种徽章都能拥有独立的文档页（如 `https://shields.io/badges/discord`），并支持浅色/深色主题。

## 三、徽章渲染与请求生命周期

徽章生成核心由独立的 [badge-maker](https://github.com/badges/shields/blob/master/badge-maker/package.json) 库承担，该库类型为 ES Module（`"type": "module"`），并通过 `exports` 字段同时导出类型定义与运行时入口。从 [badge-maker/README.md](https://github.com/badges/shields/blob/master/badge-maker/README.md) 可以看到其最小调用形式：

```js
import { makeBadge } from 'badge-maker'
const svg = makeBadge({ label: 'build', message: 'passed', color: 'brightgreen' })
```

服务器端则依赖 `@shields_io/camp` 路由请求，先查询缓存，未命中时再调用上游数据源并通过 `makeBadge` 生成 SVG，最后回写缓存。错误处理由 [core/server/error-pages/404.html](https://github.com/badges/shields/blob/master/core/server/error-pages/404.html) 等静态页面负责，访问不存在路径时会返回幽默风格的提示。

社区频繁反馈的 504 问题（如 issue #1568「Badge Images Often Fail To Load In Github README」）正是该链路在上游限流或网络抖动时的典型表现。

## 四、GitHub Token 池机制

对于 GitHub 相关徽章，shields.io 维护了一个由社区贡献的 Token 池。[frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/master/frontend/blog/2024-11-14-token-pool.md) 解释道，每小时会向 GitHub API 发起数十万次请求，单一 Token 的 5000 次/小时限额远远不够；用户可通过授权 OAuth Application 共享只读 Token，从而整体提升配额。

该机制也带来风险：issue #11912「Unexpectedly Rapid GitHub Token Rate Limit Depletion」与 #11921「GitHub badges showing 'Unable to select next Github token from pool'」记录了 Token 池被快速耗尽或选择失败时，所有 GitHub 徽章会暂时降级为错误徽章，直到小时限额重置。

## 五、扩展能力：标签过滤与自定义徽章

服务器不仅支持常见的动态徽章，也允许通过查询参数定制行为。`frontend/blog/2023-07-29-tag-filter.md` 描述了 GitHub Tag/Release 徽章的 `filter` 参数：`*` 作为通配符，前缀 `!` 表示取反。这让用户能在同一仓库存在多种标签格式（如 `server-YYYY-MM-DD` 与 SemVer）时，仅筛选需要的版本。

此外，[frontend/src/components/homepage-features.js](https://github.com/badges/shields/blob/master/frontend/src/components/homepage-features.js) 在首页明确列出四大能力：动态徽章、静态徽章、badge-maker NPM 库与自托管 Docker 镜像，体现了项目的多层次产品矩阵。

## 六、社区与生态

shields.io 由 OpenCollective 上的赞助商与个人支持者维持运营，赞助页面与捐赠页面分别位于 `frontend/src/pages/community.md` 与 `frontend/src/pages/donate.md`。社区常见的需求包括新增服务（如 Figma 插件、Thunderbird ATN、GitHub Discussions，参见 issue #11925、#6994、#6047）以及对路由变更（如 issue #8671 GitHub Workflow 路径调整、issue #2574 GitHub Actions、issue #5594 Container Registry、issue #4183 Package Registry）的持续跟进。这些反馈直接驱动着服务目录与缓存键设计的演进。

## See Also

- GitHub 徽章使用指南（仓库内 README）
- [Frontend 新版发布说明](https://github.com/badges/shields/blob/master/frontend/blog/2023-07-03-new-frontend.md)
- [Token Pool 详解](https://github.com/badges/shields/blob/master/frontend/blog/2024-11-14-token-pool.md)
- [badge-maker 库文档](https://github.com/badges/shields/blob/master/badge-maker/README.md)
- [Tag Filter 用法](https://github.com/badges/shields/blob/master/frontend/blog/2023-07-29-tag-filter.md)

---

<a id='page-2'></a>

## GitHub 服务与 Token Pool 管理

### 相关页面

相关主题：[shields.io 系统概览与架构](#page-1), [部署、自托管与故障排查](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [services/github/github-constellation.js](https://github.com/badges/shields/blob/main/services/github/github-constellation.js)
- [services/github/github-api-provider.js](https://github.com/badges/shields/blob/main/services/github/github-api-provider.js)
- [services/github/github-auth-service.js](https://github.com/badges/shields/blob/main/services/github/github-auth-service.js)
- [core/token-pooling/token-pool.js](https://github.com/badges/shields/blob/main/core/token-pooling/token-pool.js)
- [core/token-pooling/sql-token-persistence.js](https://github.com/badges/shields/blob/main/core/token-pooling/sql-token-persistence.js)
- [core/server/prometheus-metrics.js](https://github.com/badges/shields/blob/main/core/server/prometheus-metrics.js)
- [core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)
- [frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)
- [frontend/src/pages/privacy.md](https://github.com/badges/shields/blob/main/frontend/src/pages/privacy.md)
</details>

# GitHub 服务与 Token Pool 管理

## 1. 概述与背景

shields.io 为开源项目提供可嵌入 README 的 SVG 徽章，其中 GitHub 徽章（stars、forks、workflows、releases、actions、container registry 等）数量最多、调用最频繁。GitHub REST API 对单个 OAuth Token 的速率限制为每小时 5,000 次请求，而 GraphQL API 则采用更复杂的积分制。但在典型负载下，shields.io 每小时对 GitHub 的调用量达数十万次，远超单 Token 上限。

为突破这一限制，shields.io 采用了 **Token Pool（令牌池）** 机制：任何用户都可以通过 OAuth 授权 https://img.shields.io/github-auth 把自己账户下的只读 Token 贡献到池中。授权时仅请求读取公开数据所需的最小权限，不会接触用户的私有数据，也不会代为执行写操作。

资料来源：[frontend/blog/2024-11-14-token-pool.md:3-22]()

## 2. 核心架构与请求流程

GitHub 相关徽章服务的调用链由 **服务器入口**、**`GithubConstellation`**、**`GithubApiProvider`**、**`TokenPool`** 四层组成。服务器在 `core/server/server.js` 启动阶段实例化 `GithubConstellation`，作为所有 GitHub 服务的统一入口，向服务层暴露 REST、Search、GraphQL 三类接口。

```mermaid
sequenceDiagram
    participant Client as 客户端
    participant Server as shields.io Server
    participant Constellation as GithubConstellation
    participant Pool as TokenPool
    participant GitHub as GitHub API

    Client->>Server: GET /github/stars/badges/shields
    Server->>Constellation: 路由到具体服务
    Constellation->>Pool: 申请剩余配额最高的 Token
    Pool-->>Constellation: 返回可用 Token
    Constellation->>GitHub: 携带 Token 调用 API
    GitHub-->>Constellation: 返回响应
    Constellation-->>Server: 渲染 SVG 徽章
    Server-->>Client: 返回徽章图像
```

- `GithubApiProvider` 将每次调用包装为带 Token 的 HTTP 请求。当返回 `401` 或账号被封禁等错误时，对应 Token 会被标记为失效并从池中剔除。
- `TokenPool` 是核心调度器，每次被申请时优先返回 `usesRemaining` 最高的可用 Token，以达到负载均衡。Token 通过 SQL 持久化层保存，因此服务重启后状态不丢失。
- `github-auth-service.js` 负责 OAuth 回调与 Token 入库，将新贡献的 Token 即时加入运行中的池中。

资料来源：[core/server/server.js:8-15]()、[services/github/github-constellation.js:1-50]()、[core/token-pooling/token-pool.js:1-50]()

## 3. 监控与可观测性

为了解 Token 池的健康状态，shields.io 将关键指标暴露到 Prometheus。`core/server/prometheus-metrics.js` 提供了两个核心方法：

- `noteGithubTokenInvalidation({ reason })` 以 `reason`（如 `http_401`、`account_suspended`）为标签递增计数器，用于追踪 Token 失效原因分布。
- `noteGithubTokenPoolMetrics(tokenDebugInfo)` 将标准、Search、GraphQL 三类池子的 `totalUsesRemaining` 与 Token 数量写入 Gauge 指标，便于运维人员通过 Grafana 观察池子的健康度。

社区曾多次反馈 GitHub 徽章偶发出现 *rate limit exceeded* 或 *Unable to select next Github token from pool* 等提示（参见 [issue #11912](https://github.com/badges/shields/issues/11912) 与 [issue #11921](https://github.com/badges/shields/issues/11921)）。这类问题通常对应池子中可用 Token 不足或大部分 Token 已达 GitHub 速率上限；通过观察上述指标能快速判断是池子耗尽还是单点服务异常。

资料来源：[core/server/prometheus-metrics.js:1-40]()

## 4. 隐私与用户控制

shields.io 严格遵循最小化数据原则。当用户通过 OAuth 授权时，仅存储 **GitHub Token** 与 **授权时间戳**，不收集用户名、邮箱或任何其他个人信息。Token 仅用于提升对 GitHub API 的访问配额。

如果用户希望退出，可随时在 https://github.com/settings/applications 撤销 shields.io OAuth 应用授权。撤销后，shields.io 会将对应 Token 从池中移除，并通过 `noteGithubTokenInvalidation` 记录这一事件。

资料来源：[frontend/src/pages/privacy.md:1-30]()

## 5. 常见失败模式与社区反馈

- **徽章显示 *rate limit exceeded***：通常是池中所有 Token 的 `usesRemaining` 归零。可等待下一小时配额重置，或通过 OAuth 贡献新 Token。
- **徽章显示 *Unable to select next Github token from pool***：池子为空或全部 Token 失效。对照 Prometheus 的 `githubTokenPoolStandardCount` Gauge 即可确认。
- **私有仓库徽章返回错误**：GitHub 不允许跨用户访问私有资源，这是预期行为，建议改用公开仓库（参见 [issue #11877](https://github.com/badges/shields/issues/11877)）。
- **504 Gateway Timeout**：shields.io 上游链路超时，可在 `core/base-service/resource-cache.js` 检查缓存命中率以减少对 GitHub API 的实际调用。
- **GitHub Workflow 徽章路径变更**：自某个版本起，`.github/workflows/test.yml` 的徽章 URL 语法已更新，需参考 [issue #8671](https://github.com/badges/shields/issues/8671) 调整 README 中的链接。

资料来源：[core/server/prometheus-metrics.js:1-40]()、[core/token-pooling/sql-token-persistence.js:1-50]()

## See Also

- [Badge Maker 库](badge-maker.md) — 底层 SVG 渲染逻辑
- [添加新徽章服务](adding-services.md) — 如何基于 `BaseService` 扩展
- [Prometheus 指标说明](observability.md)

---

<a id='page-3'></a>

## 徽章服务开发与扩展

### 相关页面

相关主题：[shields.io 系统概览与架构](#page-1), [部署、自托管与故障排查](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/badges/shields/blob/main/README.md)
- [package.json](https://github.com/badges/shields/blob/main/package.json)
- [core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)
- [badge-maker/package.json](https://github.com/badges/shields/blob/main/badge-maker/package.json)
- [badge-maker/README.md](https://github.com/badges/shields/blob/main/badge-maker/README.md)
- [badge-maker/lib/make-badge.spec.js](https://github.com/badges/shields/blob/main/badge-maker/lib/make-badge.spec.js)
- [frontend/src/components/homepage-features.js](https://github.com/badges/shields/blob/main/frontend/src/components/homepage-features.js)
- [frontend/src/pages/community.md](https://github.com/badges/shields/blob/main/frontend/src/pages/community.md)
- [frontend/blog/2023-07-29-tag-filter.md](https://github.com/badges/shields/blob/main/frontend/blog/2023-07-29-tag-filter.md)
- [frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)
- [core/server/error-pages/404.html](https://github.com/badges/shields/blob/main/core/server/error-pages/404.html)
- [core/server/error-pages/500.html](https://github.com/badges/shields/blob/main/core/server/error-pages/500.html)
</details>

# 徽章服务开发与扩展

Shields.io 是面向开源生态的徽章生成服务，仓库同时托管服务端代码、独立的 `badge-maker` NPM 库以及徽章设计规范。README.md 中明确指出该项目每月为 VS Code、Vue.js、Bootstrap 等知名项目提供超过 16 亿张徽章图片 [资料来源：[README.md:1-40]()](https://github.com/badges/shields/blob/main/README.md)。本页面向希望理解服务架构或为其添加新徽章类型、数据源的开发者。

## 1. 仓库组成与服务角色

仓库以单一 monorepo 形式组织三个互相关联但可独立使用的产物：

| 产物 | 路径 | 角色 |
|------|------|------|
| 服务端 + 前端 | `core/`、`frontend/` | 提供 shields.io 在线服务，路由解析、徽章渲染与文档站点 |
| `badge-maker` 库 | `badge-maker/` | 独立可发布的 NPM 包，用于本地或第三方代码内直接生成徽章 SVG |
| 徽章设计规范 | `spec/`、`doc/` | 定义徽章的视觉协议、路由模板与扩展指南 |

`badge-maker/package.json` 显示该库为 ESM 类型并提供 CLI 入口 `lib/badge-cli.js`，同时声明 `node >= 20` 引擎要求 [资料来源：[badge-maker/package.json:1-40]()](https://github.com/badges/shields/blob/main/badge-maker/package.json)。这意味着任何 JS 项目都能独立引入它来生成徽章，而不必依赖 shields.io 的在线服务。

## 2. 服务端架构与请求生命周期

`core/server/server.js` 是服务启动入口，使用 `@shields_io/camp` 作为 HTTP 路由框架，并通过 `loadServiceClasses` 动态加载所有服务类 [资料来源：[core/server/server.js:1-30]()](https://github.com/badges/shields/blob/main/core/server/server.js)。服务通过常量类（Constellation）模式统一管理外部 API 凭据与限流，例如 `GithubConstellation` 与 `LibrariesIoConstellation` 分别负责 GitHub 与 Libraries.io 的请求池。

下图为典型的徽章请求生命周期：

```mermaid
flowchart LR
  A[客户端请求] --> B[Camp 路由匹配]
  B --> C[legacy-request-handler]
  C --> D[校验参数 Joi + joi-extension-semver]
  D --> E[Constellation 选择凭据]
  E --> F[服务类 handle 函数]
  F --> G[resource-cache 缓存]
  G --> H[makeBadge 渲染 SVG]
  H --> I[legacy-result-sender 响应]
  I --> J[浏览器/爬虫]

  G -.命中.-> I
  F -.异常.-> K[error-pages 404/500]
```

关键依赖在 `package.json` 中列出：`got` 处理 HTTP 请求、`graphql` + `graphql-tag` 处理 GraphQL（如 GitHub v4）、`joi` 与 `joi-extension-semver` 用于参数校验、`dayjs` 处理时间、`@sentry/node-core` 用于错误监控 [资料来源：[package.json:1-90]()](https://github.com/badges/shields/blob/main/package.json)。

当请求失败或路径未匹配时，框架会回落到 `core/server/error-pages/` 下的 HTML 模板：404 页面提供返回首页的链接，500 页面提示稍后重试 [资料来源：[core/server/error-pages/404.html:1-10]()](https://github.com/badges/shields/blob/main/core/server/error-pages/404.html)、[资料来源：[core/server/error-pages/500.html:1-6]()](https://github.com/badges/shields/blob/main/core/server/error-pages/500.html)。

## 3. 徽章样式与渲染参数

`badge-maker` 通过 `makeBadge({ label, message, format, style, color, labelColor, logo, links, idSuffix })` 接受一组参数生成 SVG 或 JSON 徽章，支持以下五种样式：`plastic`、`flat`、`flat-square`、`for-the-badge`、`social` [资料来源：[badge-maker/README.md:1-40]()](https://github.com/badges/shields/blob/main/badge-maker/README.md)。`badge-maker/lib/make-badge.spec.js` 中的快照测试覆盖了空标签、自定义 logo、`idSuffix` 等边界情况 [资料来源：[badge-maker/lib/make-badge.spec.js:1-80]()](https://github.com/badges/shields/blob/main/badge-maker/lib/make-badge.spec.js)。

颜色支持三种来源：命名色（如 `brightgreen`、`success`、`critical`）、三或六位 hex、以及任意 CSS 颜色字符串。这为扩展新徽章时提供了统一的外观控制。

## 4. 扩展新徽章的常见路径

社区讨论表明新徽章需求持续增长，例如 Figma 插件指标 (#11925)、Thunderbird 附加组件 (#6994)、GitHub Container Registry (#5594) 等都源于用户对更多数据源的需求。仓库通过以下机制降低扩展门槛：

- **服务类模板**：README.md 引导贡献者阅读 [doc/TUTORIAL.md](https://github.com/badges/shields/blob/main/doc/TUTORIAL.md)，并要求添加 [service-tests](https://github.com/badges/shields/blob/main/doc/service-tests.md) [资料来源：[README.md:1-40]()](https://github.com/badges/shields/blob/main/README.md)。
- **GitHub 凭据池**：通过 OAuth 共享 token 形成大请求池，缓解 5000 次/小时的速率限制 [资料来源：[frontend/blog/2024-11-14-token-pool.md:1-30]()](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)。社区曾因池耗尽出现 #11912、#11921 等事件，因此新服务应复用 `GithubConstellation` 而非自建 token 管理。
- **缓存层**：`resource-cache` 为高频徽章提供命中即返回的能力，社区在 #11877 中提出手动清除缓存的诉求，扩展时需注意缓存键设计与失效策略。
- **标签/发布过滤**：GitHub tag/release 徽章已支持 `filter` 参数，支持 `*` 通配与 `!` 取反，便于在标签集合中筛选特定版本 [资料来源：[frontend/blog/2023-07-29-tag-filter.md:1-20]()](https://github.com/badges/shields/blob/main/frontend/blog/2023-07-29-tag-filter.md)。
- **静态徽章**：对无外部数据源的需求，可直接使用 `https://img.shields.io/badge/<label>-<message>-<color>` 形式的静态徽章，免去新增服务类的开销 [资料来源：[README.md:1-40]()](https://github.com/badges/shields/blob/main/README.md)。

## 5. 前端、文档与社区运营

前端使用 Docusaurus 构建，组件文件如 `frontend/src/components/homepage-features.js` 描述了首页特性区 [资料来源：[frontend/src/components/homepage-features.js:1-30]()](https://github.com/badges/shields/blob/main/frontend/src/components/homepage-features.js)。`frontend/blog/` 下的文章（如 token-pool、tag-filter）兼具变更日志与原理说明的功能，是发布新特性时的标准做法 [资料来源：[frontend/blog/2024-11-14-token-pool.md:1-30]()](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)。社区赞助商页面 `frontend/src/pages/community.md` 集中展示 OpenCollective、NodePing、Sentry 等贡献方 [资料来源：[frontend/src/pages/community.md:1-50]()](https://github.com/badges/shields/blob/main/frontend/src/pages/community.md)。

## 6. 常见失败模式

- **GitHub 速率限制突发耗尽**：参见 #11912、#11921。建议在服务层显式处理 403/429，并对 `GithubConstellation` 调用做指数退避。
- **缓存中的错误响应**：私有仓库会使徽章持续返回错误，参见 #11877，需在缓存写入时区分有效响应与错误响应。
- **README 中徽章间歇性 504**：参见 #1568，热路径上的超时与缓存命中率直接相关，应监控 `legacy-request-handler` 的耗时分布。

## See Also

- 徽章渲染核心：[badge-maker/README.md](https://github.com/badges/shields/blob/main/badge-maker/README.md)
- 服务路由与错误处理：[core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)
- GitHub API 速率策略：[frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)
- Tag/Release 过滤机制：[frontend/blog/2023-07-29-tag-filter.md](https://github.com/badges/shields/blob/main/frontend/blog/2023-07-29-tag-filter.md)
- 项目主页与历史：[README.md](https://github.com/badges/shields/blob/main/README.md)

---

<a id='page-4'></a>

## 部署、自托管与故障排查

### 相关页面

相关主题：[shields.io 系统概览与架构](#page-1), [GitHub 服务与 Token Pool 管理](#page-2), [徽章服务开发与扩展](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/badges/shields/blob/main/README.md)
- [package.json](https://github.com/badges/shields/blob/main/package.json)
- [core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)
- [frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)
- [frontend/blog/2023-07-03-new-frontend.md](https://github.com/badges/shields/blob/main/frontend/blog/2023-07-03-new-frontend.md)
- [core/server/error-pages/404.html](https://github.com/badges/shields/blob/main/core/server/error-pages/404.html)
- [core/server/error-pages/500.html](https://github.com/badges/shields/blob/main/core/server/error-pages/500.html)
- [badge-maker/package.json](https://github.com/badges/shields/blob/main/badge-maker/package.json)
</details>

# 部署、自托管与故障排查

## 部署概览

Shields.io 的部署入口由 `core/server/server.js` 承担，HTTP 服务基于 [`@shields_io/camp`](https://github.com/badges/shields/blob/main/package.json) 框架运行，并通过 [`cloudflare-middleware`](https://github.com/badges/shields/blob/main/core/server/server.js) 处理 Cloudflare 反向代理请求头。服务启动后通过 `loadServiceClasses()` 动态加载所有徽章服务类，由 `legacy-request-handler.js` 与 `legacy-result-sender.js` 协同完成请求分发与响应序列化。资料来源：[core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)。

`package.json` 中定义的 `scripts` 字段覆盖了从本地调试到生产部署的完整生命周期，资料来源：[package.json](https://github.com/badges/shields/blob/main/package.json)：

| 脚本命令 | 用途 |
| --- | --- |
| `start:server` | 开发模式（nodemon 热重载，端口 8080） |
| `start:server:prod` | 生产模式（直接 `node server`） |
| `debug:server` | 启用 Node `--inspect` 调试 |
| `profile:server` | 启用 V8 `--prof` 性能采样 |
| `build` | 生成静态前端并产出 `public/` 目录 |
| `heroku-postbuild` | Heroku 平台后置构建钩子 |
| `e2e` | Cypress 端到端测试 |

部署前会执行 `depcheck` 校验 Node 版本约束（`^22 || ^24`），以避免在不同运行时下出现意外行为，资料来源：[package.json](https://github.com/badges/shields/blob/main/package.json)。

```mermaid
flowchart LR
  A[GitHub README] --> B[img.shields.io]
  B --> C[Cloudflare 边缘节点]
  C --> D[Shields Server]
  D --> E[Service Loader<br/>loadServiceClasses]
  E --> F[外部 API<br/>GitHub/NPM/...]
  D --> G[Badge Maker<br/>SVG 渲染]
  G --> H[浏览器 / CDN 缓存]
```

## 自托管配置

自托管时需关注三类配置：服务器启动脚本、敏感凭证、以及前端静态资源。服务器入口脚本通过 `cross-env NODE_CONFIG_ENV=development` 切换配置环境，配置文件遵循 [`config`](https://github.com/badges/shields/blob/main/package.json) 依赖的约定，可同时支持 `default.yml`、`production.yml`，并通过 `custom-environment-variables.yml` 将敏感值从环境变量注入。

许可证方面，本项目采用 CC0-1.0 公共领域协议，允许任何组织和个人自由复制、修改和分发整个服务，资料来源：[README.md](https://github.com/badges/shields/blob/main/README.md)。徽章渲染内核 `badge-maker` 是独立可发布的子包，要求 `engines.node ">=20"`，可作为 Node 模块嵌入到其他系统，资料来源：[badge-maker/package.json](https://github.com/badges/shields/blob/main/badge-maker/package.json)。

构建产物分为两部分：服务器本身和前端站点。前端自 2023 年 7 月起切换至 Docusaurus，资料来源：[frontend/blog/2023-07-03-new-frontend.md](https://github.com/badges/shields/blob/main/frontend/blog/2023-07-03-new-frontend.md)；`npm run build` 会先调用 `scripts/export-openapi-cli.js` 导出 OpenAPI 定义，再执行 `docusaurus:build` 将静态页面写入 `public/` 目录。

## 监控、指标与缓存管理

生产环境的可观测性由三类组件支撑，资料来源：[package.json](https://github.com/badges/shields/blob/main/package.json) 与 [core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)：

1. **错误追踪** —— 通过 `@sentry/node-core` 集成 Sentry，捕获未处理异常并上报。
2. **指标导出** —— `core/server/server.js` 中实例化了 `PrometheusMetrics` 与 `InfluxMetrics`，可同时向 Prometheus 抓取端点和 InfluxDB 推送时序指标。
3. **缓存清理** —— `clearResourceCache` 暴露自 `core/base-service/resource-cache.js`，允许在私有仓库误缓存或第三方接口变更时手动刷新响应，社区曾在 [issue #11877](https://github.com/badges/shields/issues/11877) 中呼吁提供该能力。

错误响应由 [`core/server/error-pages/404.html`](https://github.com/badges/shields/blob/main/core/server/error-pages/404.html) 与 [`core/server/error-pages/500.html`](https://github.com/badges/shields/blob/main/core/server/error-pages/500.html) 渲染：404 页面致敬《星球大战》并提示用户回到首页，500 页面则提示稍后重试。

## 常见故障排查

### GitHub 令牌池耗尽

GitHub 徽章家族依赖 `GithubConstellation` 维护的 OAuth 令牌池。令牌来自用户授权 [GitHub OAuth Application](https://img.shields.io/github-auth)，每个令牌享有 [5,000 次/小时](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api) 的 REST API 配额，资料来源：[frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)。社区曾在 [issue #11912](https://github.com/badges/shields/issues/11912) 与 [issue #11921](https://github.com/badges/shields/issues/11921) 中报告过令牌耗尽过快以及"Unable to select next Github token from pool"错误，这通常意味着令牌池配额已用尽，需要等待下一个整点重置或引导更多用户完成 OAuth 授权。

### 504 网关超时

[issue #1568](https://github.com/badges/shields/issues/1568) 记录了 README 徽章间歇性 504 的现象。常见根因包括：上游 API 响应缓慢、Cloudflare 边缘节点与源站之间的网络抖动、以及 Node 进程 GC 暂停。可使用 `npm run profile:server` 配合 `scripts/capture-timings.js` 复现并定位热点，资料来源：[package.json](https://github.com/badges/shields/blob/main/package.json)。

### 私有仓库徽章异常

当目标 GitHub 仓库被设为私有时，未授权用户访问相关徽章会得到错误渲染而非预期结果，这是预期的安全行为，参见 [issue #11877](https://github.com/badges/shields/issues/11877) 的讨论。运维侧可通过调用 `clearResourceCache` 接口刷新对应缓存条目，资料来源：[core/server/server.js](https://github.com/badges/shields/blob/main/core/server/server.js)。

### 性能基准

仓库内置了 `benchmark:badge` 脚本（`scripts/benchmark-performance.js`），默认迭代 10,100 次并丢弃前 100 次预热数据，便于在升级依赖或调整服务类实现后量化性能回归，资料来源：[package.json](https://github.com/badges/shields/blob/main/package.json)。

## See Also

- 项目主页与入门：[README.md](https://github.com/badges/shields/blob/main/README.md)
- 徽章渲染内核说明：[badge-maker/README.md](https://github.com/badges/shields/blob/main/badge-maker/README.md)
- GitHub API 令牌池原理：[frontend/blog/2024-11-14-token-pool.md](https://github.com/badges/shields/blob/main/frontend/blog/2024-11-14-token-pool.md)
- 前端 Docusaurus 迁移说明：[frontend/blog/2023-07-03-new-frontend.md](https://github.com/badges/shields/blob/main/frontend/blog/2023-07-03-new-frontend.md)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：badges/shields

摘要：发现 15 个潜在踩坑项，其中 6 个为 high/blocking；最高优先级：安装坑 - 来源证据：WinGet Service: add ReleaseDate。

## 1. 安装坑 · 来源证据：WinGet Service: add ReleaseDate

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：WinGet Service: add ReleaseDate
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/11285 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. 能力坑 · 来源证据：Badge request: GitHub Discussions

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个能力理解相关的待验证问题：Badge request: GitHub Discussions
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/6047 | 来源类型 github_issue 暴露的待验证使用条件。

## 3. 运行坑 · 来源证据：Add a way to manually clear cached badge responses

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：Add a way to manually clear cached badge responses
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/11877 | 来源类型 github_issue 暴露的待验证使用条件。

## 4. 维护坑 · 来源证据：Figma Community Plugins badges

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个维护/版本相关的待验证问题：Figma Community Plugins badges
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/11925 | 来源类型 github_issue 暴露的待验证使用条件。

## 5. 安全/权限坑 · 来源证据：Mozilla Thunderbird add-ons (ATN)

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Mozilla Thunderbird add-ons (ATN)
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/6994 | 来源讨论提到 api key 相关条件，需在安装/试用前复核。

## 6. 安全/权限坑 · 来源证据：Unexpectedly Rapid GitHub Token Rate Limit Depletion

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Unexpectedly Rapid GitHub Token Rate Limit Depletion
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/11912 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 7. 身份坑 · 仓库名和安装名不一致

- 严重度：medium
- 证据强度：runtime_trace
- 发现：仓库名 `shields` 与安装入口 `badge-maker` 不完全一致。
- 对用户的影响：用户照着仓库名搜索包或照着包名找仓库时容易走错入口。
- 复现命令：`npm install badge-maker`
- 证据：identity.distribution | github_repo:7910045 | https://github.com/badges/shields | repo=shields; install=badge-maker

## 8. 配置坑 · 来源证据：GitHub org not verified

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：GitHub org not verified
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/11917 | 来源类型 github_issue 暴露的待验证使用条件。

## 9. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | github_repo:7910045 | https://github.com/badges/shields | README/documentation is current enough for a first validation pass.

## 10. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | github_repo:7910045 | https://github.com/badges/shields | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | github_repo:7910045 | https://github.com/badges/shields | no_demo; severity=medium

## 12. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | github_repo:7910045 | https://github.com/badges/shields | no_demo; severity=medium

## 13. 安全/权限坑 · 来源证据：GitHub badges showing "Unable to select next Github token from pool"

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：GitHub badges showing "Unable to select next Github token from pool"
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/badges/shields/issues/11921 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 14. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | github_repo:7910045 | https://github.com/badges/shields | issue_or_pr_quality=unknown

## 15. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | github_repo:7910045 | https://github.com/badges/shields | release_recency=unknown

<!-- canonical_name: badges/shields; human_manual_source: deepwiki_human_wiki -->
