Github 是如何用 Github 撰寫 Github 文檔的
原文:https://github.com/blog/1939-how-github-uses-github-to-document-github
譯者:@公子
一份好的文檔能夠幫助人們理解,使用以及貢獻代碼到你的項目中,但這只是一個生成文檔的方程式的一半。生成文檔的底層系統使得人們,無論是你還是一塊和你工作的團隊,撰寫文檔變得更加容易。
撰寫文檔最難的一部分既不是編寫配置工具,也不是說明項目應該如何搭建和升級,而應該是文檔的遣詞造句。Github 文檔團隊的成員大多都是有使用XML文檔生成工具和復雜的CMS系統背景的。正因為他們飽受了這些工具的折磨,所以為了不再使用這些工具我們花費了大量的時間去思考我們自己的文檔生成流程和設置。
我們之前已經討論過我們如何使用 Github 建立 Github 了。在這里我們將著重討論一下我們如何使用 Github Page 服務運行 Github 幫助文檔 (目前每月有上百萬的訪問量)的。
我們以前的流程
幾個月前,我們把幫助文檔的地層從 Rails 程序遷移到 Jekyll 托管在了 Github Pages 上。之前我們的幫助文檔需要兩個相互獨立的項目倉庫:
- 用于托管維護網站、管理網站所用資源和文檔搜索增強的 Rails 應用程序
- 用戶托管由一大堆 Markdown 文件組成的網站具體內容
我們的 Rails 應用程序托管在一個第三方平臺上。隨著對代碼的日益升級,我們將它部署在了 Hubot ,這些都是我們在維護 Github 主站的閑暇之余完成的。(譯者注:Hubot 是 Github 開源的一款自動化智能化執行命令的機器人項目,具體刻參考 Hubot 的主頁。)
我們正常的撰寫流程可能是這個樣子的:
- 當有新特征開發出來的時候文檔團隊首先編寫好文檔內容
- 創建一個新的 issue 去追蹤這個特征
- 當文檔更新完畢一切就緒之后,我們會發起一個 pull request 去迭代更新文檔內容。
- PR 發起成功后,我們會使用 @ 方式提醒團隊(比如 @github/docs )并會讓隊友們審查一下我們的內容。
- 當這個特征開發完畢已經上線的時候,我們會合并之前創建的 PR。 使用 webhook 能夠幫助我們在 內容倉庫 快速激活我們部署的 Rails 應用程序。webhook 承擔了負責更新數據庫的任務。
下面是一個簡單的示例給我們展示了一下我們正常的工作流程:
使用 PR 進行工作是非常神奇的,因為它正好和我們在團隊中使用的 Github 工作流程是一致的。并且我們喜歡用 Markdown 語言書寫,更因為 Markdown 的語法能讓我們不用花費多少時間就有效的描述新特征的所有內容。
然而,我們的 Rails 增強程序安裝設置起來卻非常的麻煩:
- 由于我們依賴外部主機,所以我們需要專門的員工在我們的工程,運維和安全團隊中監控站點和他們發起的響應事件。
- 我們的文檔團隊并不能方便的在本地觀察內容的變化。雖然我們使用的是 Markdown 編寫的內容,可以實時預覽,但是我們能忍需要配置一個本地的 Rails 應用服務去運行腳本將內容導入到數據庫中然后觀察其在網站上的最終效果。
- 雖然我們不斷的調整 Rails 的服務器,但是我們注意到用戶的請求依舊使得網站訪問變得非常緩慢。由于 HTML 頁面是動態生成的,這就需要對數據庫進行請求,這就耗費了很多時間。為了加快訪問速度,我們還需要找尋更強大的緩存策略。
我們知道我們是時候做出改變做的更好了。
我們的新流程
當 Jekyll 2.0 發布的時候,我們看到了曙光,是時候該把我們這套該死的流程換成純靜態站了!特別是新增加的 Collections 文檔類型能讓你定義你需要的文件結構。另外,Jekyll 2.0 還增加了 Sass 和 CoffeeScript 的支持,這將使得編寫前端代碼變的更為簡單便捷。
開源的好處在于它是開放的。我們遷移到 Jekyll 后,我們也向 Jekyll 發起了很多 PR 使得它能更好的服務 Github Pages 的用戶。
使用了 Jekyll 之后,我們的工作流程發生了小小的變化。我們仍然使用 Markdown 并且我們仍然需要將內容 PR 到倉庫以便其它人審查。但是當我們發起的 PR 被合并之后,Github Pages 網站將會在幾秒內自動快速創建并部署。
下面是我們就如何使用 Jekyll 的核心功能以及我們使用的一些強化 Github 幫助文檔站點的插件列了一個簡單的綱要。
我們使用的 Gems
我們盡可能的依賴 Jekyll 代碼本身的功能去盡可能減小我們依賴自己維護的自定義插件,這樣可以減少我們的額外壓力。
Jekyll 2.0 內自帶的新的插件 Converter 使得用戶可以將任何 標記語言書寫的文件轉換成 HTML。這樣用戶可以隨便創作它的內容,Jekyll 只負責運行最后生成的 HTML文件就好了。舉個例子,只要你會,你甚至可以使用 AsciiDoc 語法書寫你的內容。
最后,我們開發了 jekyll-html-pipeline 插件,是我們之前開源的 html-pipeline 在 Jekyll 上的增強版。這個確保了我們的幫助站點的內容在 Github 上的任何地方看起來都是一樣的。我們同時也開發了我們自己的 Markdown filter 插件去提供一些語法擴展使得我們編寫文檔更方便。
搜索
老流程的 Rails 網站中,我們使用了 ElasticSearch 對我們的數據庫進行索引并增強了 Github 幫助文檔的搜索系統。
現在,我們使用 lunr-js 提供一個更快速的客戶端搜索體驗。當然我們也通過篩選分析發現絕大多數用戶都會依賴外部的搜索服務進入我們的文檔。所以,在新流程遷移完成之后,維護一個服務端的搜索引擎的解決方案看起來已經沒有多大的意義了。
內容引用
文檔團隊希望在編寫文檔的時候使用“內容引用”。內容引用允許你書寫一次某大段文字然后在網站的任何地方直接復用它。(這個靈感來自于 the DITA standard。 )
舊的 Rails 系統并不能允許我們書寫可復用的內容,但是現在我們有了強大的 Jekyll,它支持用戶自定義 data files 。舉個例子,我們已經創建了一個叫做conrefs.yml的文件,并且我們有一系列字符串形式的鍵值對集合像如下這樣:
repositories: create_new: 1. In the upper-right corner of any page, click {{ octicon-plus Plus symbol }}, and then click **New repository**. 
此時我們的鍵為repositories.create_new,其對應的值為下方的 Markdown 源代碼(及 "In the upper-right corner...")。我們現在只需要簡單一步就能在多個頁面內容中復用這段內容:
To start the process: {{ site.data.conrefs.repositories.create_new }} 2. Do something else. 3. You're done!
隨著 Github UI 的變化,我們也許需要修改圖片或者重新定義某些地方的指向。這個時候,我們僅僅只需要修改一個地方就能完成我們的變化,比起以前需要修改所有的地方簡直不知道方便了多少倍。
版本化顯示文檔
另一個隨著此次變化帶來的好處就是我們現在能夠顯示多版本的幫助文檔。隨著 Github 企業版 2.0.0 的發布,我們對之前的 11.10.3 版本 和現在的 2.0 版本這兩個不同版本提供了不同的幫助文檔內容。為了達到這個目的,我們在 Jekyll 站點內容使用了一個特別的audience變量,并在我們的 Pages 倉庫生成 HTML 的時候檢查這個變量。
例如,在我們的config.yml文件中,我們設置了一個鍵叫做audience其值為11.10.340。如果某個特征存在在新版本的 2.0 中但是不存在于老版本的 11.10.340 中,我們會使用如下語法標記上這一部分:
{% if site.audience != '11.10.340' %} This new feature... {% endif %}
當然更使我們高興的是,以上的實現都是基于 Jekyll 的核心功能,我們不需要為此創建或者維護任何其它的東西。
測試我們的站點
靜態站點并不意味著我們可以不為它開發測試驅動。
我們的第一個測試內容的工具是 html-proofer。這個工具通過測試我們網站的每一個 URL 幫助我們核實我們的鏈接和圖片都是正常的。
Ruby 的使用者們更熟悉使用 Capybara 在他們的測試中模擬網站的交互。在我們的靜態站點實現一個類似的工具這個主意看起來很瘋狂?并不! Github 的 bkeepers 4年前的一篇文章 已經談論過這個問題了。當時,我們創建了更強大的測試工具,它涵蓋了我們的內容測試和網站行為測試。舉個例子來說,我們通過檢查 YAML 文件中的鍵是否存在來確認某個內容引用是否有效,又或者說我們會測試我們的 JavaScript 代碼是否運行良好。
我們的幫助文檔在 CI(譯者注:持續集成系統)上運行,這樣確保了用戶不會拿到損壞的內容。
速度
正如我們之前提到的,新的流程使得我們的 Pages 服務比之前使用 Rails 系統的時候有了標志性的加快。這其中一部分原因當然是因為新站點是一堆靜態的 HTML 文件的集成——我們不需要向數據庫獲取任何內容。更值得注意的是,我們花費了大量的時間配置我們的 Pages 服務使得任何人運行它都是一樣的快速。我們有的好處,比如使用 CDN 分布式部署站點資源等,這些對每一個 Github 用戶來說也同樣是可用的。
讓 Github Pages 為你工作
文檔團隊通過 Github 利用 Github 的工作流程(譯者注:即前文提到的 Markdown 編寫內容,PR 提交等),Jekyll 以及 Github Pages 服務來提供一個高質量的文檔。Github Pages 提供給我們文檔團隊的好處同樣對每一個運行 Github Pages 的站點都是可用的。
隨著我們將文檔遷移到 Pages,我們再也不用重建任何新的組件了。我們花費了更少的時間建立一些東西并且更多的時間去討論我們的團隊和公司應該有什么樣的工作流程。通過使用和 Github 用戶一樣的托管系統,我們能夠提供更好更快的文檔系統。我們內部的工作流程是的我們變得更有成效,并且是的我們從未如此方便的提供版本特征,例如版本化內容。
如果你對 Github 文檔流程的簡歷有任何的疑問,無論何時,Github 都非常樂于幫助大家!