GitHub Actions 是 GitHub 的持續集成服務,于2018年10月推出。
這些天,我一直在試用,覺得它非常強大,有創意,比 Travis CI 玩法更多。
本文是一個簡單教程,演示如何使用 GitHub Actions 自動發布一個 React 應用到 GitHub Pages。
一、GitHub Actions 是什么?
大家知道,持續集成由很多操作組成,比如抓取代碼、運行測試、登錄遠程服務器,發布到第三方服務等等。GitHub 把這些操作就稱為 actions。
很多操作在不同項目里面是類似的,完全可以共享。GitHub 注意到了這一點,想出了一個很妙的點子,允許開發者把每個操作寫成獨立的腳本文件,存放到代碼倉庫,使得其他開發者可以引用。
如果你需要某個 action,不必自己寫復雜的腳本,直接引用他人寫好的 action 即可,整個持續集成過程,就變成了一個 actions 的組合。這就是 GitHub Actions 最特別的地方。
GitHub 做了一個官方市場,可以搜索到他人提交的 actions。另外,還有一個 awesome actions 的倉庫,也可以找到不少 action。
上面說了,每個 action 就是一個獨立腳本,因此可以做成代碼倉庫,使用userName/repoName
的語法引用 action。比如,actions/setup-node
就表示github.com/actions/setup-node
這個倉庫,它代表一個 action,作用是安裝 Node.js。事實上,GitHub 官方的 actions 都放在 github.com/actions 里面。
既然 actions 是代碼倉庫,當然就有版本的概念,用戶可以引用某個具體版本的 action。下面都是合法的 action 引用,用的就是 Git 的指針概念,詳見官方文檔。
actions/[email protected] # 指向一個 commit actions/[email protected] # 指向一個標簽 actions/[email protected] # 指向一個分支
二、基本概念
GitHub Actions 有一些自己的術語。
(1)workflow (工作流程):持續集成一次運行的過程,就是一個 workflow。
(2)job (任務):一個 workflow 由一個或多個 jobs 構成,含義是一次持續集成的運行,可以完成多個任務。
(3)step(步驟):每個 job 由多個 step 構成,一步步完成。
(4)action (動作):每個 step 可以依次執行一個或多個命令(action)。
三、workflow 文件
GitHub Actions 的配置文件叫做 workflow 文件,存放在代碼倉庫的.github/workflows
目錄。
workflow 文件采用 YAML 格式,文件名可以任意取,但是后綴名統一為.yml
,比如foo.yml
。一個庫可以有多個 workflow 文件。GitHub 只要發現.github/workflows
目錄里面有.yml
文件,就會自動運行該文件。
workflow 文件的配置字段非常多,詳見官方文檔。下面是一些基本字段。
(1)name
name
字段是 workflow 的名稱。如果省略該字段,默認為當前 workflow 的文件名。
name: GitHub Actions Demo
(2)on
on
字段指定觸發 workflow 的條件,通常是某些事件。
on: push
上面代碼指定,push
事件觸發 workflow。
on
字段也可以是事件的數組。
on: [push, pull_request]
上面代碼指定,push
事件或pull_request
事件都可以觸發 workflow。
完整的事件列表,請查看官方文檔。除了代碼庫事件,GitHub Actions 也支持外部事件觸發,或者定時運行。
(3)on.<push|pull_request>.<tags|branches>
指定觸發事件時,可以限定分支或標簽。
on: push: branches: - master
上面代碼指定,只有master
分支發生push
事件時,才會觸發 workflow。
(4)jobs.<job_id>.name
workflow 文件的主體是jobs
字段,表示要執行的一項或多項任務。
jobs
字段里面,需要寫出每一項任務的job_id
,具體名稱自定義。job_id
里面的name
字段是任務的說明。
jobs: my_first_job: name: My first job my_second_job: name: My second job
上面代碼的jobs
字段包含兩項任務,job_id
分別是my_first_job
和my_second_job
。
(5)jobs.<job_id>.needs
needs
字段指定當前任務的依賴關系,即運行順序。
jobs: job1: job2: needs: job1 job3: needs: [job1, job2]
上面代碼中,job1
必須先于job2
完成,而job3
等待job1
和job2
的完成才能運行。因此,這個 workflow 的運行順序依次為:job1
、job2
、job3
。
(6)jobs.<job_id>.runs-on
runs-on
字段指定運行所需要的虛擬機環境。它是必填字段。目前可用的虛擬機如下。
ubuntu-latest
,ubuntu-18.04
或ubuntu-16.04
windows-latest
,windows-2019
或windows-2016
macOS-latest
或macOS-10.14
下面代碼指定虛擬機環境為ubuntu-18.04
。
runs-on: ubuntu-18.04
(7)jobs.<job_id>.steps
steps
字段指定每個 Job 的運行步驟,可以包含一個或多個步驟。每個步驟都可以指定以下三個字段。
jobs.<job_id>.steps.name
:步驟名稱。jobs.<job_id>.steps.run
:該步驟運行的命令或者 action。jobs.<job_id>.steps.env
:該步驟所需的環境變量。
下面是一個完整的 workflow 文件的范例。
name: Greeting from Mona on: push jobs: my-job: name: My Job runs-on: ubuntu-latest steps: - name: Print a greeting env: MY_VAR: Hi there! My name is FIRST_NAME: Mona MIDDLE_NAME: The LAST_NAME: Octocat run: | echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.
上面代碼中,steps
字段只包括一個步驟。該步驟先注入四個環境變量,然后執行一條 Bash 命令。
四、實例:React 項目發布到 GitHub Pages
下面是一個實例,通過 GitHub Actions 構建一個 React 項目,并發布到 GitHub Pages。最終代碼都在這個倉庫里面,發布后的參考網址為ruanyf.github.io/github-actions-demo。
第一步,GitHub Actions 目前還處在測試階段,需要到這個網址申請測試資格。申請以后,可能需要幾天才能通過。據說,2019年11月就會放開。
獲得資格后,倉庫頂部的菜單會出現Actions
一項。
第二步,這個示例需要將構建成果發到 GitHub 倉庫,因此需要 GitHub 密鑰。按照官方文檔,生成一個密鑰。然后,將這個密鑰儲存到當前倉庫的Settings/Secrets
里面。
上圖是儲存秘密的環境變量的地方。環境變量的名字可以隨便起,這里用的是ACCESS_TOKEN
。如果你不用這個名字,后面腳本里的變量名也要跟著改。
第三步,本地計算機使用create-react-app
,生成一個標準的 React 應用。
$ npx create-react-app github-actions-demo $ cd github-actions-demo
然后,打開package.json
文件,加一個homepage
字段,表示該應用發布后的根目錄(參見官方文檔)。
"homepage": "https://[username].github.io/github-actions-demo",
上面代碼中,將[username]
替換成你的 GitHub 用戶名,參見范例。
第四步,在這個倉庫的.github/workflows
目錄,生成一個 workflow 文件,名字可以隨便取,這個示例是ci.yml
。
我們選用一個別人已經寫好的 action:JamesIves/github-pages-deploy-action,它提供了 workflow 的范例文件,直接拷貝過來就行了(查看源碼)。
name: GitHub Actions Build and Deploy Demo on: push: branches: - master jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/[email protected] - name: Build and Deploy uses: JamesIves/[email protected] env: ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} BRANCH: gh-pages FOLDER: build BUILD_SCRIPT: npm install && npm run build
上面這個 workflow 文件的要點如下。
- 整個流程在
master
分支發生push
事件時觸發。- 只有一個
job
,運行在虛擬機環境ubuntu-latest
。- 第一步是獲取源碼,使用的 action 是
actions/checkout
。- 第二步是構建和部署,使用的 action 是
JamesIves/github-pages-deploy-action
。- 第二步需要四個環境變量,分別為 GitHub 密鑰、發布分支、構建成果所在目錄、構建腳本。其中,只有 GitHub 密鑰是秘密變量,需要寫在雙括號里面,其他三個都可以直接寫在文件里。
第五步,保存上面的文件后,將整個倉庫推送到 GitHub。
GitHub 發現了 workflow 文件以后,就會自動運行。你可以在網站上實時查看運行日志,日志默認保存30天。
等到 workflow 運行結束,訪問 GitHub Page,會看到構建成果已經發上網了。
以后,每次修改后推送源碼,GitHub Actions 都會自動運行,將構建產物發布到網頁。
五、參考鏈接
- GitHub Pages 官方文檔
- Github Actions for web apps, Luke Boyle
- My First Week With GitHub Actions, Adam Zolyak
(完)
Rw 說:
這樣貌似可以制作靜態博客網站
2019年9月12日 11:38 | # | 引用
Wu 說:
現在使用 netlify 和 GitHub Pages 配合 actions 搭建個人站點,再加上公共 CDN,體驗很好了。
2019年9月12日 14:11 | # | 引用
DY 說:
甚至可以動態吧
2019年9月12日 14:16 | # | 引用
小兵 說:
為啥我在github上還看不到action
2019年9月12日 14:46 | # | 引用
Tuuu Nya 說:
我的Hexo博客 終于可以不用自己那一套Hook了.... 這個方法感覺優雅多了。
2019年9月12日 16:32 | # | 引用
dujm 說:
要github審核通過才有
2019年9月12日 16:36 | # | 引用
bigma 說:
我之前用的hook 加jenkins.這個action 看起來能替代我之前的流程
2019年9月12日 17:29 | # | 引用
davix 說:
正驚訝今天怎么沒等到科技愛好者周刊,才想起來還沒到周五呢
2019年9月12日 19:51 | # | 引用
SimonAking 說:
阮老師中秋快樂!
2019年9月13日 18:22 | # | 引用
jacktan 說:
runs-on 可以使用自定義的image嗎?如果test任務依賴mysql,如何解決呢?
2019年9月13日 22:15 | # | 引用
平凡 說:
要是介紹一波自己寫的 action 就好了, 我現在一直卡死在 push 處, 上不去.
2019年9月14日 20:42 | # | 引用
superlb 說:
感覺和Travis CI區別不大
2019年9月14日 21:59 | # | 引用
Junle 說:
自定義的trigger? Server less?
2019年9月15日 00:34 | # | 引用
谷雨 說:
阮大神可以講講react+dva-cli嗎,我最近在寫但是,看了官方文檔還是,不太懂
2019年9月16日 15:11 | # | 引用
李華泰 說:
剛剛試了,action權限秒開....突然萌生出一個想法,舍棄hexo,用react自己寫個。這樣我的博客主題我做主。哈哈哈哈哈哈哈。
2019年9月18日 17:46 | # | 引用
鄭明遠 說:
阮一峰老師,您有一個地方沒寫,就是要在 package.json 中加入 homepage 字段,否則github pages會找不到 js 和 css 文件。
2019年9月18日 22:34 | # | 引用
高行 說:
發現Fork之后不會運行,可以自己建個倉庫再把阮老師的代碼push上去,我運行的效果https://github.com/gaohanghang/github-actions-demo/actions
2019年9月19日 20:20 | # | 引用
阮一峰 說:
@鄭明遠:
謝謝指出,我確實忘了,已經補上。
2019年9月20日 00:35 | # | 引用
wisen 說:
請問這個怎么配置到github pages上呢?
2019年9月20日 08:26 | # | 引用
鴻強 說:
申請就通過
2019年9月20日 17:52 | # | 引用
Steven 說:
感謝阮大大分享。說的很詳細很清晰,立馬申請個action試試!
另外,提一點個人淺見。 文中提到的“秘密變量”,如果改成叫“私密變量” 會不會好理解一些? 出現地方有:
1:
```
上圖是儲存[秘密]的環境變量的地方。環境變量的名字可以隨便起,這里用的是ACCESS_TOKEN。
```
改成=》
```
上圖是存儲私密的環境變量的地方。…………
```
2:
```
第二步需要四個環境變量,分別為 GitHub 密鑰、發布分支、構建成果所在目錄、構建腳本。其中,只有 GitHub 密鑰是[秘密變量],需要寫在雙括號里面,其他三個都可以直接寫在文件里。
```
改成=>
```
…………其中,只有 GitHub 密鑰是私密變量,…………
```
個人淺見,說的不對的地方還請見諒。
2019年9月29日 11:20 | # | 引用
simon-woo 說:
有個問題:僅執行 npm install && npm run build 沒有運行 gh-pages -d build 為什么會自動生成 gh-pages 分支呢?(我的 https://[user.name].github.io 是新建的一個項目名字叫做 [user.name].github.io )
2019年10月 8日 16:36 | # | 引用
rackar 說:
感謝大佬。嘗試做一個基于vuepress的靜態博客,自己寫的action腳本老出問題,參考這個一次成功。
2019年10月16日 09:50 | # | 引用
rackar 說:
分支和推送分支包括一些目錄對應之類的處理都在引用的那個action腳本里JamesIves/[email protected]
2019年10月16日 09:52 | # | 引用
simon-woo 說:
如果是常規的開發流程,打包好Push到Github,自動發布到公司服務器,怎么建立Github與公司服務器的聯系?
2019年10月24日 20:05 | # | 引用
1221 說:
可以執行CI,但是怎么在gitpage查看到效果呢
2019年10月28日 11:14 | # | 引用
1221 說:
為什么CI執行action完成之后,gitpage要刷新好久才能出來
2019年10月28日 13:47 | # | 引用
GodzzZZZ 說:
我用這個插件 easingthemes/[email protected] 可以打包發到服務器
2019年11月 5日 13:49 | # | 引用
Echo 說:
老師您好,我想請問一下如果我之前使用hexo部署了我的博客,地址是我的[username].github.io,現在再使用action部署上去訪問就會404,我是應該把原先的博客也使用action的方式部署么?謝謝老師解惑
2019年11月14日 12:52 | # | 引用
trtrtr6 說:
我的情況看來和@Echo一樣,部署完也是404
2019年11月19日 14:45 | # | 引用
dev4mobile 說:
我用github action 搭建了自己的hexo blog https://dev4mobiles.com,
源碼在develop 分支上: https://github.com/dev4mobile/dev4mobile.github.io
2019年11月21日 15:03 | # | 引用
LOUSANPANG 說:
同樣的問題...
2019年12月 6日 16:01 | # | 引用