
在由数十个和数百个交互服务组成的大型项目中,将文档作为代码(即文档作为代码 )的方法变得越来越强制。
我将展示如何在分类服务的现实中应用这一理念,或者,我将从其实现的第一阶段开始:自动更新文档中的数据。
工具套件
“将文档作为代码”的原则意味着在编写文档时使用与创建代码时相同的工具:文本标记语言,版本控制系统,代码审查和自动测试。 主要目标:为整个团队共同努力以达成最终结果创造条件-完整的知识库和使用单个产品服务的说明。 接下来,我将讨论我们选择用来解决此问题的特定工具。
作为一种文本标记语言,我们决定使用最通用的reStructuredText 。 除了提供用于构造文本的所有基本功能的大量指令外,该语言还支持关键的最终格式,包括项目所需的HTML。
通过Sphinx文档生成器将文件从.rst转换为.html。 它允许您创建静态网站,您可以为其创建自己的网站或使用现成的主题 。 我们的项目使用两个现成的主题-stanford-theme和bootstrap-theme 。 第二个包含子主题,可让您为关键界面元素设置不同的配色方案。
为了方便快捷地访问文档的当前版本,我们使用静态站点,该站点的主机是虚拟机,可从开发团队的局域网访问。
项目的源文件存储在Bitbucket存储库中,并且该站点仅由master分支中包含的文件生成。 只有通过pull-request才可以更新其中的数据,这使您可以在公共领域发布文档之前检查文档的所有新部分。
由于在完成文档的新部分与将其发送到站点之间必须检查其内容,因此整个链中的关键过程是构建站点和更新主机上数据的过程。 每次带有更新的请求合并到项目的主分支后,都应重复此过程。

