GitHub Actions入門教程:自動(dòng)化部署靜態(tài)博客
前天,我使用 GitHub Actions 實(shí)現(xiàn)了靜態(tài)博客的自動(dòng)化部署,覺得它非常強(qiáng)大,只要你提交到 GitHub,后面的部署完全由 GitHub 自動(dòng)完成。
這里提的靜態(tài)博客,就是通過生成工具(eg:Hexo、Hugo、VuePress 等),直接將作者所書寫的博文編譯成最終的 html、css、js 等靜態(tài)文件。然后只需將生成的文件部署在服務(wù)器(eg:GitHub、Gitee、自建服務(wù)器)上面即可被在互聯(lián)網(wǎng)中訪問。
一般這類靜態(tài)博客部署的流程是:
寫一篇 markdown 文章。 執(zhí)行命令生成靜態(tài)文件,比如 npm run build。將靜態(tài)文件推送到博客倉庫,比如說 GitHub、Gitee 或者服務(wù)器,如果是 Gitee,還要手動(dòng)點(diǎn)擊更新按鈕部署。 訪問網(wǎng)址驗(yàn)證是否成功 為了備份你的博客,你可能要將你寫博客的項(xiàng)目也推送到倉庫。
博客就是用來寫文章的,每次寫篇文章還要搞這么多操作,時(shí)間長了你一定會(huì)覺得很累。
現(xiàn)在,你不會(huì)累了,使用 GitHub Actions 之后,流程可以簡化為:
寫一篇 markdown 文章。 提交到 GitHub。(這一步相當(dāng)于上面的第 5 步,不需要上傳 node_modules 文件夾)
結(jié)束了,是不是很方便?
當(dāng)然了,不止博客的部署,任意軟件的持續(xù)集成,都可以由 GitHub Actions 來完成,比如拉取代碼、運(yùn)行測(cè)試、登錄遠(yuǎn)程服務(wù)器,發(fā)布到第三方服務(wù)等。因此 GitHub Actions 是實(shí)現(xiàn)自動(dòng)化發(fā)布最便捷的方式了,值得每一個(gè)程序員學(xué)習(xí)和使用。
接下來,我以 GitHub Actions 實(shí)現(xiàn)靜態(tài)博客的自動(dòng)化部署為例,帶你入門 GitHub Actions,如有任何問題,歡迎文末留言討論。
本文的方法可以大大簡化靜態(tài)博客的部署流程,從機(jī)械的流程中解脫,專注于寫作,豈不快哉!那么現(xiàn)在就開始 GitHub Actions 之旅吧。
1. 先定一個(gè)小目標(biāo)
假如有以下四個(gè)倉庫:
[email protected]:somenzz/push_blog:寫博客的項(xiàng)目倉庫,里面有用于生成博客的 md 文件,和生成靜態(tài)博客的腳手架,比如 VuePress,hexo 等,該倉庫可以私有。 [email protected]:somenzz/somenzz.github.io:存放博客的靜態(tài)資源文件,用于 GitHub Pages 展示博客,必須開源。 [email protected]/somenzz/somenzz:存放博客的靜態(tài)資源文件,用于 Gitee Pages 展示博客,必須開源。 ip 地址:xxx.xxx.xxx.xxx,或者域名 somenzz.cn,路徑 /xxxx/public/,是自己購買的服務(wù)器,用于存放靜態(tài)博客資源文件。
現(xiàn)在的目標(biāo)就是,寫好一篇文章,向倉庫 1 推送之后,倉庫 2、3、4 自動(dòng)更新靜態(tài)資源文件。當(dāng)然了,你也可以根據(jù)自己情況,選擇性的更新 2、3、4 中的一個(gè)或多個(gè),只需要將對(duì)應(yīng)的步驟從 GitHub Actions 配置中注釋或刪除即可。
2. 理解 GitHub Actions
這里說下我對(duì) GitHub Actions 的理解,你提交到倉庫 1 后,GitHub 會(huì)監(jiān)控到,然后分配一臺(tái)虛擬機(jī)先將你的項(xiàng)目 checkout 過去,然后按照你指定的 step 順序執(zhí)行定義好的 action,這些 action 就包括 npm run build 生成靜態(tài)文件,push 到你指定的倉庫等動(dòng)作。
這就不可避免的涉及一些訪問權(quán)限的控制,你要向 GitHub 證明你對(duì)這些倉庫有控制權(quán)限,有些操作,還需要你提供 RSA 的私鑰,登錄的口令,當(dāng)然了,這些口令都是加密存放的,不會(huì)泄漏,可放心使用。
為了實(shí)現(xiàn)上面的小目標(biāo),我們要讓 GitHub 替我們做的事情如下:
編譯項(xiàng)目,生成靜態(tài)文件。也就是對(duì)倉庫 1: [email protected]:somenzz/push_blog,執(zhí)行 npm run build 生成博客的靜態(tài)資源。 將靜態(tài)資源 push 到 GitHub,也就是 push 到倉庫 2: [email protected]:somenzz/somenzz.github.io,這一步完成后 GitHub Pages 就部署完成了。 將倉庫 2 同步給倉庫 3,也就是 [email protected]:somenzz/somenzz.github.io 同步給 [email protected]/somenzz/somenzz,這樣兩個(gè)項(xiàng)目的靜態(tài)資源就一致了。 部署 Gitee Pages,因?yàn)?Gitee 的限制,需要手動(dòng)點(diǎn)一下更新,現(xiàn)在把這一步變成一個(gè) GitHub action。 使用 rsync 增量同步工具,將靜態(tài)資源同步的自購服務(wù)器的對(duì)應(yīng)目錄上。
3. ?一步一步跟我操作
現(xiàn)在,我們一步一步來。
首先在倉庫 1 的根目錄下,創(chuàng)建 .github/workflows/main.yml 文件,這就是 GitHub Actions 功能的配置文件,用于告訴 GitHub 要做哪些事情,寫入以下內(nèi)容
name:?Deploy?GitHub?Pages
#?觸發(fā)條件:在 push 到 master 分支后
on:
??push:
????branches:
??????-?master
#?任務(wù)
jobs:
??build-and-deploy:
????#?服務(wù)器環(huán)境:最新版 Ubuntu
????runs-on:?ubuntu-latest
????steps:
??????#?拉取代碼
??????-?name:?Checkout
????????uses:?actions/checkout@v2
????????with:
??????????persist-credentials:?false
??????#?1、生成靜態(tài)文件
??????-?name:?Build
????????run:?npm?install?&&?npm?run?build
??????#?2、部署到?GitHub?Pages
??????-?name:?Deploy
????????uses:?JamesIves/github-pages-deploy-action@releases/v3
????????with:
??????????ACCESS_TOKEN:?${{?secrets.ACCESS_TOKEN?}}
??????????REPOSITORY_NAME:?somenzz/somenzz.github.io
??????????BRANCH:?master
??????????FOLDER:?public
??????????#注意這里的?public?是倉庫根目錄下的?public,也就是?npm?run?build?生成靜態(tài)資源的路徑,比如有的人是?`docs/.vuepress/dist`
??????#?3、同步到?gitee?的倉庫
??????-?name:?Sync?to?Gitee
????????uses:?wearerequired/git-mirror-action@master
????????env:
??????????#?注意在?Settings->Secrets?配置?GITEE_RSA_PRIVATE_KEY
??????????SSH_PRIVATE_KEY:?${{?secrets.GITEE_RSA_PRIVATE_KEY?}}
????????with:
??????????#?注意替換為你的?GitHub?源倉庫地址
??????????source-repo:?[email protected]:somenzz/somenzz.github.io.git
??????????#?注意替換為你的?Gitee?目標(biāo)倉庫地址
??????????destination-repo:?[email protected]:somenzz/somenzz.git
??????#?4、部署到?Gitee?Pages
??????-?name:?Build?Gitee?Pages
????????uses:?yanglbme/gitee-pages-action@main
????????with:
??????????#?注意替換為你的?Gitee?用戶名
??????????gitee-username:?somenzz
??????????#?注意在?Settings->Secrets?配置?GITEE_PASSWORD
??????????gitee-password:?${{?secrets.GITEE_PASSWORD?}}
??????????#?注意替換為你的?Gitee?倉庫,倉庫名嚴(yán)格區(qū)分大小寫,請(qǐng)準(zhǔn)確填寫,否則會(huì)出錯(cuò)
??????????gitee-repo:?somenzz/somenzz
??????????#?要部署的分支,默認(rèn)是?master,若是其他分支,則需要指定(指定的分支必須存在)
??????????branch:?master
??????#?5、部署到?somenzz.cn?服務(wù)器
??????-?name:?rsync?deployments
????????uses:?burnett01/[email protected]
????????with:
??????????#?這里是?rsync?的參數(shù)?switches:?-avzh?--delete?--exclude=""?--include=""?--filter=""
??????????switches:?-avzh
??????????path:?public/
??????????remote_path:?/home/ubuntu/public/
??????????remote_host:?somenzz.cn
??????????remote_port:?22
??????????remote_user:?ubuntu
??????????remote_key:?${{?secrets.MY_UBUNTU_RSA_PRIVATE_KEY?}}
稍微有點(diǎn)長,為了便于你理解,每一步我都有注釋,這就是實(shí)現(xiàn)前面的小目標(biāo)需要的全部內(nèi)容,內(nèi)容遵循 YAML 格式,這里我做一個(gè)大致的說明:
on 表示觸發(fā)條件 jobs 表示要做的工作 jobs 下的 step 表示要做的步驟,前一步失敗,后面不會(huì)繼續(xù)執(zhí)行。 jobs 下的 step 下有 name、uses、with 等,表示一個(gè) action。 name 表示 action 的名稱,uses 表示使用哪個(gè)插件,with 表示傳給插件的參數(shù)。 secrets.XXX這個(gè) XXX 表示本倉庫的環(huán)境變量,配置在倉庫設(shè)置里面的 secrets 菜單欄,都是加密的。
uses 用的就是別人寫好的插件,持續(xù)集成由很多操作組成,比如抓取代碼、運(yùn)行測(cè)試、登錄遠(yuǎn)程服務(wù)器,發(fā)布到第三方服務(wù)等等,這些操作都用共性,有共性就能復(fù)用,GitHub 因此允許其他人把寫好的插件共享到插件市場(chǎng),以便他人使用。因此如果你需要某個(gè) action,不必自己寫復(fù)雜的腳本,直接引用他人寫好的 action 即可,你說方便不方便,插件市場(chǎng)見本文的學(xué)習(xí)資源小節(jié)。。
上述文件 .github/workflows/main.yml 寫好之后,先別著急 push,一旦 push,這些 actions 就會(huì)執(zhí)行,在參數(shù)正確的配置之前,報(bào)錯(cuò)那是肯定的。
接下來我說一下一些參數(shù)的意義以及如何確定這些參數(shù)的值。
1、secrets.ACCESS_TOKEN
對(duì)應(yīng)的配置代碼:
??????#?部署到?GitHub?Pages
??????-?name:?Deploy
????????uses:?JamesIves/github-pages-deploy-action@releases/v3
????????with:
??????????ACCESS_TOKEN:?${{?secrets.ACCESS_TOKEN?}}
??????????REPOSITORY_NAME:?somenzz/somenzz.github.io
??????????BRANCH:?master
??????????FOLDER:?public
這個(gè) ACCESS_TOKEN 是訪問 GitHub API 的令牌,可以在 GitHub 主頁,點(diǎn)擊個(gè)人頭像,Settings -> Developer settings -> Personal access tokens 進(jìn)行生成或更新,第一次生成后你可以看到這個(gè)令牌,然后再也不會(huì)顯示,因此你需要記下來,假如這個(gè)字符串是 aaa,然后打開倉庫 1 的設(shè)置頁面,設(shè)置 secrets,加入環(huán)境變量, name 是 ACCESS_TOKEN,value 是 aaa。如下圖所示:



