MoreRSS

site iconlinnana | 不二木子修改

全栈工程师,腾讯 -阿里 -TapTap,曾经的骑行爱好者。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

linnana | 不二木子的 RSS 预览

Terraform 念念碎

2024-11-01 08:00:00

前言

在过去的几年里,Terraform 和 Kubernetes 的陆续发布,全球大部分云服务提供商提供了无数的 Terraform Providers,使得声明式 API 进行 IaC 操作成了业界惯例。

Terraform 毫无疑问是一个很好的基础设施治理方案,采用声明式配置来描述基础设施,并进行标准化,比如使用版本控制管理配置、对变更进行评审,进行变更,回滚等操作,使得基础设施的管理过程和业界软件工程的最佳实践靠的越来越近。

之前在 TapTap 以及 心动都大规模使用 Terraform,我并不是这些仓库的维护者,但是因为 ops 团队经常无法满足实际的进度需求,有时候我自己也会去提 MR 来管理一些基础设施。同时在过去的一年多里,我一直都用 Terraform 来管理所需的基础设施。

在这里并不想写某个命令或者怎么安装某个资源,也不想分享它的好处,因为如果没有一定的收益,也就不会引入它了,因此更多的是分享自己的一些乱七八糟的想法,特别是从应用开发者的角度。

我们、他们是怎么用的

自动化

在 TapTap 使用 Atlantis 做 Pull Request Automation,基于 Atlantis 可以在 Pull Request 内按照机器人提示,在评论区输入对应指令,重新 plan。review plan 结果,确认出现的结果是你需要的。ops 同事 approve 之后,仓库会自动 apply。

在我自己的项目中都是用的非自托管的 Gitlab, 因此我们也就用了 Gitlab IaC 中的 OpenTofu 作 Pull Request Automation,它是兼容 Terraform 的。

提交 Pull Request 之后,会自动触发 fmt、validate、plan,可以非常方便的在 Pull Request 内看到 plan 的结果。

alt text

但它并不支持评论区指令识别的功能,自行 review plan 结果,确认出现的结果是你需要的,在 merge 之后,可以自动或者手动 apply。

alt text

最佳实践?

  • 建议遵循 Google 提供的 Best practices
  • Pull Request 记得标记 WIP 和 Draft,避免误操作合并
  • 如果你是自托管的 Gitlab,并使用 Atlantis 那么你可以 hack 更多的逻辑做 tf 文件命名、资源命名、格式等等的规范,让自动化的过程更规范。

  • 提供类似 infra/template/default.tf 这样的模版,
  • 尽可能地模块化

    alt textalt text

吐槽

引入 IaC 对基础设施服务进行标准化,其中的一个好处是减少开发人员和运维团队之间的摩擦,这和 DevOps 的理念是类似的。但使用的过程其实也有不少槽点。

  • 状态与协作
  • 重构变得困难
  • 访问控制

状态与协作

Terraform 是一个有状态的工具,它利用状态用来维护所定义的资源与在云供应商平台上创建的实际资源之间的映射关系。它必须在某个地方维护状态,并且需要在多人协作下保持状态的一致。因此在 apply 配置时,必须对状态文件进行锁定,带来的好处是我们可以确保在应用变更时,没有其他人在做同样的操作,但是可能导致数分钟的阻塞。在此期间,配置被独占,其他工程师无法进行任何变更。当有多个工程师管理基础设置的时候,可能会显得比较混乱,增加了协作成本

比如我在增加 grafana 时,helm 源一直超时,等待了几分钟后无果手贱强行结束了 Gitlab 的 apply job 导致的 state 锁定。于是所有人包括你自己都无法进行其他的 apply 操作了,只能在如图这个页面上点击 Action 中的 unlock 来解锁。

alt text

如下图是我尝试在本地进行一次测试时,自动生成的一些 state 文件,但在只有可能几十个左右的资源类型的时候执行 plan 命令依然需要好几分钟才能有结果。

alt text