为了实现此逻辑, Jenkins (在我们的情况下为持续集成开发系统)可以提供文档。 我将在各节中进一步介绍设置:
- 向Jenkins添加新节点
- Jenkinsfile的描述
- Jenkins和Bitbucket集成
向Jenkins添加新节点
要在站点上构建和更新文档,您必须为此预先注册一台机器作为Jenkins代理。
机器准备
根据Jenkins的要求 ,系统中包括的所有组件(包括主机和所有注册的代理节点)都必须安装JDK或JRE。 在我们的例子中,将使用JDK 8进行安装,足以运行以下命令:
sudo apt-get -y install java-1.8.0-openjdk git
主机将连接到代理以在其上执行分配的任务。 为此,您需要在代理上创建一个用户,在该用户下执行所有操作,并将所有Jenkins生成的文件存储在主文件夹中。 在Linux系统上,只需运行以下命令:
sudo adduser jenkins \--shell /bin/bash su jenkins
要在主机和代理之间建立连接,必须配置SSH并添加必要的授权密钥。 我们将在代理上生成密钥,然后将公共密钥添加到jenkins用户的authorized_keys
文件中。
我们将使用现成的python图像3.7在Docker容器中使用文档构建站点。 按照官方文档中的说明在代理上安装Docker。 要完成安装过程,您必须重新连接到代理。 通过运行加载测试映像的命令来验证安装:
docker run hello-world
为了不必代表超级用户(sudo)运行Docker命令,只需添加在安装阶段创建的用户docker组即可,将代表该组执行命令。
sudo usermod -aG docker $USER
Jenkins新节点配置
由于连接到代理需要授权,因此您必须在Jenkins设置中添加适当的凭据。 Jenkins官方文档中提供了有关如何在Windows计算机上执行此操作的详细说明。
重要信息:在Jenkinsfile中 ,在“ 标签”参数中的“ 配置Jenkins”部分->“ 管理构建环境 -> 节点名称 -> 配置”中指定的标识符用于指示将在其上执行所有操作的代理。
Jenkinsfile的描述
项目存储库的根目录包含Jenkinsfile ,其中包含有关以下内容的说明:
- 准备构建环境并安装依赖项
- 使用Sphinx建立网站
- 更新主机信息。
指令是使用特殊指令设置的,我们将在项目中使用的文件示例中进一步考虑其应用。
代理商指示
在Jenkins文件的开头,在Jenkins中指定代理的标签,将在该标签上执行所有操作。 为此,请使用agent指令 :
agent { label '-' }
环境准备
要执行sphinx-build site build命令,您需要设置环境变量,在其中存储实际数据路径。 另外,要更新主机上的信息,您必须预先指定包含文档的站点数据的存储路径。 环境指令允许您将这些值分配给变量:
environment { SPHINX_DIR = '.' //, Sphinx BUILD_DIR = 'project_home_built' // SOURCE_DIR = 'project_home_source' // .rst .md DEPLOY_HOST = 'username@127.1.1.0:/var/www/html/' //@IP__:__ }
主要动作
将在Jenkinsfile中执行的主要指令包含在stage指令中 ,该指令 由stage指令描述的不同步骤组成。 一个三阶段CI管道的简单示例:
pipeline { agent any stages { stage('Build') { steps { echo 'Building..' } } stage('Test') { steps { echo 'Testing..' } } stage('Deploy') { steps { echo 'Deploying....' } } } }
启动Docker容器并安装依赖项
首先,使用完成的python图像3.7运行Docker容器。 为此,请使用带有--rm和-i标志的docker run命令 。 然后依次执行以下操作:
stage('Install Dependencies') { steps { sh ''' docker run --rm -i python:3.7 python3 -m pip install --user --upgrade pip python3 -m pip install --user virtualenv python3 -m virtualenv pyenv . pyenv/bin/activate pip install -r \${SPHINX\_DIR}/requirements.txt ''' } }
用文档建立站点
现在让我们建立一个网站。 为此,请运行带有以下标志的sphinx-build命令 :
-q
:仅记录警告和错误;
-w
:将日志写入标志后指定的文件;
-b
:站点构建器的名称;
-d
:指定用于存储缓存文件的目录-doctree泡菜。
在启动程序集之前,使用rm -rf
删除以前的站点程序集和日志。 如果在其中一个阶段出现错误,则在Jenkins控制台中将显示sphinx-build执行日志。
stage('Build') { steps { // clear out old files sh 'rm -rf ${BUILD_DIR}' sh 'rm -f ${SPHINX_DIR}/sphinx-build.log' sh ''' ${WORKSPACE}/pyenv/bin/sphinx-build -q -w ${SPHINX_DIR}/sphinx-build.log \ -b html \ -d ${BUILD_DIR}/doctrees ${SOURCE\_DIR} ${BUILD\_DIR} ''' } post { failure { sh 'cat ${SPHINX_DIR}sphinx-build.log' } } }
主机站点更新
最后,我们将使用本地环境中可用的产品文档来更新为站点提供服务的主机上的信息。 在当前实现中,主机是注册为Jenkins代理的同一虚拟机,用于组装和更新文档。
作为同步工具,我们使用rsync实用程序。 为了使其正常工作,有必要在包含文档的站点所在的Docker容器与主机之间配置SSH连接。
为了使用Jenkinsfile配置SSH连接,必须在Jenkins中 安装以下插件 :
- SSH代理插件 -允许您在脚本中使用
sshagent
步骤以提供用户名/密钥形式的凭据。 - SSH凭据插件 -允许您在Jenkins设置中保存用户名/密钥形式的凭据。
安装插件之后,必须通过在“ 凭据”部分中填写表格来指定用于连接到主机的当前凭据:
- ID :标识符,将在Jenkinsfile中的步骤
sshagent
使用该标识符指示特定的凭证( docs-deployer
); - 用户名 :将用于执行站点数据更新操作的用户名(用户必须具有对主机的
/var/html
文件夹的写权限 ); - 私钥 :访问主机的私钥;
- 密码 :密钥的密码,如果它是在生成阶段设置的。
以下是脚本代码,该脚本代码通过SSH连接并使用在环境准备阶段指定的系统变量以及必要数据的路径来更新主机上的信息。 rsync命令的结果将写入日志,如果出现同步错误,它将显示在Jenkins控制台中。
stage('Deploy') { steps { sshagent(credentials: ['docs-deployer']) { sh ''' #!/bin/bash rm -f ${SPHINX_DIR}/rsync.log RSYNCOPT=(-aze 'ssh -o StrictHostKeyChecking=no') rsync "${RSYNCOPT[@]}" \ --delete \ ${BUILD_DIR_CI} ${DEPLOY_HOST}/ ''' } } post { failure { sh 'cat ${SPHINX_DIR}/rsync.log' } } }
Jenkins和Bitbucket集成
有很多方法可以组织Jenkins和Bitbucket的交互,但是在我们的项目中,我们决定使用Parameterized Builds for Jenkins插件。 官方文档包含有关安装插件的详细说明 ,以及必须为两个系统指定的设置。 要使用此插件,您需要创建一个Jenkins用户并为其生成一个特殊令牌,该令牌将允许该用户登录到系统。
创建用户和API令牌
要在Jenkins中创建新用户,请转到Jenkins设置 -> 用户管理 -> 创建用户 ,然后在表单中填写所有必要的凭据。
允许第三方脚本或应用程序使用Jenkins API而不实际传输用户密码的身份验证机制是可以为每个Jenkins用户生成的特殊API令牌。 为此:
- 使用先前创建的用户的详细信息登录到管理控制台;
- 去配置Jenkins- > 用户管理 ;
- 单击用户名右侧的齿轮图标,在该用户名下系统会授权使用该图标;
- 在参数列表中找到令牌API ,然后单击添加新令牌按钮;
- 在显示的字段中,指定API令牌的标识符,然后单击“ 生成”按钮;
- 按照屏幕上的提示,复制并保存生成的API令牌。
现在,在Bitbucket服务器的设置中,您可以指定默认用户以连接到Jenkins 。
结论
如果是更早的过程,则该过程包括几个步骤:
- 将更新下载到存储库
- 等待确认正确性;
- 建立一个带有文件的网站;
- 更新主机上的信息;
现在只需单击一个按钮在Bitbucket中合并。 如果在检查后不需要更改源文件,则在确认数据正确后立即更新文档的当前版本。
这极大地简化了技术编写者的任务,使他免于进行大量的手动操作,并且项目经理获得了一个方便的工具来跟踪文档添加和反馈。
自动化此过程是构建文档管理基础结构的第一步。 将来,我们计划添加自动测试,以检查文档中使用的外部链接的正确性,并且还希望创建内置于Sphinx的现成主题中的交互式界面对象。
感谢那些阅读本文的人的关注,很快我们将继续在我们的项目中共享创建文档的细节!