软件研发的协做过程当中,文档是必不可少的一环,有需求文档、接口文档、使用文档等等。当开始写文档时,首先会遇到两个问题:html
team members 之间如何协做?node
文档 OK 后如何分发,去哪里看?如何更新?nginx
很早的时候采用 word+ppt 作文档,而后放到共享服务器(ftp,samba)上,这种方式会有文档锁定和覆盖的问题,几我的的小团队还能够,大不了更新的时喊一嗓子:“我要更新文档了,你们都不要占用某某文件(使用windows共享文档的童鞋应该很熟悉)”。更新完了还要再喊一嗓子。除此以外,因为 word 文件格式(word文件实际上是个压缩包,由不少 xml 和其余文件构成)太过于复杂,即使是借助 git 或者 svn 作版本控制,一旦产生冲突,很难经过肉眼合并和解决冲突。git
那么如何解决上述问题呢?这篇文章我用 gitbook + flow.ci 进行文档的发布、集成和部署,但愿给有需求的同窗一些参考。github
开发团队使用 git 或 svn 做为协做和版本控制工具已是很成熟的方案了,固然也能够用于文档,只是word文档自己自然不太适合版本控制,markdown 是一种轻量级的标记语言, 学习简单,上手容易(具体语法参考 http://wowubuntu.com/markdown/
) , 配合 git 几乎能作到完美的文档版本控制 。web
最好的方式是把文档发布为 web 网站,这样无需安装任何工具便可查看文档,更新时只需更新网站便可。在这里,用 gitbook 将 markdown 文件快速生成为网站。docker
什么是 gitbook 呢?官网上是这么介绍的:shell
GitBook is a modern publishing toolchain. Making both writing and collaboration easy.
简单来讲就是将 markdown 文档转换成 html、pdf、epub 等多种格式,不少开源软件和书籍都是用 gitbook 发布的,
如:Elasticsearch 权威指南、 Docker — 从入门到实践 等。npm
若是将 markdown 文档生成静态 html 部署到服务器(nginx)上,不只能够经过浏览器查看,并且一旦更新server,全部人看到的都是最新的文档。ubuntu
CI(Continuous Integration)意为 “持续整合”,指代码的持续测试及与其余代码修改的整合与归并。
CD(Continuous Deployment)意为 “持续部署”,指代码与其补丁的持续部署于整个代码库。
拿文档来看,持续部署就是内容的持续测试、与必要修改的归并及部署。在此,部署意为发布。举例来讲,“部署文档”是指输出文件被复制于web服务器为人阅览。
关于持续集成、持续部署不是一两句话能说清的,用于实现 持续集成、持续部署的工具链也五花八门,好比:最多见的 jenkins 、TravisCI 等,使用起来配置过于复杂。这篇文章里我将使用自家的持续集成服务 —— flow.ci 来进行文档的集成和部署,仅供参考。
首先,建一个git repo存储文档,此处以 flow.ci官方文档 docs.flow.ci 为例, git repo 为
git@github.com:FIRHQ/flow.ci.git
目前 flow.ci 支持 github、bitbucket、国内的coding 和 私有部署的Gitlab。只要文档放在以上代码仓库的 git repo 均可以使用 flow.ci 进行集成. 如何在 flow.ci 建立项目能够 参考文档.
接着,在 flow.ci 上建一个flow,语言模板选用 nodejs(使用 gitbook 须要用到node环境)。
同时删除掉 Cache、Install、Test等 step,这几个 step 是为 nodejs 项目提供的,咱们此处只须要 nodejs 运行时环境及 npm 工具。
删除完以后添加自定义脚本step, 如何添加自定义脚本step可参考文档。 此处要添加两个自定义脚本,一个用于安装gitbook,一个用于编译文档并发布。
安装 gitbook 的自定义脚本 step 内容
flow_cmd "npm install gitbook-cli -g" --echo --retry --assert
此处的 flow_cmd 是 flow.ci 提供的一个函数,若是执行命令失败会进行重试
生成静态文件 && 部署 的自定义脚本step 内容
if [ "$FLOW_GIT_BRANCH" == "gitbook" ]; then # 只部署 gitbook分支 source get_commits_from_last.sh bash -x ./deploy.sh fi;
$FLOW_GIT_BRANCH
是一个环境变量,用来存储当前的git分支
get_commits_from_last.sh
会获取上次发布的日期以及git commit id
deploy.sh
会调用gitbook命令编译markdown文档,并在首页head里面添加本次commit id号以及时间戳,并发布到服务器,脚本会为文末放出
因为deploy.sh
会将gitbook生成的静态文件使用scp的方式copy到服务器, 因此 服务器必须添加 rsa key 信任 , rsa-key能够在项目的设置页找到,将其添加倒对应user的~/.ssh/authorized_keys中便可
Email Sender插件须要三个参数,分别是邮件接受者、邮件主题、邮件内容模板,以下:
至此,使用 flow.ci 快速发布文档的步骤已经所有完成。flow.ci 不仅是持续集成,持续部署的工具,也帮助咱们用自动化的视角审视手头繁琐的工做,将更多的时间用在新鲜事物上。
有任何疑问发邮件到 my@fir.im,分享你的观点:)
附上全部 step 中涉及的脚本:
get_commits_from_last.sh
#!/usr/bin/env bash # usage: sh get_commits_from_last.sh # 会export 2个环境变量: # DEPLOY_DIFF 与上次部署的时间差 # DEPLOY_LOG 与上次部署的变化 set -e STAGE="docs" URL="${STAGE}.flow.ci" HTML=`eval curl -sS ${URL}` # 获取首页html # 从首页html中提取上次 部署的ID 和 部署时间 LAST_ID=`echo $HTML | awk 'match($0, /-[0-9a-f]{7}/) { print substr( $0, RSTART+1, RLENGTH-1 )}'` LAST_TIME=`echo $HTML | awk 'match($0, /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}/) { print substr( $0, RSTART, RLENGTH )}'`"Z" FMT="%Y-%m-%dT%H:%M:%SZ" currDate=`date -u +"$FMT"` if [[ `uname` == 'Darwin' ]]; then ts=$(date -j -f "$FMT" "${currDate}" "+%s") ts2=$(date -j -f "$FMT" "${LAST_TIME}" "+%s") else ts=$(date --date="${currDate}" +"%s") ts2=$(date --date="${LAST_TIME}" +"%s") fi (( diff=(ts-ts2)/60 )) export DEPLOY_DIFF=$diff echo "Last $1 version : $LAST_ID @ ${LAST_TIME} (${DEPLOY_DIFF} minutes ago)" echo "-----------------------------------------" export DEPLOY_LOG=`git log --oneline $LAST_ID..HEAD` echo "${DEPLOY_LOG}"
deploy.sh
#!/bin/bash set -e # VARS DEPLOY_TIME=`date +%Y%m%d%H%M%S` REMOTE_DIR="/var/www/flow-doc" RELEASE_DIR="${REMOTE_DIR}/release" DEPLOY_DIR="${RELEASE_DIR}/${DEPLOY_TIME}" LATEST_DIR="${REMOTE_DIR}/latest" TARGET=prod USER=deploy # 需添加 rsa key 信任 HOST="此处修改成server的ip" PORT=22 # ssh端口 # 使用gitbook 生成静态文件 gitbook build docs dist # 获取当前时间 FMT="%Y-%m-%dT%H:%M:%SZ" currDate=`date -u +"$FMT"` if [[ `uname` == 'Darwin' ]]; then ts=$(date -j -f "$FMT" "${currDate}" "+%s") else ts=$(date --date="${currDate}" +"%s") fi # 获取当前分支 branch=$(git rev-parse --abbrev-ref HEAD) if [ -n "$FLOW_GIT_BRANCH" ] ; then branch=$FLOW_GIT_BRANCH fi # 获取commit log commit=$(git rev-parse --short HEAD) # 将本次部署的时间和COMMIT ID 嵌入倒首页html中 sed -i '/author/a\ \<meta name="version" content="production|COMMIT-TAG"\>' ./dist/index.html sed -i '/author/a\ \<meta http-equiv="last-modified" content="UPDATE-TIME"\>' ./dist/index.html sed -i "s/COMMIT-TAG/${branch}-${commit}/g" ./dist/index.html sed -i "s/UPDATE-TIME/${currDate}/g" ./dist/index.html # 开始部署 echo "########## Deploy to ${TARGET} ##########" ssh ${USER}@${HOST} -p ${PORT} "mkdir -p ${DEPLOY_DIR}" ssh ${USER}@${HOST} -p ${PORT} "rm -rfv ${LATEST_DIR}" scp -P ${PORT} -rv ./dist/* ${USER}@${HOST}:${DEPLOY_DIR} ssh ${USER}@${HOST} -p ${PORT} bash -x <<EOF ln -s ${DEPLOY_DIR} ${LATEST_DIR} exit EOF echo "########## Deploy $HOST success ##########" exit 0