Commit Graph
100 Commits
Author SHA1 Message Date
yeasy 08e981018e fix(content): 修正四处书内自相矛盾的技术断言
1. FROM「必须是第一条指令」(4.5、7.16、summary 三处)与本书 7.7.4「FROM 之前的
   ARG」整节直接冲突。官方 Dockerfile 参考写的是 "A Dockerfile must begin with a
   FROM instruction. This may be after parser directives, comments, and globally
   scoped ARGs",且 "ARG is the only instruction that may precede FROM"。三处
   一并改成「第一条构建指令」并点明例外。

2. 12 章小结把 USER Namespace 列进「默认启用」的一档,并写「容器 root ≠ 宿主机
   root」;而同章 12.2.2 明写 USER Namespace 默认**不**启用、需 userns-remap 显式
   开启,18.1 更直说「在默认情况下,容器内的 root 用户(UID=0)就是宿主机上的
   root 用户」。小结按正文口径改回——这条读反了会直接误判容器逃逸的风险面。

3. 11.5「目前支持三种日志驱动类型」是 Compose 早期文本的残留。官方支持 json-file、
   local、syslog、journald、gelf、fluentd、awslogs、splunk、etwlogs、gcplogs、
   none 共十余种,本书 19 章小结自己就列了六种。改为给出常见取值并链到官方清单。

4. 7.8 与 7.5 的示例注释建议 postgres:latest / redis:latest,而 4.1、7.10、
   7.16、7 章小结、4.5 全都要求避免 latest(7.8 同一文件第 177 行也写「避免
   latest」)。按全书口径改掉这两处。

