软件研发的协做过程当中,文档是必不可少的一环,有需求文档、接口文档、使用文档等等。当开始写文档时,首先会遇到两个问题:html
很早的时候采用 word+ppt 作文档,而后放到共享服务器(ftp,samba)上,这种方式会有文档锁定和覆盖的问题,几我的的小团队还能够,大不了更新的时喊一嗓子:“我要更新文档了,你们都不要占用某某文件(使用windows共享文档的童鞋应该很熟悉)”。更新完了还要再喊一嗓子。除此以外,因为 word 文件格式(word文件实际上是个压缩包,由不少 xml 和其余文件构成)太过于复杂,即使是借助 git 或者 svn 作版本控制,一旦产生冲突,很难经过肉眼合并和解决冲突。node
那么如何解决上述问题呢?这篇文章我用 gitbook + flow.ci 进行文档的发布、集成和部署,但愿给有需求的同窗一些参考。nginx
###如何进行文档协做 & 版本控制 (git+markdown) 开发团队使用 git 或 svn 做为协做和版本控制工具已是很成熟的方案了,固然也能够用于文档,只是word文档自己自然不太适合版本控制,markdown 是一种轻量级的标记语言, 学习简单,上手容易(具体语法参考 http://wowubuntu.com/markdown/
) , 配合 git 几乎能作到完美的文档版本控制 。git
###如何发布文档 (gitbook+nginx) 最好的方式是把文档发布为 web 网站,这样无需安装任何工具便可查看文档,更新时只需更新网站便可。在这里,用 gitbook 将 markdown 文件快速生成为网站。github
什么是 gitbook 呢?官网上是这么介绍的:web
GitBook is a modern publishing toolchain. Making both writing and collaboration easy.
简单来讲就是将 markdown 文档转换成 html、pdf、epub 等多种格式,不少开源软件和书籍都是用 gitbook 发布的, 如:Elasticsearch 权威指南、 Docker — 从入门到实践 等。docker
若是将 markdown 文档生成静态 html 部署到服务器(nginx)上,不只能够经过浏览器查看,并且一旦更新server,全部人看到的都是最新的文档。shell
###如何将文档进行持续集成 & 部署 (flow.ci)npm
CI(Continuous Integration)意为 “持续整合”,指代码的持续测试及与其余代码修改的整合与归并。ubuntu
CD(Continuous Deployment)意为 “持续部署”,指代码与其补丁的持续部署于整个代码库。
拿文档来看,持续部署就是内容的持续测试、与必要修改的归并及部署。在此,部署意为发布。举例来讲,“部署文档”是指输出文件被复制于web服务器为人阅览。
关于持续集成、持续部署不是一两句话能说清的,用于实现 持续集成、持续部署的工具链也五花八门,好比:最多见的 jenkins 、TravisCI 等,使用起来配置过于复杂。这篇文章里我将使用自家的持续集成服务 —— flow.ci 来进行文档的集成和部署,仅供参考。
####建一个git repo存储文档 首先,建一个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 接着,在 flow.ci 上建一个flow,语言模板选用 nodejs(使用 gitbook 须要用到node环境)。
同时删除掉 Cache、Install、Test等 step,这几个 step 是为 nodejs 项目提供的,咱们此处只须要 nodejs 运行时环境及 npm 工具。
####添加自定义脚本step 删除完以后添加自定义脚本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 iddeploy.sh
会调用gitbook命令编译markdown文档,并在首页head里面添加本次commit id号以及时间戳,并发布到服务器,脚本会为文末放出deploy.sh
会将gitbook生成的静态文件使用scp的方式copy到服务器, 因此 服务器必须添加 rsa key 信任 , rsa-key能够在项目的设置页找到,将其添加倒对应user的~/.ssh/authorized_keys中便可####添加邮件通知的step,文档部署成功后触发 Email Sender插件须要三个参数,分别是邮件接受者、邮件主题、邮件内容模板,以下:
###总结
至此,使用 flow.ci 快速发布文档的步骤已经所有完成。flow.ci 不仅是持续集成,持续部署的工具,也帮助咱们用自动化的视角审视手头繁琐的工做,将更多的时间用在新鲜事物上。
有任何疑问发邮件到 my@fir.im,分享你的观点:)
附上全部 step 中涉及的脚本:
#!/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}"
#!/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