给我的感受是:Terraform 在状态这一块有一个稀烂的实现。

重构变得困难

旧有未纳入资源的重构

很多团队可能并不一开始就使用 Terraform,而它无法很好地将已有资源纳入到它的状态管理中。好在,Terraform 引入了 import 命令缓解了这个问题。但又出现了另一个与此紧密相关的问题——如果你的栈很大,就必须为每个资源多次使用 terraform import 命令。如果这个过程无法自动化,这就变成了一个非常耗时且令人感到沮丧的过程。

想象一下,一个工程师在处理一个线上故障,TA 通过云服务商的控制台对生产环境的某个配置直接进行了修改。这个状态没有同步到 Terraform,之后会怎么样呢?

已纳入资源的重构

既然是 IaC, 从软件工程的实践上重构是必然的

比如可能从一个 sdk server 配置开始,然后逐渐分为 login、auth、 payment 等小配置。这也是 Terraform 推荐的:把配置分离为小粒度的配置。然而因为 state 的存在,甚至轻易改动已有资源名称都是”不可以”的,虽然有 state mv,这个过程就变得非常痛苦。因此随着时间的推移,配置就变得越来越难以维护。

访问控制

每个团队如何只具备自己需要的权限——有的可能只需要管理 A 资源、其他的可能有权使用 B 或者 C 资源,Terraform 在访问控制的抽象并没有太多的支持。于是,在 TapTap 的所使用的是不同团队采用不同模块,分别经过团队 ops、仓库统一负责人进行审核的方式。

还有一个问题是:该把秘钥保存在哪里?

Hashicorp 有他们的 Vault,但它使整个设置变得更加复杂。与 Vault 类似,使用使用私有 git 存储库,只要电脑不被偷,就不会有什么问题。如果你是在 CI/CD 上运行作业,可以将秘钥保存在环境变量中,但在一个复杂的系统中,可能就难以维护太多的环境变量。

在这个方面 Terraform 并没有提供一个更好的实践。

总结

基础设施即代码(IaC, Infrastructure as Code)是正确的方向!

但抽象总是尝试隐藏细节,而抽象同时也损失了细节。 Terraform 的引入对于应用开发者来说,配置的抽象程度提高了,也就引入了新的复杂度。

但为什么依然要选择 Terraform?在我看来,是并没有更好的选择。如果你的系统每天都有大量重复的基础设施小变更,那么 Terraform 会是一个不错的选择!

找到前 100 个付费用户真的太难了

2024-10-02 08:00:00

前言

对独立开发者和创业者来说,找到前 1000 个早期用户太关键了。

这是 Github 上 1000UserGuide 内的介绍,深以为然。但换个说法,我觉得或许会更贴切:对独立开发者和创业者来说,找到前 100 个付费用户真的太难了

看到大佬 laike9m 写的一篇博客《推广独立开发产品,我做了哪些尝试 》,我也来回顾一些自己尝试过的推广路子。

借鉴 1000UserGuide 的内容,以下是我尝试过的一些渠道和方式。

我尝试过的

✅ Reddit

我一般会选择 r/buildinpublic 板块,主要是可以蹭 buildinpublic 的流量。Reddit 的用户真的非常积极,而且大部分会抱着善意给予建议,有人愿意付费,也有人愿意给出建议或者改进意见。

alt text

甚至我第一次发帖一两天之后就有用户和开发者私信和我交流。 alt text

之后我也常在 r/SideProject r/IndieBiz r/iosapps 这个三个模块发帖子,但往往效果不佳。

另外 Reddit 部分板块的帖子审核是有点严格,乱发帖很容易被封号,我 5 个马甲号被封了 2 个……

✅ ProductHunt

除了有一个 launch schedule time 需要等等之外,几乎找不到太多的吐槽点。

大家也非常愿意给出自己的建议,也会有人愿意付费。

alt text

alt text

看到有人愿意 upvote,不管多少也算是一种认可!!!

❌ V2EX

