使用 GitLab 托管

以 Markdown 格式查看

使用 GitLab CI/CD 可以在合并请求时自动生成预览链接,在更改合并到 main 分支时发布你的 Fern 文档,并在合并后删除预览链接。

前提条件
  • Node.js 版本 22 或更高
  • Fern CLI 已在本地安装
  • 包含 fern 文件夹的 Fern 项目(快速开始

将 Fern token 添加到 GitLab

1

生成 Fern token

在包含 fern 文件夹的目录中,从终端运行 fern token。这会生成一个组织范围的 token,用于在 CI/CD 中验证 Fern CLI。

$fern token

复制 token 输出 — 你将在下一步中将其添加到 GitLab。

2

将 Fern token 添加为 CI/CD 变量

  1. 登录 GitLab 并导航到你的 Fern 文档仓库。
  2. 转到 Settings > CI/CD
  3. 滚动到 Variables 部分,选择 Expand,然后点击 Add variable
  4. 将键设置为 FERN_TOKEN,将你在上一步中生成的 token 粘贴为值,取消选择 Protect variable,然后点击 Save changes

将项目访问 token 添加到 GitLab

要在合并请求上发布预览链接,你需要一个 GitLab 项目访问 token。

1

创建项目访问 token

  1. 在你的 GitLab 仓库中,转到 Settings > Access Tokens
  2. 点击 Add new token 并配置以下内容:
    • Token name:描述性名称(例如,fern-preview
    • Expiration date:根据需要设置(过期后需要重新生成)
    • Role:Reporter
    • Scopes:api
  3. 点击 Create project access token 并复制 token。
保存你的 token

立即保存生成的 token — 离开页面后将不会再显示。

2

将项目访问 token 添加为 CI/CD 变量

  1. 转到 Settings > CI/CD
  2. 滚动到 Variables 部分,选择 Expand,然后点击 Add variable
  3. 将键设置为 REPO_TOKEN,将项目访问 token 粘贴为值,取消选择 Protect variable,然后点击 Save changes

添加 CI/CD 流水线

在你的仓库根目录中创建一个 .gitlab-ci.yml 文件。这个流水线验证你的 API 定义,在每个合并请求上发布按分支的预览链接,在更改合并到 main 时发布你的文档,并删除已合并分支的预览部署。

.gitlab-ci.yml
1stages:
2 - check
3 - preview_docs
4 - publish_docs
5 - cleanup_preview
6
7before_script:
8 - apt-get update -y
9 - apt-get install -y curl jq
10 - curl -sL https://deb.nodesource.com/setup_current.x | bash -
11 - apt-get install -y nodejs
12 - npm install -g fern-api
13
14check:
15 stage: check
16 rules:
17 - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
18 - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
19 script:
20 - echo "Checking API is valid"
21 - fern check
22
23preview_docs:
24 stage: preview_docs
25 rules:
26 - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
27 script:
28 - echo "Generating preview for branch $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME..."
29 - |
30 OUTPUT=$(fern generate --docs --preview --id "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" --force 2>&1) || true
31 echo "$OUTPUT"
32 DEMO_URL=$(echo "$OUTPUT" | grep -oE -m1 '(https://[^[:space:]]+-preview-[^[:space:]]+) ' | tr -d ' ')
33 echo "Preview URL: $DEMO_URL"
34 - |
35 if [ -z "$DEMO_URL" ]; then
36 echo "No preview URL found"
37 exit 1
38 fi
39 curl --location --request POST \
40 --header "PRIVATE-TOKEN: $REPO_TOKEN" \
41 --header "Content-Type: application/json" \
42 --url "https://gitlab.com/api/v4/projects/$CI_MERGE_REQUEST_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" \
43 --data-raw "{ \"body\": \"Preview your docs [here]($DEMO_URL)\" }"
44
45publish_docs:
46 stage: publish_docs
47 rules:
48 - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
49 script:
50 - echo "Publishing Docs"
51 - fern generate --docs
52
53cleanup_preview:
54 stage: cleanup_preview
55 rules:
56 - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
57 script:
58 - echo "Looking up merged MR for commit $CI_COMMIT_SHA..."
59 - |
60 MR_INFO=$(curl -sf --header "PRIVATE-TOKEN: $REPO_TOKEN" \
61 "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_SHA/merge_requests") || {
62 echo "Failed to query MRs for commit — skipping cleanup"
63 exit 0
64 }
65 SOURCE_BRANCH=$(echo "$MR_INFO" | jq -r 'map(select(.state == "merged")) | .[0].source_branch // empty')
66
67 if [ -z "$SOURCE_BRANCH" ]; then
68 echo "No merged MR found for this commit (likely a direct push to main) — skipping cleanup"
69 exit 0
70 fi
71
72 echo "Deleting preview for branch: $SOURCE_BRANCH"
73 fern docs preview delete --id "$SOURCE_BRANCH" || echo "Preview deletion returned non-zero — it may already be gone"

提交并推送 .gitlab-ci.yml 文件到你的仓库。流水线会在合并请求时以及更改合并到默认分支时自动运行。