另:ENV 的空格分隔旧写法(7.6 的「格式一」、附录四的 PG_MAJOR/PATH 示例)改为等号
形式并加注。BuildKit 的 LegacyKeyValueFormat 检查会报
"ENV key=value" should be used instead of legacy "ENV key value" format,
而本书 10.2 与 07 章 README 正是在推荐 docker buildx build --check。
2026-08-07 23:26:12 -07:00
yeasy 42253fc1e8 fix(ci): 示例里的 GitHub Actions 大版本标签落后上游
第 18、21 章的工作流示例仍用 actions/checkout@v6 与 actions/upload-artifact@v4,
而上游当前大版本分别是 v7.0.1(2026-07-20)与 v7.0.1(2026-04-10);本仓库自己的
.github/workflows/* 早已按 SHA 钉在 v7.0.1 上,书里教的和书自己在跑的不一致。
21.2 更是同一个文件内自相矛盾:第 27/108 行写 @v6,第 59 行却钉着 v7.0.0 的 SHA。

sigstore/cosign-installer 一并从 @v3 提到 @v4.1.2:官方 v4.0.0 发布说明写明
"You must upgrade to cosign-installer v4 if you want to install Cosign v3+",
而 18.6 手工安装那段用的是 releases/latest(今天就是 Cosign 3.x),两条路径装的
不是同一个大版本。该仓库没有可移动的 v4 标签,只能引用完整版本号,已就地加注说明。

docker/{build-push,setup-buildx,login}-action、anchore/sbom-action@v0、
github/codeql-action@v3 逐一核对后确认仍是当前受支持版本,未改动;
trivy-action 的 SHA 57a97c7e 经 GitHub API 核对确与 v0.35.0 一致,注释无误。
2026-08-07 23:24:00 -07:00
yeasy b81816bb07 fix(content): 修正已随上游变化失效的版本事实与镜像引用
深审发现 14 处正文与上游现状不符(另有 4 处在 .agent/ 本地记忆,不入库)。
全部经官方一手源核验,并由独立复核者逐条尝试证伪后保留。

**Docker Content Trust 已从 CLI 移除(本书基线正是 Engine 29.x)**
- 18.6:`docker trust`、`DOCKER_CONTENT_TRUST` 的示例此前标为“历史用法”,
  但未说明命令在 29.x 上根本不存在。Engine 29.0 release notes 原文:
  "Docker Content Trust was removed from the Docker CLI";实测 docker/cli
  的 cli/trust 包在 v28.5.0 返回 200、v29.0.0 返回 404
- 2.3、18.6:DCT 不再是“弃用阶段、时间线待公布”——官方 retired 页已给出
  完整时间表(notary.docker.io 2026-12-08 关闭)
- 注意:`--disable-content-trust` 是 MarkDeprecated(隐藏但仍接受为 no-op),
  不是“不可用”。初版提议写成不可用,经复核纠正后才落地

**etcd 维护分支写反了**
- 15_etcd README/15.1/15.2 均称“3.5 已退出维护窗口”,但 2026-07-23 官方与
  v3.7.1、v3.6.14 同批发布了 v3.5.33,公告称三个分支均在维护;3.4 EOL 也应
  是 2026-06(v3.4.45),非 5 月

**其他上游变化**
- 17.6:containerd 首个 2.x LTS 是 2.0(2024-11-05 起),非 2.3
- 6.4:`sonatype/nexus3:3.69` 这个 tag 从不存在(Sonatype 用三段式),改 3.69.0
- appendix/repo/centos:`rockylinux` 官方镜像已冻结(最后推送 2024-05-30),
  改用官方指引的 `rockylinux/rockylinux`(2026-07-12 仍在更新)
- 6.2/6.3:docs.docker.com/registry/ 已 301 到 retired 页,改指
  distribution.github.io(实测 200)
- 6.1:`docker search centos` 的示例输出补上上游现有的 DEPRECATED 标记

**刻意未改**:`minio/minio` 虽在 Docker Hub 标记 archived,但提议替换的
quay.io/minio/minio 最新 tag 停在 2024-07-31,比 Docker Hub 的 2025-09-07
更旧,照改会把读者引向更陈旧的仓库,留待作者定夺。

验证:check_project_rules 202 文件全过、emphasis 全过、40 测试通过、format 干净。
2026-07-28 20:12:47 -07:00
yeasy 0b526c1674 docs: drop the as-of date stamps from prose
A reader dates a book by the book. An inline 截至 <date> or (核验日期:<date>)
tells them nothing they cannot infer, and it decays: this cluster's clearest
case is the eight files that carried 截至 2026-05-18 while git showed they were
written 33 days earlier, one commit having later nudged the date a day for
visual consistency.

Two kinds of date deliberately survive, because they are not as-of stamps:

- Forward-looking deadlines. "Sonnet 5 的 $2/$10 是截至 2026-08-31 的介绍价"
  states when a price expires; deleting that date would lose a fact.
- Ledger metadata. verified_at / expires_at / ttl_days in the volatile-facts
  appendices are inputs to check_volatile_facts(), which fails the build when
  they lapse. That is the right home for a verification date — machine-checked
  and self-expiring, rather than prose nothing re-earns.

Event dates are untouched throughout (2026-06-09 GA, 2026-06-12 暂停). Where a
sentence needed the sequence, "截至 2026-07-09 官方模型页已恢复" became
"官方模型页此后已恢复", which keeps the ordering without the observation date.
2026-07-28 11:38:02 -07:00
yeasy 90ea597376 fix(check-emphasis): recognise code fences opened inside a blockquote
FENCE_RE was `^\s*(`{3,}|~{3,})`, which matches leading whitespace but not
a blockquote marker. A fence written as `> ```python` was therefore never
recognised, so the quoted code was scanned as prose and CJK-adjacent `**`
inside it was reported as non-rendering emphasis. Since the emphasis check
became a blocking CI gate, that false positive could red-line a legitimate
push over a code sample in a callout.

This file documents itself as mirroring check 6 of the workspace-level
format_checker.py, whose FENCE_RE already handles up to three spaces of
indent plus any number of `>` prefixes. Adopting that pattern restores the
stated invariant.

Demonstrated before/after on a file holding the same line both inside and
outside a blockquoted fence: previously only the quoted copy was flagged
(exit 1); now neither is (exit 0), while a genuine prose defect is still
reported (exit 1), so the gate is not weakened. All 14 repos re-checked:
check_emphasis and check_project_rules pass on all 1,615 markdown files,
and the 14 copies remain byte-identical. A mutation-tested regression guard
now lives in the workspace repo at tests/test_blockquote_fence_emphasis.py.
2026-07-24 21:08:44 -07:00
yeasy 21e43e1927 ci: stop && from swallowing a check_project_rules failure
The step ran `check_project_rules.py && check_emphasis.py` with more
commands on following lines. Under `bash -e` the left operand of `&&`
is an exempt context, so a rules failure did NOT abort the step: it
short-circuited past check_emphasis.py, execution continued to the next
line, and the step exited with that last command's status -- green.

Demonstrated:
  bash -e -c 'false_check && emphasis
              next_cmd'          -> exit 0   (failure swallowed)
  bash -e -c 'false_check
              emphasis
              next_cmd'          -> exit 1   (correctly blocks)

So the repo's main content gate could fail while CI stayed green, and
today's new CJK emphasis gate was skipped entirely whenever it did.
Splitting the line restores fail-fast for both.

Swept all 14 repos: only this one and the other CI whose && line is
followed by further commands were affected; the 12 where the && list is
the last line of its run block already exit non-zero and are unchanged.

Verified: YAML parses, both checkers pass, repo test suite unchanged.
2026-07-24 19:05:25 -07:00
yeasy 95ee0aeca5 ci: gate CJK-punctuation bold regressions with a self-contained emphasis check
check_project_rules.py only checks fences + local links, so a bold marker that
CJK punctuation stops from rendering (e.g. `**(配比)**相互交织` — the closer is
preceded by punctuation and followed by a letter, so it can't close and the
asterisks print literally) would pass this repo's own CI. That class of bug had
to be swept out of every book by hand; nothing here was watching for it.

Adds check_emphasis.py — a standalone gate (identical across all books) that
runs CommonMark's flanking + process-emphasis rules and flags markers that
print literally or silently bold the wrong span. The ci.yaml content step now
runs it right after check_project_rules.py. Verified clean on this book.
2026-07-24 07:27:07 -07:00
yeasy 657c0b25df test(html-reader): guard the bold-lead-in list rendering with real pandoc
The reason 640 collapsed lists shipped green is that no test exercised real
markdown->HTML rendering — the existing build_html_reader tests stub pandoc with
a fake, covering TOC/mermaid plumbing but never the markdown parse. This feeds
the exact bold-lead-in pattern through the real pandoc invocation the reader uses
and asserts the list survives as <ul>. Proven both ways: passes with the
extension, fails when it is removed.
2026-07-23 22:57:35 -07:00
yeasy 7391bf95ef fix(html-reader): stop pandoc from collapsing bold-lead-in lists into a paragraph
The book style writes a bold label then a list with no blank line between them:

    **触发分离的条件**:
    - 输入序列长度 > 某阈值

Strict CommonMark (pandoc default -f markdown) requires a blank line before a
list, so it folded every such list into a single <p>. Measured 640 occurrences
across 13 books — troubleshooting checklists and diagnostic steps shipped in the
offline HTML reader as run-on paragraphs, while GitBook, GitHub, and the PDF all
rendered them correctly. The source was fine; only this reader was wrong.

Fix is the additive pandoc extension markdown+lists_without_preceding_blankline,
verified on real book content through real pandoc: the three bullets that
previously joined into one <p> now produce <ul><li>, with no effect on ordinary
paragraphs or on tables (pipe_tables stays enabled).
2026-07-23 22:57:35 -07:00
yeasy 4175760d1b ci: drop the two Dependabot auto-merge steps that could never work
Neither step did what its name said, and together they meant no Dependabot PR
was ever auto-merged — the job died before reaching the merge step.

1. "Confirm required checks are configured" failed OPEN. It read branch
   protection, which GITHUB_TOKEN cannot do (administration scope is not even
   a valid permissions key), so gh api returned 403 JSON into REQUIRED and
   `[ "$REQUIRED" -eq 0 ]` died with "integer expression expected". A failing
   test inside an `if` condition is exempt from set -e, so the guard evaluated
   false and let execution continue. A guard whose whole purpose is refusing
   an unsafe merge silently passed whenever it could not check.

2. "Approve low-risk Dependabot PR" can never succeed: GitHub Actions is not
   permitted to approve pull requests. It is also unnecessary — these repos do
   not require reviews.

The real gate is now branch protection, which as of today requires BOTH
check-commit-identity and CI on every repo, and gh pr merge --auto cannot
complete until they pass. That is stronger than the removed probe, which only
checked that some required check existed.

This makes the 13 repos match oc_guide, which already had exactly this shape
and was the only one whose auto-merge was not broken.

prompt_engineering_guide asserted the old step ORDER; its test now asserts the
invariants that still hold — no self-approve attempt, and auto-merge gated on
the low-risk update-type allowlist.
2026-07-23 17:27:39 -07:00
yeasy b7d4410cf0 fix(build): drop the _site_site workaround that mdPress 0.8.1 made obsolete
The build script anticipated an older mdPress behaviour where a shared
--output made the site land in a sibling directory, then moved it back:

  mdpress build --format site --output _site && rm -rf _site && mv _site_site _site

mdPress 0.8.1 writes straight into --output, so the sibling never appears and
the mv aborts the step:

  ✓ Generated site  → .../docker_practice/_site/index.html
  mv: cannot stat '_site_site': No such file or directory

Caught by a smoke test after 0.8.1 shipped, before any content push fanned it
out — this repo is the only one with a live copy of the workaround (the three
matches in other repos are inside gitignored _book/ build artifacts).

The site itself built fine; only the post-processing dance failed.
2026-07-23 17:14:19 -07:00
yeasy f8691a8868 ci: retry the mdPress PDF build instead of failing the job on a Chrome flake
The mdPress PDF step drives headless Chrome, which intermittently dies with
"websocket url timeout reached" plus dbus/bus.cc:405 errors. Confirmed by the
verbatim signature in six runs across five repos on 2026-07-22 and 07-23 — most
recently it failed a docker_practice smoke test after mdPress had already
finished parsing 196 chapters and assembling the HTML, dying only at step 5/5.
It is infrastructure, not content: a rerun clears it every time.

oc_guide already solved this with tools/build_pdf.py (bounded retries, process-
scoped timeout cleanup, per-attempt logs) and is notably absent from the flake
victims. This applies the same idea to the other 13 repos with a much smaller
change: shadow mdpress with a retry function once per run block, so every call
shape — including the multi-line continuations — is covered without rewriting
42 heterogeneous call sites. `command mdpress` reaches the real binary.

Fails closed: after 3 attempts the function returns 1 and errexit fails the
step. Verified all three paths against a fake mdpress before rollout — first-try
success, success after two flakes, and 3x failure aborting the step without
printing the following command.

oc_guide is untouched (it has no `mdpress build` call). Converging the other 13
onto its richer build_pdf.py remains the better long-term shape.
2026-07-23 17:06:11 -07:00
yeasy eb939f69e5 fix(format): unstick bold markers that CJK punctuation kept from rendering
CommonMark only treats a run of asterisks as an emphasis delimiter when it is
left/right-flanking. CJK punctuation counts as Unicode punctuation, so a closer
like `**数据(配比)**相互交织` is preceded by punctuation and followed by a
letter — it cannot close, and the page shows literal asterisks instead of bold.

Inserts the single space that book-rules 1.1 already asks for, on whichever
side was failing: 2 places across 2 file(s). No wording changed —
every diff here is whitespace-only. Verified against pandoc's gfm reader:
each span now renders as its own <strong>.
2026-07-23 17:04:37 -07:00
yeasy 898fb10bbe ci: track the latest mdPress release instead of a per-repo pinned version
Per the author: mdPress should default to the latest release.

The cluster had drifted to three versions (0.7.10 x4, 0.7.11 x9, 0.7.14 x1),
and nine of those were pinned to bytes upstream had rebuilt under an existing
tag — the exact thing the harness move to 0.7.14 refused to do on principle.
Pinning also took CI down cluster-wide twice when a tag was rebuilt, because
the digest no longer matched. Latest is now 0.7.15; nothing was on it.

Each of the 43 install sites now resolves the newest release at build time by
following the /releases/latest redirect (no api.github.com call, so no
unauthenticated rate limit on shared runner IPs) and exports the version via
GITHUB_ENV.

Integrity is kept, not dropped: the archive is verified against that same
release's published checksums.txt, and a missing entry aborts the step rather
than passing silently. The honest trade-off is that this verifies the download
rather than pinning an immutable artifact — a rebuilt release is now followed
instead of failing the build. That is the intended behaviour here, since the
rebuild breakage was the problem being solved and upstream is the same author.

Tests updated in step: 12 suites asserted the literal MDPRESS_SHA256 as a
proxy for "this download is checksum-verified". They now assert checksums.txt,
which is where that guarantee lives.
2026-07-23 13:47:03 -07:00
yeasy 1e56295251 fix(ci): close two silent false negatives in Identity Guard
An audit found the guard could miss commits it exists to catch.

1. SIGPIPE. Three inner checks used `printf ... | grep -q` under
   `set -euo pipefail`. When grep -q matches early it exits, printf dies of
   SIGPIPE, pipefail turns the pipeline non-zero, the `if` goes false, and the
   offending commit is silently not reported — the guard then prints its
   success line. This file already documents the hazard in a comment and had
   fixed it for the two outer pre-filters; the three inner ones were left as
   pipes. Now here-strings, like the rest.

   Demonstrated on a synthetic revert-style commit (an AI trailer quoted near
   the top, then a 200KB body): the pipe form MISSES it, the here-string form
   detects it. A trailer in the conventional last position happens to survive
   the pipe form, because grep must read to the end before matching — which is
   why this never showed up in practice.

2. `chatgpt` was in BAD_NAME and BAD_ANY but not BAD_TRAILER, so a
   Co-authored-by naming ChatGPT with an email outside anthropic.com/openai.com
   was not caught. Confirmed by test, then added.

Verified before pushing this time: the amended script flags an AI-authored
commit, a large-body early trailer, and a ChatGPT trailer, and scans
claude_guide's full 345-commit history with zero false positives — that repo
has 46 commits with Claude or Anthropic in the subject, none of which are
identity or trailer hits.
2026-07-23 13:13:39 -07:00
yeasy 52f6c73478 ci: bound every workflow job with timeout-minutes
A wedged Chrome/mdPress step held a harness runner for 27 minutes yesterday
(normal run: ~4 min) and ignored `gh run cancel`; it only stopped because that
job happened to carry timeout-minutes: 30. An audit found 66 of the 101 jobs
across the cluster had no timeout at all — the same hang there would have held
a runner for GitHub's 6-hour default.

Values come from measured run history, not guesses. Across ~120 successful
runs the slowest workflow tops out at 10 min (Update Preview Publications),
CI at 6.5, Update Preview PDF at 4.8:

  30 min — jobs that run Chrome/mdPress/pandoc (3x the observed max, and the
           value harness already used)
  15 min — release, publish, deploy, check-link, chaincode-tests
  10 min — dependabot auto-merge

Every value has at least 6x headroom over its job's observed maximum, so this
should never turn a slow-but-working run into a failure.

Verified: all 72 workflow files still parse, and all 101 jobs now carry an
integer timeout in range.
2026-07-23 08:26:48 -07:00
yeasy 7c96d19fd4 fix(links): busybox 官方仓库 pointed at the homepage, duplicating the line above
git.busybox.net is gone — every path under it 404s, including /busybox/ — so
the earlier sweep replaced the dead repo link with https://busybox.net/. That
is byte-identical to the 官网 bullet directly above it, leaving two bullets
with different labels and the same URL, and a 官方仓库 label describing a page
that is not a repository.

Points it at the official source-download index instead and relabels it
源码下载. Verified 200.
2026-07-23 07:40:41 -07:00
yeasy d705dfb631 fix(ci): make the Mermaid fail-closed guard actually fire
The guard added earlier could never trigger. tools/render_mermaid.py has no
nonzero exit path — its own docstring said "Exits 0 even if some/all fail
(non-fatal)" — so `if ! render_mermaid.py ...; then exit 1; fi` never ran its
body, and a build that rendered zero diagrams still passed. Reproduced by
running the script with no Chrome on PATH: it printed the fallback warning and
exited 0.

Adds a --strict flag that exits 1 when Chrome is missing or any diagram fails
to render, and passes it from every workflow invocation. The default stays
lenient so local mobile-reader builds keep working, which is what the exit-0
behaviour was actually for.

Verified both directions: with no Chrome, --strict exits 1 and the default
exits 0; against the real book with Chrome, --strict renders every diagram and
exits 0.
2026-07-23 07:40:28 -07:00
yeasy 1c8f0dc14d chore: remove the remaining VuePress artifacts
Follows the devDependency removal. The build has been mdPress-only since
1.7.0 and nothing referenced these:

- .vuepress/ (config.js + .gitignore). The mirror it configured is still
  live, but no workflow in this repo builds or deploys it, so this was a
  recipe nobody ran. Local .vuepress/dist/ (400 files of Feb-2026 build
  output, never tracked) was removed from the working tree too — with its
  .gitignore gone it would otherwise have shown up as untracked noise.
- docker-compose.yml: the vuepress-offline service, plus the now-unused
  &mdpress-offline anchor that existed only to feed it.
- README: the 'docker run ... :vuepress' one-liner. That tag was last
  pushed 2022-06-25, so readers following it got a four-year-old snapshot
  of the book. 'mdpress serve' immediately above it still works.
- CODEOWNERS, .zhlintignore and check_project_rules.py entries for the
  deleted directory, and the check-link allowlist entry for the mirror
  (no content links to it).

The CHANGELOG entry recording the original CI removal is left alone — it
is history.

Verified: npm test passes (3 + 35), check_project_rules passes 202 files,
docker-compose.yml still parses with no dangling YAML aliases.
2026-07-22 22:51:34 -07:00
yeasy 2c8acc6c9c build(deps): retire the unused VuePress toolchain
The build moved to mdPress in 1.7.0 ('移除遗留的 vuepress 构建,统一使用
mdpress'), but the VuePress devDependencies stayed. Nothing references them:
build/serve/start/pdf all call mdpress, and the only occurrence of vuepress
in code is '.vuepress' inside check_project_rules.py's ignore list. Pages
still ran 'npm ci', so every deploy installed the whole VuePress tree as
dead weight.

They were also the entire source of the repo's 91 Dependabot alerts. The
lockfile carried two copies of several packages; the vulnerable ones were
all VuePress's (dompurify 2.4.3, highlight.js 9.18.5, katex 0.15.6,
mermaid 9.4.3) while mermaid-cli's copies are above every patched
threshold. Removing the three devDependencies drops 16 of the 20 flagged
packages from the tree entirely and leaves the other four at safe versions.

.vuepress/config.js is deliberately kept — the mirror site it configures is
still live, and whether to archive it is a separate decision.

Verified: npm test passes (3 + 35 tests) and check_project_rules passes
202 files.
2026-07-22 20:11:38 -07:00
yeasy a1f63a565b fix(links): repair dead external links found by a cluster-wide sweep
对 13 本书的 1,842 个外链做了一次全量 curl 健康检查(跟随重定向、带浏览器 UA),
逐条排除误报后确认的真死链。替换目标全部逐个验证返回 200。

注意两类**不是**缺陷、因此没有动的:
- platform.claude.com / docs.anthropic.com 当时返回 500,串行重试仍 500,
  但同日早些时候可正常访问——是上游临时故障,不是死链。
- docker_practice 列出的国内 registry 镜像连不上,是因为书里已明确标注
  「已停止服务」「已于 2024 年关闭」,属于故意保留的历史记录。
2026-07-22 16:51:15 -07:00
yeasy a42f94faad ci: add timeout-minutes to Identity Guard
harness_engineering_guide 的 lab/tests/unit/test_project_configuration.py 要求
每个工作流都写 timeout-minutes,我漏了,导致该仓库 CI 变红。

漏检原因值得记一笔:我本地批量跑测试时用的是 `ls tests/test_*.py`,
而 harness 的测试在 lab/tests/ 下、且用 pytest,这个 glob 一个都没匹配到,
于是它被静默报成"OK"。应当按各仓库 ci.yaml 里真正的测试命令来跑。

timeout-minutes 本身也是好实践:避免作业异常时空转到默认上限。
统一给 14 个仓库都加上,与该测试的其余约束(SHA 固定、禁 continue-on-error、
checkout 不持久化凭据)保持一致。
2026-07-22 16:04:50 -07:00
yeasy 38c89065b6 ci: fix Identity Guard trigger — it was never actually running
上一版给 push 只写了 tags-ignore: ['**'],本意是让发布 tag 不再触发一次
重复的全量审计。但 GitHub 的过滤规则是"只给了 tag 过滤器,就只在 tag 上跑",
因此这条配置的真实含义变成"只跑 tag,但忽略所有 tag" —— 工作流一次都不会触发。

症状很有迷惑性:工作流在 API 里状态是 active、名字也正常显示,
只是 runs 数恒为 0,同一次推送里 CI 和 Preview 都正常跑。
改为 branches: ['**'],覆盖全部分支且天然排除 tag,达到原本的意图。

教训记一句:光看"工作流已注册/active"不能算验证,必须确认它真的产生了 run。
2026-07-22 15:37:50 -07:00
yeasy 3781d9c382 ci: fix a latent false negative and cut Identity Guard runtime 50s to 1s
两处都是本地实测发现的,不是推测。

1) 漏判(正确性):尾注预筛写成 `git log --format=%B "$RANGE" | grep -qiE`,
   在 `set -o pipefail` 下 grep -q 命中即退出,左侧 git log 收到 SIGPIPE,
   整条管道返回非 0,if 判定为"没命中"从而跳过整个尾注检查。
   实测:沙箱里 8 条应报错误只报出 6 条,两个带 AI 尾注的提交被静默放过。
   改为 here-string(不再有管道),身份预筛同样改掉以杜绝这一类问题。

2) 性能:全量审计路径(新建分支推送、workflow_dispatch)原先为每个提交
   各起一个 git 子进程,docker_practice 1,592 个提交实测 50 秒。
   现在先用一次 git log 流式预筛,只有命中时才逐个提交定位;
   同一仓库实测降到 1 秒,且不改变任何判定结果。

回归验证:被删分支的真实 4 个提交在 push / pull_request / 新建分支三种
形态下仍全部拦下;专门构造的 2,502 提交仓库(身份流 258KB,远超管道缓冲区)
中埋在末尾的 AI 提交能被检出;14 个仓库完整历史仍然零误报;
范围解析失败仍 fail closed,删除分支仍正确放行。
2026-07-22 15:34:52 -07:00
yeasy f82e13017d ci: add Identity Guard rejecting AI-assistant commit attribution
起因:blockchain_guide 上曾有一个 claude/novel-content-extraction-r0wys3
分支,4 个提交的 author 和 committer 都是 Claude <noreply@anthropic.com>
(内容还是与本书无关的小说抓取脚本)。分支已删除,但暴露出一个缺口:
既有的 .git/hooks/commit-msg 只查提交信息里的 Co-authored-by 尾注,
查不到身份字段;而且本地钩子不随仓库分发,那 4 个提交来自云端会话,
根本不经过本地钩子。

因此把闸门放到服务端:本工作流在 push 与 pull_request 上扫描本次新增
提交的 author/committer 身份与 Co-authored-by 尾注,命中即失败。
本地另配 pre-commit(拦当前身份)与 pre-push(拦 cherry-pick/rebase
带进来的外来提交)作为纵深防御,二者不入库。

判定刻意收窄,避免误伤本仓库群里大量讨论 Claude/Codex 的正文:
只检查身份字段与行首锚定的 Co-authored-by 尾注,绝不扫描自由文本;
姓名要求全等("Claude Dubois" 这样的真人不受影响),邮箱按厂商域名
(含子域)匹配,并覆盖 claude[bot] 这类 GitHub App 身份。

已验证:
- 用被删分支的真实 4 个提交做回归,push / pull_request / 新建分支
  三种到达形态全部拦下;
- 全部 14 个仓库的完整历史(5,715 个提交,含 docker_practice 1,591
  个多人历史与 claude_guide 339 个满是 Claude 的提交)零误报;
- dependabot 的 Co-authored-by、真人 Claude Dubois、正文提到
  co-authored-by 但非尾注的提交,均正确放行;
- 范围解析不出来时 fail closed,只有确实没有 head 提交(删分支)才放行;
- tags-ignore 避免发布 tag 触发一次重复的全量审计。
2026-07-22 15:24:38 -07:00
yeasy 51698c89c5 fix(content): correct verified internal inconsistencies across 7 sections
均为书内自证的矛盾,无需外部来源:

- 19.3: golang:1.26-alpine 标注为 ~1GB,但 21.7 将 ~900MB 归给非 alpine 的
  golang:1.26,且 7.17 实测 alpine 版镜像为 295MB——alpine 变体不可能大于其
  非 alpine 版本。改为与 21.7 一致的「golang:1.26 基础镜像的 ~900MB」。
- 20_cases_os: 正文称通用镜像 100-300 MB,紧邻的表格却列 Ubuntu ~80 MB
  (与 4.2 的 ubuntu 24.04 78MB 一致)。正文改为 80-300 MB。
- 4.2: 「查找大于 500MB 的镜像」的 ^[0-9]+GB 不匹配小数,会漏掉 docker 实际
  输出的全部 x.yGB(本书自己的示例即为 2.5GB)。补充可选小数部分。
- 6.2: docker image ls 示例输出把 tag 混入 REPOSITORY 列
  (127.0.0.1:5000/ubuntu:latest + TAG latest),与同块 ubuntu/latest 行及
  本节自述的 tag 格式不符。
- 5.3: 生命周期状态图缺 Stopped --> Running,而 5.3.6 正是讲 docker start
  启动已停止的容器;原图中停止的容器只能被删除。
- 9.5: 端口映射图节点标签 "容器 (Class B: 80)" 语义错乱(Class B 是 IP 地址
  分类,与端口无关),改为「容器 (端口: 80)」。
- appendix/faq/errors.md: 标题「常见错误速查表」与 SUMMARY.md 及 faq/README
  两处链接文字「常见错误处理」不一致(全书 196 篇中唯一一处标题漂移)。
2026-07-16 23:20:25 -07:00
yeasy 7340cc16a8 fix(security): avoid world-writable storage in Laravel multi-stage examples
两处 Laravel 多阶段构建示例把 storage 目录设为 chmod -R 777,且全文没有任何
警告或说明,读者复制粘贴即得到 session/cache/log 目录全局可写的生产镜像。
这与本书 7.11(USER)与第 18 章的最小权限指引相矛盾。

改为将 storage 归属 www-data(php:8.3-fpm-alpine 中 php-fpm worker 的运行用户)
并设为 775:构建期 artisan 以 root 运行不受影响,运行期 www-data 仍可写。
2026-07-16 23:20:25 -07:00
yeasy 2ef6d80d4f fix(ci): make publication checks runner-safe 2026-07-11 06:44:12 -07:00
yeasy 44822cea16 test(ci): enforce preview publish step order 2026-07-10 19:29:30 -07:00
yeasy 1f970681ee test(ci): enforce exact preview tag commands 2026-07-10 19:29:30 -07:00
yeasy 397c66673b fix(ci): fail closed on preview lookup errors 2026-07-10 19:29:30 -07:00
yeasy 8cd6094ae9 fix(ci): keep preview tag current 2026-07-10 19:29:30 -07:00
yeasy ee0fbd7d38 fix(ci): attest releases and validate offline examples 2026-07-10 19:29:30 -07:00
yeasy daa6661b2b fix(ci): harden publishing and validate examples 2026-07-10 19:29:30 -07:00
yeasy 8eabe30dc2 fix(content): correct verified technical facts across cgroups, namespaces, etcd and k8s sections
- 12.3: daemon.json has no top-level cgroup-driver key; use exec-opts
  native.cgroupdriver (values cgroupfs/systemd) per official dockerd reference
- 12.2: USER namespace is not enabled by default; requires userns-remap
  (aligns with 18.1)
- 14.1: cgroup v1 deprecation and kubelet default-fail happen in v1.35, not
  v1.36 (per kubernetes.io cgroups doc)
- 15_etcd: maintenance window updated after etcd v3.7.0 release (2026-07-08)
  to 3.6/3.7
- 3.9.6: fix dangling sentence order in registry migration note
- tools: add 'from __future__ import annotations' so PEP 604 annotations run
  on Python 3.9 (fixes npm test)
2026-07-10 06:13:27 -07:00
yeasy bd944a2383 fix(ci): embed local images for PDF builds 2026-07-05 19:30:30 +08:00
Baohua YangandGitHub 47a6f56049 Merge pull request #567 from yeasy/dependabot/github_actions/dependencies-0ceda8b77f
chore(deps): bump the dependencies group across 1 directory with 2 updates
2026-07-05 04:22:43 -07:00
yeasy 68fec82301 ci: sanitize auto-release artifact tag names 2026-06-24 15:39:30 +08:00
yeasy a601794cd4 ci: guard manual auto-release tag name 2026-06-21 15:53:28 +08:00
yeasy 2bcc83dcf4 ci: build and attach HTML reader to each release
Renders Mermaid to SVG via the workflow's Chrome, pandoc --mathml, assembles a
single self-contained responsive HTML reader, and attaches <repo>-<tag>.html to
the GitHub Release next to the PDF. Non-blocking (continue-on-error).
2026-06-21 10:14:47 +08:00
yeasy 9fdffa9d91 fix(content): harden Docker practice guide 2026-06-16 21:23:21 -07:00
yeasy f4e684afeb docs: update Fedora install support list 2026-06-16 19:32:29 -07:00
yeasy 01a6b2dccd fix(content): align compose demo Dockerfiles to COPY over ADD
The app and django compose demos used ADD for plain local files, but the
book's in-text versions of the same examples (11.3_usage.md, 11.6_django.md)
and its own guidance (7.2/7.3, appendix best_practices) all use COPY. Align
the demos with the documented practice.
2026-06-11 23:17:58 -07:00
yeasy 0cfd55af7b fix(content): repair Django tutorial crash and complete the hardening sweep
Follow-ups to the 9 secret-hardening commits (each verified against
docs.docker.com / vendor docs; one outright new bug found and fixed):

- 11.6: eb5e4397 changed settings.py to a hard os.environ lookup but the
  web service never receives POSTGRES_PASSWORD (only db does; DATABASE_URL
  is set but never read) -> step-6 'docker compose up' crashed with
  KeyError. Pass the var to web; harden the leftover literal password in
  the 配置详解 snippet that contradicted the new guidance two lines down;
  blank line after the inserted sentence (bold heading merged into the
  paragraph); dev/prod table no longer claims dev uses 明文 passwords
- 11.8: FAQ still told readers to check passwords in .env after the same
  file banned passwords in .env -> point at secrets/db_password.txt;
  backup sidecar env vars updated to tiredofit/db-backup 4.x interface
  (DB01_* + DB01_PASS_FILE + DB01_BACKUP_INTERVAL - the unprefixed DB_*
  names are ignored by current :latest; verified against upstream README)
- demo/wordpress: compose now references secrets files that ship nowhere
  -> add README with the creation commands from 11.8; demo/django: align
  with the hardened 11.6 (env-injected password, passed to web too)
- 04_image multistage demos: go build without go.mod fails on module-mode
  Go (reproduced by reviewer on go1.26) -> add 'go mod init helloworld'
  matching the 7.17 doc pattern in all three Dockerfiles
- 21.7: init script reworked init-db.sql -> init-db.sh per the official
  image's env-reading .sh hook - removes the baked 'secure_password' AND
  the CREATE DATABASE myappdb collision with POSTGRES_DB that aborted
  first-boot init (ON_ERROR_STOP); compose passes APP_DB_PASSWORD;
  microservices init.sql mount annotated schema-only (POSTGRES_USER:
  appuser would collide with CREATE USER); Dockerfile-redis healthcheck
  now authenticates via REDISCLI_AUTH read from redis.conf (plain
  redis-cli ping gets NOAUTH against requirepass - same class as the
  compose sibling eb5e4397 already fixed); dev-container dev/dev creds
  annotated local-only
- 19.3: Grafana admin password 'admin' sat directly under the newly added
  security warning -> env-injected like the rest of the stack
2026-06-10 12:06:57 -07:00
yeasy eb5e4397e8 docs: remove hardcoded compose secrets 2026-06-08 16:16:36 -07:00
yeasy 070d4d6d69 fix(content): harden secret handling examples 2026-06-06 00:43:52 -07:00
yeasy 67d5fc775a fix(content): harden Compose credential examples 2026-06-04 01:02:59 -07:00
yeasy 130d03bf65 fix(content): harden dashboard and etcd examples 2026-06-03 00:40:40 -07:00
yeasy 8dd6a556c8 fix(content): refresh DCT and monitoring safety guidance 2026-06-02 00:48:00 -07:00
yeasy 3c1720ccc9 应用专业编辑审查(复核续):修复确定性引用/链接/口径等 1 处 2026-06-01 21:04:00 -07:00
yeasy 6fc032f7d6 应用专业编辑审查:修复版本/引用/技术准确性等 3 处 2026-06-01 11:11:28 -07:00
yeasy 1cdd3c582a fix(content): harden Docker examples 2026-06-01 10:33:50 -07:00
yeasy 094965e039 修复编辑问题:错别字/语病/术语/标点等 25 处(自动审校) 2026-05-31 22:20:50 -07:00
yeasy 48e86b7bec fix(appendix): correct .dockerignore typo in image-slimming FAQ 2026-05-28 11:38:28 -07:00
yeasy 9230b49b6b fix(04): replace deprecated openjdk base image with eclipse-temurin and fix 地 typo 2026-05-28 11:38:28 -07:00
yeasy 2185211041 fix(07): note FROM uses pre-FROM ARG, not ENV, for variable substitution 2026-05-28 11:38:27 -07:00
yeasy f09e800020 fix(content): harden copy-paste safety examples 2026-05-27 18:17:24 -07:00
yeasy 3a9ee19d22 docs(content): refresh Kubernetes helper versions 2026-05-26 00:45:20 -07:00
yeasy ea26f96297 fix(content): remove demo registry credential 2026-05-25 01:13:10 -07:00
yeasy 30f26d9195 chore(17): remove obsolete coreos_README.md leftover
This 7-line file was never in SUMMARY.md and its content is a strict
subset of the current 17.1_coreos_intro.md. It looks like a draft
that survived the chapter rename to NN.M_topic.md convention.
Removed so the directory only contains files reachable from the ToC.
2026-05-24 12:56:55 -07:00
yeasy fb361bb1f0 fix(appendix): use H2 for 附录七 to match sibling appendix files
The other appendix entries (附录四 best_practices, 附录五 debug,
附录六 resources, 附录八 learning_roadmap) all use H2. glossary.md
was the lone H1, which broke the table-of-contents nesting in
GitBook. Demoted to H2 to align.
2026-05-24 01:03:34 -07:00
yeasy 036f0486db fix(content): tighten safety guidance 2026-05-24 00:57:03 -07:00
yeasy 28c23d003e fix(content): harden Docker examples 2026-05-23 21:28:59 -07:00
yeasy 6a55219310 fix(11.3): use COPY (not ADD) in Flask/Redis intro Dockerfile
§7.3 of this book explicitly recommends COPY over ADD for simple
file copies ("在大多数情况下,你应该使用 COPY,而不是 ADD"). The intro
Compose example showed ADD without needing tar extraction or URL
download, contradicting the canonical guidance. Switched to COPY
so the first Dockerfile readers see matches the rule the book
teaches a few chapters later.
2026-05-23 21:27:01 -07:00
yeasy 8f4d88e350 docs: refine Buildx guidance 2026-05-22 07:58:38 -07:00
yeasy 7f83abc53b fix(content): correct Docker Engine 29.0.0 date and align login-action version
Docker Engine 29.0.0 was released 2025-11-10 per docs.docker.com release
notes, not 2025-11-11 (off by one day). Also bring docker/login-action
reference in 18.6 up to v4 to match the 21.2 example (v4 has been current
since 2026-03-04).
2026-05-22 03:19:37 -07:00
yeasy ec0fa15835 docs(content): harden Kubernetes and supply-chain examples 2026-05-22 00:53:38 -07:00
yeasy 8b9e4518c8 docs(content): add Mac alternatives, K8s transition guide, CI/CD registry push example
- Add OrbStack/Colima comparison table to Mac install chapter (3.7.4)
- Add Docker→K8s concept mapping paragraph to Ch13 intro
- Add KubeKey/RKE2 deployment tool notes to Ch14
- Add production image checklist to Dockerfile chapter summary
- Add build-and-push-to-registry workflow example to GitHub Actions section
- Expand Ch18 security summary with dimension table
2026-05-21 21:33:58 -07:00
yeasy dae0af9ae7 fix(content): DCT expiry tense + bundle buildx --check additions 2026-05-21 20:49:42 -07:00
yeasy 10b09f35eb fix(content): update DCT expiry tense and prefer named multistage COPY 2026-05-21 20:49:19 -07:00
yeasy e17bef96d2 docs(content): update Compose and safety guidance 2026-05-21 20:13:39 -07:00
yeasy a3567ff6a0 docs: use digest-based cosign signing 2026-05-21 19:14:33 -07:00
yeasy 9ef842ebb3 docs: update distro caveats 2026-05-21 18:25:54 -07:00
yeasy 2e625a3cdf fix(content): harden install and security guidance 2026-05-21 01:23:44 -07:00
yeasy d47afa7e75 docs: harden Docker practice security examples 2026-05-20 15:58:46 -07:00
yeasy 1b651e5f8c fix(content): refresh Docker and Kubernetes guidance 2026-05-20 09:16:36 -07:00
yeasy e91fe87822 fix(content): harden kubernetes and signing examples 2026-05-20 08:49:28 -07:00
yeasy bb97d5a46a fix(13.2): remove incorrect "Node lifecycle" (Pending/Running/Terminated)
The "节点周期" subsection listed `Pending`/`Running`/`Terminated` as
node phases, but those are **Pod** phases (pod.status.phase). Kubernetes
nodes use Conditions (Ready/MemoryPressure/DiskPressure/PIDPressure)
not phases; there is no "Terminated" node state. Removed the
misleading subsection and clarified the surviving "节点状态" section
with an explicit note distinguishing Pod phases from node conditions,
and added the eviction behavior when a node becomes Unknown.
2026-05-20 08:37:43 -07:00
yeasy 1f69884c8f Fix Chinese quote formatting 2026-05-20 08:02:42 -07:00
yeasy 4f92b3aa70 fix(19.3): add security trade-off note for cAdvisor privileged: true
The cAdvisor compose examples in 19.3.3 use `privileged: true`, which
contradicts the minimum-privilege / cap_drop=all guidance in chapter 18.
Add an explicit trade-off note before the first cAdvisor snippet
explaining the inconsistency and pointing to 18.4 for capability-based
hardening alternatives (cap_add: [SYS_ADMIN] + device_cgroup_rules
instead of full privileged mode).

This addresses the Round 1 review finding about pedagogical conflict
between the monitoring and security chapters.
2026-05-20 00:18:37 -07:00
yeasy 58504e9316 fix(review-fixes): surgical content corrections from web-verified library deep review 2026-05-19 19:45:02 -07:00
yeasy 4075330dba Fix architecture mermaid and MySQL version 2026-05-19 18:43:11 -07:00
yeasy e6bf228066 docs: update image signing and login guidance 2026-05-19 15:29:26 -07:00
yeasy 1b15b65bc5 Clarify AKS pricing tiers 2026-05-19 08:20:49 -07:00
yeasy 26da467052 docs: link deployment engineering guide 2026-05-18 22:37:02 -07:00
yeasy 7abaff237a test: add project rules check 2026-05-18 22:37:02 -07:00
yeasy 1c4e0538d8 Fix CI PDF order 2026-05-18 08:06:51 -07:00
yeasy 0b8f6e9b60 Refresh metadata and workflows 2026-05-18 07:38:58 -07:00
yeasy 5650315cb4 Remove demo TLS key 2026-05-17 20:28:01 -07:00
yeasy e21794ebde Fix stale image facts 2026-05-17 20:28:01 -07:00
yeasy 78ca8f6d19 Refresh Docker ecosystem 2026-05-16 14:09:31 -07:00
yeasy 1ba904a9ff Fix markdown format issues 2026-05-15 09:58:19 -07:00
yeasy 705d162f05 Fix image docs typos 2026-05-15 09:16:33 -07:00
yeasy 92be0050fd Fix docker debug note, Go modules, Compose V2, CentOS Quay migration 2026-05-15 08:11:38 +00:00
yeasy a20d1b19c4 Fix 3 broken external links in appendix 2026-05-14 02:27:32 +00:00
yeasy 9f481e88ca Fix go mod, Docker Hub rate limit, Compose verbose, docker debug, htpasswd security 2026-05-13 08:30:20 +00:00
yeasy ef5a97fa09 Fix VirtioFS note, cri-socket, componentstatuses, ES version and typo 2026-05-13 08:26:24 +00:00
yeasy 3c5c5911b0 Fix nginx version, IPVS removal, cgroups v2 and Redis config 2026-05-13 08:22:20 +00:00
yeasy e2742313f2 Fix typo in Fedora install guide 2026-05-08 21:20:03 +00:00
yeasy 2cea196860 Replace chromium-browser snap with setup-chrome 2026-05-08 04:19:18 +00:00