我一般都会用小号发在分享创造模块,本来我觉得这里的用户本身已经经过翻墙这道门槛筛选了,用户的意愿会高不少,但往往是只赚吆喝,不赚钱!可能是我打开姿势不对……

另外:目前 V2EX 新用户注册已经需要邀请码了。

❌ 阮一峰的《科技爱好者周刊》

直接在上面提 issue 就可以了,被选中会在阮一峰的《科技爱好者周刊》 展示,但很不幸我并没有被选中过。

  • ❌ Twitter 上面有很多独立开发者,TA 们宣传每月赚了 XXX USD/month,但记住那不是,可能你的 tweet 只有几十的浏览量….
  • ❌ 小红书
  • ❌ 群组
  • indiehackers
  • w2solo
  • Medium
  • ❌ 即刻

总结

赚吆喝或许并不难,但是让用户用真金白银去买你的产品却是非常困难,它必须提供某种特定的价值。

因此,当你觉得有了技术就是一切的时候,当你打算埋头苦干三个月然后产品推出立即颠覆 xxx 的时候,花个几个周末的时间快速去测试一下产品的盈利能力,或许你对产品、技术、营销的定位会有不同的看法。

我想过这件事情比较难,但没想到这么难。或许这就是商业化的现实和残酷。

小小团队的工程基建

2024-09-15 08:00:00

不管是独立开发者还是数人小团队,打造高效试错的环境至关重要。获取更多的用户、把产品做好永远是第一要务。因此,我写这些并不是鼓励你在这些工具、平台上尝试,只是记录自己所使用到的一些平台和工具。

VCS

代码直接托管在 gitlab,免费薅的羊毛包括:

  • 基于 Git 的版本控制。
  • 基本的 CI/CD。
  • 限量的存储和 CI/CD 分钟:免费存储空间和每月 400 分钟的 CI/CD 运行时间。基本够用。
  • 协作工具:我们一般都用 issue 来驱动小的需求。
  • Container Registry:托管 Docker 容器镜像。
  • Project 和 members 不限制数量

如果你们是一个几人团队完全不需要自建,当然也可以用 Github。

Vercel

Vercel 把与 Next.js 云函数的融合做得非常好,10 个 endpoint 内是免费的,但是超过了则需要 $20/month,我一般都是不同的账号注册来薅羊毛,写一个非常小的项目时非常方便。也有 redis、postgress 这样的存储可以用在小项目上。

alt text

但有一点需要注意,Vercel 的 endpoint 如果超时超过了阈值是需要额外收费的,如果做 StableDifffusion 这样的 API 对接接口是非常耗时的,不建议放在 Vercel 上。否则可能早上刚起床房子就不是你的了!

我一般使用 netlify 在放静态类型的资源,比如官方教程或者文档这些,然后再 CNAME 到自定义域名上就可以了。

以上两个平台都支持 Gitlab 或者 Github 代码更新了自动触发 CI/CD。

Cloudflare

这个大部分接触过全球部署或者产品海外发行的工程师应该都知道。而且基础的功能都可以免费薅到羊毛。

以下是我主要使用的两个功能:

  • CDN: 免费又好用。
  • Workers:你甚至不再需要 Vercel 这种平台,只需要写 JS 就可以了。

Cloud Provider

如果项目的复杂度大到一定程度了,或许你开始考虑要上云了,那么恭喜你,至少算是“活下来了”。大部分 side project 基本是活不到这一步的。

到这里,你可以选的云厂商很多,包括但不仅限于:AWS/Google Cloud/Microsoft Azure/DigitalOcean 等等,这些厂商同样有各种各样的羊毛可以薅……

我用了 Vultr,它同样有 Free Tier Program 可以节省一点费用。

alt text

Kubernetes

我直接用了 Vultr Kubernetes Engine (VKE),这样不用自己来维护集群。