這一段配置文件的作用就是,將 public 目錄內(nèi)的文件 push 到 somenzz/somenzz.github.io 的 master 分支,其中 public 就是 npm run build 生成的靜態(tài)資源所在的位置。
2、secrets.GITEE_RSA_PRIVATE_KEY
沒錯(cuò),這里就是 RSA 的私鑰,這里如果你不熟悉 RSA,可能會(huì)產(chǎn)生困惑,不是說公鑰在網(wǎng)上傳輸,私鑰不公開嗎?沒錯(cuò),確實(shí)是這樣,Gitee 上保存你賬戶對(duì)應(yīng)的公鑰,GitHub 倉庫的 secrets.GITEE_RSA_PRIVATE_KEY 保存著私鑰,因?yàn)?GitHub 的服務(wù)器不會(huì)讓你親自登錄設(shè)置密鑰對(duì),因此需要配置 secrets.GITEE_RSA_PRIVATE_KEY 來告知 GitHub,解密操作需要的私鑰并不是在網(wǎng)上傳輸,只有自己知道。
GitHub Actions 的服務(wù)器會(huì)使用你的賬戶登錄 Gitee,Gitee 使用你的公鑰加密后傳輸給這臺(tái)服務(wù)器,這臺(tái)服務(wù)器使用你設(shè)置的私鑰才能解密成功,通訊完成。如果想搞懂 RSA 算法可以看我之前寫的文章一文搞懂 RSA 算法,是全網(wǎng)講的最明白的文章。
這里說下如何生成 RSA 的公鑰和私鑰。
打開終端,輸入以下命令:
ssh-keygen?-t?ed25519?-C?"[email protected]"
這里的郵箱是你 Gitee 的注冊(cè)郵箱。如果服務(wù)器不支持 ed25519 算法,可以這樣:
ssh-keygen?-t?rsa?-b?4096?-C?"[email protected]"
我這里使用的就是第二種,然后一路回車即可。執(zhí)行完成后,在 ~/.ssh 目錄下可以看到 id_rsa、id_rsa.pub 等文件,其中私鑰就是 id_rsa,公鑰就是 id_rsa.pub,這就是密鑰對(duì),一個(gè)可用于加密,另一個(gè)可用于解密。
打開 gitee.com 并登錄,點(diǎn)擊自己頭像右下角,選擇設(shè)置-> ssh 公鑰,將 id_rsa.pub 的內(nèi)容復(fù)制到公鑰的輸入框里,公鑰的標(biāo)題可以自己填寫,如下圖所示:

接下來設(shè)置 secrets.GITEE_RSA_PRIVATE_KEY ,在 GitHub 上打開倉庫 1 的設(shè)置頁面,點(diǎn)擊 secrets,增加環(huán)境變量,name 就填寫 secrets.GITEE_RSA_PRIVATE_KEY,value 就填寫 id_rsa 文件的內(nèi)容,如下圖所示:

id_rsa 文件的內(nèi)容通常如下所示:
$?cat?id_rsa
-----BEGIN?OPENSSH?PRIVATE?KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEA4v2D0sH/puF4GWZdCfeontuoInVna7jxmtrnHxiOHkoIt5Mp/lMO
6kHWxpSxumQ+CAuqdVYGcsE+8FL0wCBBolpAK7jmX+S7l9wTkPJxYduOPxRBbKFKZp07R/
......
C2FVan1VGNpJ/wAAAA9zb21lbnp6QDE2My5jb20BAg==
-----END?OPENSSH?PRIVATE?KEY-----
注意第一行和最后一行也是要添加進(jìn)去的,不然 GitHub actions 會(huì)提示 id_rsa 格式不正確。
3、secrets.GITEE_PASSWORD
對(duì)應(yīng)的配置文件代碼段:
??????#?4、部署到?Gitee?Pages
??????-?name:?Build?Gitee?Pages
????????uses:?yanglbme/gitee-pages-action@main
????????with:
??????????#?注意替換為你的?Gitee?用戶名
??????????gitee-username:?somenzz
??????????#?注意在?Settings->Secrets?配置?GITEE_PASSWORD
??????????gitee-password:?${{?secrets.GITEE_PASSWORD?}}
??????????#?注意替換為你的?Gitee?倉庫,倉庫名嚴(yán)格區(qū)分大小寫,請(qǐng)準(zhǔn)確填寫,否則會(huì)出錯(cuò)
??????????gitee-repo:?somenzz/somenzz
??????????#?要部署的分支,默認(rèn)是?master,若是其他分支,則需要指定(指定的分支必須存在)
??????????branch:?master
這里就很簡單了,用戶名可以明文,密碼一定要放在 secrets 環(huán)境變量中,即使倉庫開源,也不至于泄漏自己的登錄密碼信息,這一步依然是在倉庫 1 的設(shè)置頁面添加 secrets 環(huán)境變量,和前述的操作一樣,不再贅述。
4、secrets.MY_UBUNTU_RSA_PRIVATE_KEY
對(duì)應(yīng)的配置文件代碼段
??????#?5、部署到?somenzz.cn?服務(wù)器
??????-?name:?rsync?deployments
????????uses:?burnett01/[email protected]
????????with:
??????????#?這里是?rsync?的參數(shù)?switches:?-avzh?--delete?--exclude=""?--include=""?--filter=""
??????????switches:?-avzh
??????????path:?public/
??????????remote_path:?/home/ubuntu/public/
??????????remote_host:?somenzz.cn
??????????remote_port:?22
??????????remote_user:?ubuntu
??????????remote_key:?${{?secrets.MY_UBUNTU_RSA_PRIVATE_KEY?}}
這個(gè)是自購服務(wù)器的私鑰,一般情況下云服務(wù)器都會(huì)提供一個(gè)私鑰文件,推薦你使用私鑰登錄服務(wù)器,和第二個(gè)參數(shù)的原理是一致的,如果服務(wù)器沒有給你這個(gè)私鑰,請(qǐng)自行生成一個(gè)可用于登錄的私鑰。
這里用到了 rsync,是一個(gè)增量同步工具,可以只傳輸有變化的文件,大大減輕網(wǎng)絡(luò)帶寬,具體的使用方法可參考阮一峰老師的教程[1]
4. 執(zhí)行、驗(yàn)證、結(jié)果通知
以上 4 個(gè)參數(shù)配置完成之后,就可以對(duì)倉庫 1 push,然后點(diǎn)開 GitHub 上的 actions 看下執(zhí)行過程。
$?cd?xxx/push_blog/
$?git?add?-u
$?git?commit?-m?"add?article"
$?git?push
打開 GitHub 上的 push_blog 倉庫,點(diǎn)擊 Actions,可以看到部署的結(jié)果,結(jié)果的標(biāo)題就是 commit 信息,如下圖所示:

