今天是国庆假期之后新的一周,但我依然没有恢复过来。
前三天刷了两本书:《余生不上班:城市打工人的乡村冒险记》、《独家对话美的方洪波:我只是一个过客,不需要被任何人记住》。
然后在 AI 协作下,发布了第一个开源组件 upload-file v1.0.0 GA。
最后四天带家人,突击式打卡海洋馆、野生动物园、自然博物馆。
可以说假期里的每一天,节奏都远远快过日常。
或许,我应该慢下来。
向着 Forward Deployed Engineer 靠近
“慢下来”这个词,是我花了近两个月时间,去理解并尝试 FDE 之后,才慢慢品出来的。
FDE(Forward Deployed Engineer)是一种更靠近现场、更靠近决策的前线工程师角色。假定有一个原始需求,通过 AI 去实现它——这听起来有些 Vibe Coding 的味道:人负责想,机器负责写。
但故事不会一次成型。当需求实现到尾声的时候,我作为一个多变的产品经理提出了第一个需求改点(rc.1),然后开始指导 AI 去调整实现。
接着是 rc.2、rc.3……直到第九个改点(rc.9)之后,又改了一次,才最终敲定 GA 版本。

但,我真的不是产品经理。
升级依赖这件”小事”
如果说 FDE 是”慢下来”的实践,那么”升级依赖”就是我慢不下来的另一面。
我以前很怕”升级依赖”四个字。
不是因为难,是因为它永远排不进 todo list。
周一确定升级,周二本地验证发现一堆依赖报错,排查半天也没找到对策,周三又被其他需求打断,被迫退回。三天像三次轮回,每一次都败给”再等等”。
直到我给开源项目配置了 Dependabot,才发现这个流程早就有一套成熟的解决方案——我把它当问题,别人早已把它当基础设施。
配置 Dependabot
上手比想象中轻。在仓库根目录建一个 .github/dependabot.yml 就行。
它有两层必填:顶部 version: 2 声明语法版本,下面 updates 里,每个包管理器一段。每段三件事:管哪个生态、清单在哪个目录、多久查一次。
默认的全量更新,PR 会有点多。别怕,三个旋钮就能把它调顺。
旋钮一 · allow 白名单 — 只盯你想要的那部分,比如只升生产依赖、只升 patch 和 minor。
旋钮二 · cooldown 冷静期 — 新版本发布头几天先别动,给上游留出踩坑时间。Dependabot 默认就有 3 天冷静期,你还能给大版本单独调长。
旋钮三 · groups 分组 — 把一堆零散小更新并成一个 PR,每周一次”批量合并”,不用逐个点头。
下面是一个完整的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
version: 2
updates:
# ───── Maven ─────
- package-ecosystem: "maven" # Java 依赖
directory: "/"
schedule:
interval: "weekly" # 每周检查一次
open-pull-requests-limit: 10 # 同时最多 10 个开放 PR
labels:
- "dependencies"
commit-message:
prefix: "build" # 提交信息前缀:build(deps): bump
# 只允许更新生产依赖的 minor/patch 版本
allow:
- dependency-type: "production"
update-types:
- "version-update:semver-minor"
- "version-update:semver-patch"
# 按 semver 级别设置冷却期,防止供应链投毒
cooldown:
default-days: 3
semver-major-days: 14
semver-minor-days: 5
semver-patch-days: 1
exclude:
- "org.springframework.boot:*"
- "com.h2database:h2"
# 分组更新,减少 PR 数量
groups:
spring-boot:
patterns:
- "org.springframework.boot:*"
- "org.springframework:*"
exclude-patterns:
- "org.springframework.boot:spring-boot-starter-test"
test-deps:
dependency-type: "development"
patterns:
- "*"
# ───── GitHub Actions ─────
- package-ecosystem: "github-actions" # CI 工作流依赖
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
labels:
- "dependencies"
commit-message:
prefix: "build"
cooldown:
default-days: 3
groups:
all-actions:
patterns:
- "*"
GitHub Actions 工作流
Dependabot 管”该不该升级”,GitHub Actions 管”升完能不能用”。这是项目的 CI(持续集成)流水线,每次 push 或 PR 到 main 时自动触发,负责构建、测试和发布质量检查。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
name: build
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
name: Build & test (JDK $)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# The full reactor includes the jakarta modules (Boot 4 / Servlet 6), so it needs JDK 17+.
java: [ '17', '21' ]
steps:
- uses: actions/checkout@v4
- name: Set up JDK $
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: $
cache: maven
- name: Build & test
run: mvn -B verify
release-gates:
name: Release gates (binary compat + SBOM)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
cache: maven
- name: Binary-compatibility gate + SBOM
run: |
BASELINE=$(mvn -B -q -DforceStdout help:evaluate -Dexpression=compat.baseline.version)
PROFILES=sbom
if [ -n "$BASELINE" ] \
&& mvn -B -q dependency:get -Dartifact="cn.chenxinjie:upload-file-core:$BASELINE"; then
PROFILES=compat-check,sbom
else
echo "::warning title=compat gate skipped::baseline ${BASELINE:-<unknown>} is not resolvable; publish it to enable the binary-compatibility gate"
fi
mvn -B verify -P"$PROFILES" \
-pl upload-file-core,upload-file-servlet,upload-file-servlet-jakarta,upload-file-spring-boot-starter,upload-file-spring-boot-starter-jakarta,upload-file-store-jdbc,upload-file-store-redis
当升级从手工 todo 变成自动 PR,当验证从”我跑一遍”变成”流水线跑一遍”,节奏一下子慢了下来。
写在最后:FDE 的三点感想
回头看这两个月,FDE 给我的不是某种新头衔,而是三种朴素的感觉。
1、文档阅读理解非常重要。AI 越强,读文档越要细——它写的代码,得靠你读过的文档来校准。
2、节奏感非常重要。不是越快越好,而是该快时快、该慢时慢,rc.1 到 rc.9 教会我这一点。
3、开发门槛越来越低。门槛低不代表价值低,反而意味着”能不能看懂、能不能把握”,比”能不能写”更值钱。
慢下来,有时候不是退,是为了走得更远。