Gitlab 可以非常方便的连接 Kubernetes(参考文档

连接成功后,所有项目都可以共用它。 alt text

CI/CD

  1. Gitlab PR 触发 Gitlab CI/CD,使用 Gitlab shared runner 进行 lint、自动化测试。

  2. 在 Gitlab shared runne 上 build Docker 镜像,并 push 到 Gitlab Container Registry。

alt text

alt text

  1. 通过上述提到的 Kubernetes 连接,集群可以拉取到 Docker 镜像。

alt text

大致流程如图

alt text

Istio

如果一个域名一个服务,那么直接用一个 LB 就可以了,然后你可以把 LB 的流量导到对应的 Kubernetes Headless Service 上。

稍微复杂点,你有多个子域名,多个服务。比如 api.example.com、console..example.com 等等都区分开来,你可以选择:Nginx Ingress Controller,然后用 cert-manager 来管理 HTTPS 证书。

更复杂可能会引入类似 Istio 这样的 Service Mesh 方案,它的好处或者如何使用我这里不再重复介绍,具体可以看官方的文档。我觉得比较好用的方面:

  • Nginx Ingress Controller 的流量入口功能可以用 Istio Gateway 来代替。
  • 可以非常方便的实现金丝雀发布,支持基于请求 Header,Cookie 或者其他自定义范围。
  • 可以很快的实现服务的 A/B 测试。
  • 支持多种负载均衡、outlierDetection、connectionPool 等实现起来也非常简单。

alt text

  • 非常方便的集成 kiali 控制面板、prometheus、grafana、jaeger 等组件,提高系统的可观察性。

alt text

我目前就一直在用 Istio,目前感觉还不错。当然需要承认 sidecar 的方式是会带来一定的性能损失的。

也写点前端

2024-09-11 08:00:00

前言

在前司,出于前端工程师的紧缺,为了加快需求的推进,往往我自己也会承担一小部分在管理后台的前端开发工作。阿里“毕业”的后端工程师,应该都多多少少接触过类似 ice 这样的框架,并在无数个被前端拒绝的后台类需求里挣扎在前端代码里面。而平常的 side project 一般也都是自己来动手写前端。这里总结一下最近一年来写前端的一些乱七八糟的东西。

工具

TypeScript

TypeScript 可以说是让前端开发更能让人接受了,或者说是重新创造了一遍 JavaScript(better JavaScript 呀)。 Structural type system,泛型、类型检查等无疑给工程实践和维护上带来了巨大的益处。而且 TypeScript 的入门成本可以说非常低,即使你只有一点点 JavaScript 基础也很容易上手。

React

Library 方面则使用选择了 React。React 的学习成本真的非常低,除了 JSX,其它都是原生的 ES 的概念。而 VUE 谈不上难,却也是引入一些有别于 ES 的新概念。比如渲染列表,React 中只需要纯粹的 ES 方法 map,而 VUE 则需要理解 v-for 的新概念。当你使用 map 的时候它非常符合直觉,比如很多其他的编程语言都支持类似的操作,而当你看到 v-for 的时候并不符合直觉, 甚至你会想为什么不是 a-for/vfor 偏偏是 v-for 呢?

并且 React 对于我这类偶尔写前端的一个好处:需要记住的东西非常少。除了少数几个 hook 以及 API 基本上都不需要记,只需要写 TypeScript 就可以了。

提到 hook, 2019 年 React 正式引入了 hook 功能。使得所有的组件都可以写成函数的形式,比起原有的以 class 的多个方法来维护组件生命周期的方式,简化了代码,你看又少记几个生命周期方法。不过有了 hook 之后 function 也可以有状态了,如果不小心,很容易导致一些奇怪的 bug。State Management 我选择了 zustand,它真的非常符合官方的描述:small, fast and scalable bearbones state-management solution

react-bootstrap

组件库我选了 react-bootstrap,对于小型项目可以说非常方便了。

复用

不管是前端还是后端,为了提高维护性,我觉得有一点是不变:组件化。单一职责原则、高内聚,低耦合这些在后端非常基本的概念,用在前端也是一样的。提高可维护性的同时,每个组件也可以单独测试,确保其功能正确。

我把可复用的放在了 component 目录,pages 则是具体的页面。

alt text

当然我并不是一个专业的前端工程师,欢迎大家的建议!

为了更方便地在项目里 axios 我还对它进行了一点小小的封装。

alt text

测试

测试可以使用 JEST。为了更快地生成测试用例,我使用了 Jest Test Gen 这个插件。

vscode-jest 和 Jest Runner 等可以非常方便在编辑器内运行这些测试。

alt text

当然 npm test 也非常方便。

alt text

部署

使用 Docker 通过 Gitlab CI/CD 部署到 Kubernetes 也非常方便

alt text

alt text

前端的快速发展

一分钟之内会发生什么事情?Netflix 观看时间增长 70,000 小时;Snapchat 上有三百万视频被观看;Google 新增两百四十万次搜索;一个 JS 新框架被发明 (这条不是真的!)

这是我以前看到的一则关于前端快速发展的”笑话“,虽有点讥讽的意思,但是也从侧面看出来前端发展之快。

2014 年左右我第一次接触 JavaScript,当时还是 jQuery 大行其道的时候。当时我用 HTML5 的新特性 Canvas 做了一个 Doodle 网站,用户可以在上面自由的画一些有趣的东西,并增加各种各样类似于现在相机里的滤镜效果。当时写前端还是一件比较”痛苦“的事情,也是我后来放弃走前端方向的原因之一。不过有趣的是,凭着那时候做的 Doodle 网站,次年我在腾讯的实习招聘二面中把这个网站现场打开给面试官看,然后大部分面试时间都在和面试官聊这个网站具体的实现细节,最后顺利拿到了实习机会。

但 2024 年的今天,前端已经发展到和 10 年前大一样了!类型系统、工程化等等,甚至似乎真的每天都有新的东西冒出来,让人目不暇接。

2023 年博客数据分析

2023-12-24 08:00:00

没有目的的数据分析是没有意义的。过去几年我写博客并没有太多的目的,这也导致很难坚持下来。今年尝试去做一些改变,也是为了能够更好地坚持下去。对博客的访问数据做分析一方面是好奇与有趣,更重要的是对内容质量、推广方式、受众特征有一些概念和启发。

《2022 年总结》中对 2023 年的计划中有一项是【完成至少 6 篇博客】,这一目标今年完成得还算不错。 7 月份更换了新的博客主题后顺便把 Google Analytics 加上了。9 月份把 Github Pages 的域名 CNAME 到了之前一直使用的 linnana.me,又对博客的访问速度和性能做了简单测试。10 月份简单学习了如何使用 Google Looker Studio,于是在年底有了如下图的数据报告。

你可以访问这个链接(需科学上网)体验上面这份报告。

简单分析

虽然 3500+ 的总浏览次数并不多,甚至可能在样本量上太少不一定具备参考性。但看到有总共 833 位用户浏览过自己的博客还是觉得挺欣慰的。将近 4 分钟的用户平均会话时长至少说明内容质量是不错的。

内容

今年的博客内容集中在过去两年自己在 TapTap 作为团队 Tech Lead 推行的工程实践和管理记录,文章列表如下:

流量的陡峰主要来源于知乎上我的一个回答,此后每日的流量基本都是几个或者几十。

表现最好的是【面向开发者的技术文档如何维护】,可能网络上关于技术文档如何工程化的内容比较少。About 页的会话数量也符合了工程师的八卦心理。最让我有成就感的还是 【在 100 天里瘦了 30 斤】,有几位网友还特意在 TA 们的博文中有所提及。

用户

受众的地理位置体现了中国的特色(科学上网和肉身翻墙应该都有)。访问设备有 10 % 来自于 mobile 则出乎我的意料,这部分受众应该是用移动设备刷 V2EX/知乎的,但一般移动设备用户都不太会点开外部链接的(至少我不太会)。

受众的 Desktop 操作系统 60% 是 Mac 远超出了我的预期,说明工程师变得越来越有钱了。

本来想看看年龄、性别分布,以及其他用户特征,但不知道为什么数据一直出不来,只能作罢了。

来源

会话的主要来源是 V2EX 和知乎V2EX 的来源较多主要是今年我特意在一些互链交换帖子上做了一些回复,而知乎的来源是在知乎上我的一个回答

google 和 baidu 的来源则非常奇怪,或许是爬虫?或者真的是搜索流量?然后就是几个友链带来的个位数的流量。

搜索

在 Google Search Console 的后台上看几乎没有流量,也没有点击展示、点击方面的任何数据。国内因为没有做域名备案百度等搜索引擎也没办法提交录入。这也与上面的会话来源的数据比较符合。

胡思乱想

分析完了有什么结论呢?

内容上

因为我写博客更多是为了自我输出,并不是为了流量所以内容上依然是我想写什么就写什么。哈哈哈!

流量获得

V2EX 作为一个翻墙群体的论坛,流量质量是比较高的,是一个不错的推广地。但是由于论坛的特征主题的流量随着时间流量下降会非常明显。因此如果想持续获得流量,就得不断发帖或者回复。知乎上回答引流则很困难,只能靠某个大 V 也回答了问题才有可能获得不错的流量。当然 V2EX 和知乎上的推广依然可以坚持

从上面看搜索上基本没有流量,这也意味着流量变得不可持续!后面可以在搜索上做一些尝试。

访问便利性

上面提到受众的访问地理位置具有中国特色(墙),因此在没有备案的前提下国内用户访问便利性会受到很大的影响,不少用户由于访问速度的问题只是打开了首页但是没有浏览具体内容就离开了(这个开头有提到做过性能测试)。后面可以尝试做备案?或者内容静态化等。

面向开发者的技术文档如何维护

2023-09-28 08:00:00

前言

文档即产品门户。在一个商业化的项目中,如何用工程化的思维和实践更好的持续迭代文档是一件非常值得思考的问题。

平常工作中我们接触到的文档主要包括两类:

  • 类似 API 设计、架构设计、技术改动设计、逻辑设计等等
  • 面向用户比如开发者,更专注于教程和概念的文档。

在《我们是如何做 code review》中提到如果是新增功能以及稍大的改动请提前达成设计上的共识。这类前后端、客户端、后端之间达成设计一致的文档属于第一类。这类文档结构化程度没有那么明显,我们主要放在 Confluence 和 Gitlab Wiki 里。平时工作中,工程师接触可能更多的是第一类。

但这里主要谈第二类,这一类文档内容复杂,工程化的 ROI 更高,同时又因为其用户是开发者或者用户。内容往往会涉及到研发工程师、技术支持工程师、产品经理等等角色,工程化带来的业务价值也更明显。

内容是首要的

文档通常是为了产品用户的利益而创建的。它的主要目的通常是帮助用户完成产品的某些任务,因此在制作不同类型的技术文档时,应始终考虑到最终用户。而文档的内容是评判文档好坏的最好的标准。

  • 信息传达:文档的首要目标是传达信息。无论是教程、指南、手册还是说明书,文档需要提供详尽、明确和准确的信息,以满足读者的需求。良好的内容能够帮助读者理解和掌握所描述对象的知识和操作。
  • 解决问题:开发者查阅文档的常见原因是为了解决问题。好的文档内容能够回答读者可能提出的问题,并提供解决方案和示例。它可以帮助开发者快速定位问题,并给予正确的指导,提高效率和准确性。
  • 提供指导:文档内容应提供明确的指导,帮助开发者完成特定任务或实现特定目标。良好的内容能够清晰地解释步骤、操作和概念,并提供示例和提示,使开发者能够顺利地应用所述对象。
  • 用户体验:内容直接影响开发者的体验。清晰、准确、易于理解的内容可以提升开发者对文档的满意度,并增强开发者对所述对象的理解和操作能力。相反,混乱、模糊或错误的内容会导致开发者困惑和不满。

脱离好的内容,再好的工程化都是没有意义的,不要因噎废食。

文档由谁来写,谁来审核

谁来写

谁更熟悉就谁来写

我们的服务是面向开发者的,部分功能下游的产品经理或者运营也会接触到。

最熟悉的人当然是工程师,因此文档主要由开发此功能的工程师来写,当然也有部分文档由技术支持来写,极少部分由产品经理来写。之所有由技术支持、产品经理来写也是因为他们是最熟悉这部分功能的人。

而不熟悉这个功能的人则不应该参与文档编写。有部分公司觉得文档工作不重要就交给一个新人来写,我不太能接受这种做法。一个不熟悉业务的人正更需要帮助,却让 TA 来写文档,这多少有些荒谬。

谁审核

面向开发者的文档我们一般有至少一位技术支持工程师来做 review,技术支持工程师作为接触开发者和处理工单的第一经手人,他们更能从开发者角度来审视文档是否从开发者角度出来了。同时也可以增加之前有较多 review 经验的工程师来一起参与 review。

版本控制

上面提到我们的开发者文档编写者主要包括:完成该功能的研发工程师、技术支持、产品经理以及相应的审核人,而且往往我们会有多个功能需要同时写文档。因此使用版本控制系统可以尽可能的保证内容的更新得到合理的控制,冲突问题也更容易解决。

文档一般我们都会托管在 Gitlab 上,更新文档需要通过 Merge Request 或者 Pull Request 这样的机制来发起。不允许直接更新 master 分支。文档的修改必须要经过至少一位技术支持的 review 才能合并到 master 分支。

至于国际化多语言是采用一个 repo 多个模块还是多个 repo,取决于各自的实际情况。我们团队维护的文档目前只包括中文和英文,采用了两个 repo。

能自动化尽量自动化

CI/CD 自动化

因此在 MR / PR 被创建之后,CI/CD 会自动执行一次预发布,将文档部署到一个预发布环境中。同样 在 MR / PR 被合并到 master 分支之后同样也会执行一次预发布,打 tag 之后会自动更新预发布环境和正式环境。这用 Gitlab CI/CD 可以很方便的做到,如果你在使用 Github 则可以使用 Github Action 来达到同样的效果。

方便的脚本

为了减少 reviewer 的负担,同时提高 Merge Request 或者 Pull Request 的质量,我们通常会提供一些脚本方便发起者本地使用。 比如江宏大佬提供的 add-space-between-latin-and-cjk 可以非常方便地添加英文和中文词之间的空格。这些脚本会同样也会放在仓库中进行维护,比如当前博客的目录下就有一个 add-space-between-latin-and-cjk 脚本,每次新增或更新文档我都会实现一遍这个脚本。

尽可能保持一致的风格

让很多人措施行文风格一致是非常困难的,甚至不可能做到。文案风格的形成可能是在细节上,但更多在于文案作者本身的文学经验等等。

因此还是需要一些技术性的规范来提高行文风格一致的可能性。

规范或指南

在技术性的细节上我们团队主要遵守如下两个规范:

审核人或者团队尽可能固定

审核人或则审核团队对于保持文档长期的风格一致性是至关重要的。

软件工程历史可能是最典型的例子是 Linux Kernel(好的与坏的),同样的 Linux Kernel Docs 中也充满了 Linus Torvalds 以及内核核心团队的个人印记。或许也正是因为 Linus Torvalds 的坚持,在长年累月无数开发者不断地代码共享后,Linux Kernel Docs 仍然可以将文档和 Code as Document 理念贯彻到底。

因此在选择审核人时尽可能在某个模块地审核任务提交给一个到两个固定的审核人,这样有利于保持风格的一致性。

预发布

事实上在技术文档,尤其是面向开发者的技术文档的发布过程中,预发布发布是很重要的。

如果一个 PR 包含了在 Review 的时候未发现的事实错误和样式渲染错误,因为没有提前再次确认一遍。导致开发者因为这些错误,严重误解了某个功能(比如我们团队负责了支付业务),乃至进一步造成了严重的线上事故,这是不可接受的。同时没有预览环境也会导致工程师疑虑重重,不敢于发布,久而久之就会衍生出团队内对更新文档和发布的恐惧。

因此在 MR / PR 被创建之后,Gitlab CI/CD 会自动执行一次预发布,将文档部署到一个预发布环境中。我们的预发布环境提供了一个特有的共享 preview 域名,内部所有人都可以同时访问,这样让多人协作和审核变得更简单方便。在 MR / PR 被合并到 master 分支之后同样也会执行一次预发布。这样一些样式错误、渲染错误、内容出错等等问题可以更早的被大家发现。

只有从 master 打出 tag 之后文档才会自动部署到正式环境。

用了哪些工具

工欲善其事必先利其器,以下是我们在用的一些工具:

  • Docusaurus: 支持 Markdown、全文搜索、自定义主题等等功能。帮助开发者快速创建具有优雅外观和良好用户体验的文档网站。因为 Markdown 的易用性,不管是工程师还是技术支持、产品经理都可以很容易的参与进来。
  • Gitlab CI/CD: MR / PR 被创建之后,CI/CD 会自动执行一次预发布,将文档部署到一个预发布环境中。在 MR / PR 被合并到 master 分支之后同样也会执行一次预发布。我们用 Tag 进行发布管理,因此打 Tag 会自动执行一次预发布,并自动进行正式环境发布。如果代码托管在 Github 上也可以使用 Github Action 来完成。
  • LeanEngine: 文档仓库放在 LeanEngine 上是因为它是我们自己的产品,它提供了预发和正式环境。同时提供了一个用于预发环境的共享子域名,命令行工具也非常方便。如果有需要也可以选择 Github Pages 和 Cloudflare Pages 的静态页面产品。
  • 常用 scripts: 上面自动化章节里提到的类似 add-space-between-latin-and-cjk 的脚本,放在文档代码仓库中,在代码提交之前应该在本地做检查和执行。

如何让团队内写技术文档的氛围更好

团队成员可能会更重视项目业务代码仓库的建设,团队 leader 可能更关注业务带来的正面价值。而技术文档由于没有直观的业务价值,其长期建设的优先级往往被降级。那怎么让团队内写技术文档的氛围更好呢?

首先任何工程实践的实施都要以对现状的理解为基础 , 比如说对新工具的接受度、具体的业务特征、技术成熟度等。脱离具体的上下文,照搬“普适”的框架,会带来巨大的适配成本。我向来反对不尊重现状和团队需要的工程实践,因此 Team Leader 在推行工程实践时,更应该结合实际做渐进式地改善。

以下是我的一些思考和经验:

好的榜样

团队里的核心骨干或者 Team Leader 应该在这方面起到榜样的作用。TL 应该做到从自己开始,逐步地引导大家,也可以带头把一些自动化工具做好。当你能够以一个比较高的标准去持续输出文档的时候,身边的其他人多多少少也会被你感染,潜移默化地和你保持一致的标准。

在一个开放透明的团队里,好的习惯和理念是很容易被传播的。

直接的参与感

让团队内每个人都有参与的机会,而不是把写文档的机会或者任务把控在一到两个人的手上,同时也不要出现只有某个新人比较闲于是把写文档的任务交给 TA 的情况。直接的参与感不管是对于新人还是老同事都是最直接的。作为 TL 我一般会就一些有争议的话题咨询大家的意见,这样大家就会有参与进来的契机。

不要过早追求可度量化

过分地追求可度量化很容易导致指标倾向滑坡,比如追求工程师的 PR 数就很可能导致多了很多毫无意义的 PR。开发者类的文档可能我们会使用 TTFHW(Time to first hello world) 这类可度量的指标,但早期还是应该更注重团队内文档文化的形成。PR 数 & Issue 数、美观性再逐步去改善。

一些不错的参考和实践