點(diǎn)擊標(biāo)題,可以看到詳細(xì)情況:

再點(diǎn)擊,可以看到每一個(gè) action 的詳情:

接下來就是訪問下網(wǎng)站是否正常:
https://somenzz.github.io https://somenzz.gitee.io https://somenzz.cn
強(qiáng)制刷新下,看看新增的文章是否已經(jīng)到位。
你會(huì)問了,如果報(bào)錯(cuò)了怎么收到通知?點(diǎn)擊 Notifications 添加接受通知的郵件即可,如下圖所示:

如果覺得郵件不方便,想發(fā)送到微信,可以自己編寫 Python 爬取 Actions 的結(jié)果,再使用 Server醬發(fā)送到微信,使用方法參考前文為什么很多開源項(xiàng)目都使用了 Server醬
5. 學(xué)習(xí)資源
如果要學(xué)習(xí) GitHub Actions 來實(shí)現(xiàn)自己的部署流程,以下學(xué)習(xí)資源供你參考:
GitHub Actions 入門教程[2]。
GitHub Actions 官方文檔[3]。
GitHub Actions 官方插件市場(chǎng)[4]。
awesome-actions[5]。
最后的話
GitHub 的 Actions 除了支持 push 觸發(fā),也支持 schedule 觸發(fā),這就可以玩出很多花樣了,比如你可以在倉庫中寫一個(gè)腳本,然后編寫 workflow 讓 GitHub 每天定時(shí)執(zhí)行,相當(dāng)于免費(fèi)獲得了服務(wù)器的計(jì)算資源,可以參考阮一峰老師的文章GitHub Actions 教程:定時(shí)發(fā)送天氣郵件[6], 對(duì)于沒有服務(wù)器跑定時(shí)任務(wù)的人來說真的是一大福利。
本文講述了如何編寫 workflow,讓 GitHub Actions 自動(dòng)化部署靜態(tài)博客,可以讓程序員專心的寫博客,無需處理重復(fù)的部署操作,提升寫作效率。在這里拋磚引玉,供各位博客大佬參考使用,即使不寫博客,也可以修改下,變成自己的部署工作流。最后,GitHub Actions 是一個(gè) CI/CD(持續(xù)集成/持續(xù)部署)工具,值得每一個(gè)程序員學(xué)習(xí)使用。
如果你覺得本文有價(jià)值,請(qǐng)點(diǎn)贊、在看、轉(zhuǎn)發(fā),謝謝支持。
參考資料
教程: https://www.ruanyifeng.com/blog/2020/08/rsync.html
[2]GitHub Actions 入門教程: http://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html
[3]GitHub Actions 官方文檔: https://docs.github.com/en/actions
[4]GitHub Actions 官方插件市場(chǎng): https://github.com/marketplace?type=actions
[5]awesome-actions: https://github.com/sdras/awesome-actions
[6]GitHub Actions 教程:定時(shí)發(fā)送天氣郵件: http://www.ruanyifeng.com/blog/2019/12/github_actions.html
遇到問題?留言討論。
