軟件研發的協做過程當中,文檔是必不可少的一環,有需求文檔、接口文檔、使用文檔等等。當開始寫文檔時,首先會遇到兩個問題: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