最近公司內部項目的發佈流程接入了 GitHub Actions
,整個體驗過程仍是比較美好的;本文主要目的是對於沒有還接觸過 GitHub Actions
的新手,可以利用它快速構建自動測試及打包推送 Docker
鏡像等自動化流程。git
本文主要以 Go
語言爲例,固然其餘語言也是相似的,與語言自己關係不大。github
這裏咱們首先在 GitHub
上建立一個項目,編寫了幾段簡單的代碼 main.go
:golang
var version = "0.0.1"
func GetVersion() string {
return version
}
func main() {
fmt.Println(GetVersion())
}
複製代碼
內容很是簡單,只是打印了了版本號;同時配套了一個單元測試 main_test.go
:docker
func TestGetVersion1(t *testing.T) {
tests := []struct {
name string
want string
}{
{name: "test1", want: "0.0.1"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetVersion(); got != tt.want {
t.Errorf("GetVersion() = %v, want %v", got, tt.want)
}
})
}
}
複製代碼
咱們能夠執行 go test
運行該單元測試。ubuntu
$ go test
PASS
ok github.com/crossoverJie/go-docker 1.729s
複製代碼
固然以上流程徹底能夠利用 Actions
自動化搞定。bash
首選咱們須要在項目根路徑建立一個 .github/workflows/*.yml
的配置文件,新增以下內容:服務器
name: go-docker
on: push
jobs:
test:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags')
steps:
- uses: actions/checkout@v2
- name: Run Unit Tests
run: go test
複製代碼
簡單解釋下:markdown
name
沒必要多說,是爲當前工做流建立一個名詞。on
指在什麼事件下觸發,這裏指代碼發生 push
時觸發,更多事件定義能夠參考官方文檔:Events that trigger workflowsapp
jobs
則是定義任務,這裏只有一個名爲 test
的任務。該任務是運行在 ubuntu-latest
的環境下,只有在 main
分支有推送或是有 tag
推送時運行。ssh
運行時會使用 actions/checkout@v2
這個由他人封裝好的 Action
,固然這裏使用的是由官方提供的拉取代碼 Action
。
Action
來簡化流程,這點也是 GitHub Action
擴展性很是強的地方。最後的 run
則是運行本身命令,這裏天然就是觸發單元測試了。
mvn test
.以後一旦咱們在 main
分支上推送代碼,或者有其餘分支的代碼合併過來時都會自動運行單元測試,很是方便。
與咱們本地運行效果一致。
接下來考慮自動打包 Docker
鏡像,同時上傳到 Docker Hub
;爲此首先建立 Dockerfile
:
FROM golang:1.15 AS builder
ARG VERSION=0.0.10
WORKDIR /go/src/app
COPY main.go .
RUN go build -o main -ldflags="-X 'main.version=${VERSION}'" main.go
FROM debian:stable-slim
COPY --from=builder /go/src/app/main /go/bin/main
ENV PATH="/go/bin:${PATH}"
CMD ["main"]
複製代碼
這裏利用 ldflags
可在編譯期間將一些參數傳遞進打包程序中,好比打包時間、go 版本、git 版本等。
這裏只是將 VERSION
傳入了 main.version
變量中,這樣在運行時就便能取到了。
docker build -t go-docker:last .
docker run --rm go-docker:0.0.10
0.0.10
複製代碼
接着繼續編寫 docker.yml
新增自動打包 Docker
以及推送到 docker hub
中。
deploy:
runs-on: ubuntu-latest
needs: test
if: startsWith(github.ref, 'refs/tags')
steps:
- name: Extract Version
id: version_step
run: | echo "##[set-output name=version;]VERSION=${GITHUB_REF#$"refs/tags/v"}" echo "##[set-output name=version_tag;]$GITHUB_REPOSITORY:${GITHUB_REF#$"refs/tags/v"}" echo "##[set-output name=latest_tag;]$GITHUB_REPOSITORY:latest"
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USER_NAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: PrepareReg Names
id: read-docker-image-identifiers
run: | echo VERSION_TAG=$(echo ${{ steps.version_step.outputs.version_tag }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV echo LASTEST_TAG=$(echo ${{ steps.version_step.outputs.latest_tag }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Build and push Docker images
id: docker_build
uses: docker/build-push-action@v2.3.0
with:
push: true
tags: | ${{env.VERSION_TAG}} ${{env.LASTEST_TAG}} build-args: | ${{steps.version_step.outputs.version}} 複製代碼
新增了一個 deploy
的 job。
needs: test
if: startsWith(github.ref, 'refs/tags')
複製代碼
運行的條件是上一步的單測流程跑通,同時有新的 tag
生成時纔會觸發後續的 steps
。
name: Login to DockerHub
在這一步中咱們須要登陸到 DockerHub
,因此首先須要在 GitHub 項目中配置 hub 的 user_name
以及 access_token
.
配置好後便能在 action 中使用該變量了。
這裏使用的是由 docker 官方提供的登陸 action(docker/login-action
)。
有一點要很是注意,咱們須要將鏡像名稱改成小寫,否則會上傳失敗,好比個人名稱中 J
字母是大寫的,直接上傳時就會報錯。
因此在上傳以前先要執行該步驟轉換爲小寫。
最後再用這兩個變量上傳到 Docker Hub。
從此只要咱們打上 tag
時,Action
就會自動執行單測、構建、上傳的流程。
GitHub Actions
很是靈活,你所須要的大部分功能都能在 marketplace
找到現成的直接使用,
好比能夠利用 ssh
登陸本身的服務器,執行一些命令或腳本,這樣想象空間就很大了。
使用起來就像是搭積木同樣,能夠很靈活的完成本身的需求。
參考連接:
How to Build a CI/CD Pipeline with Go, GitHub Actions and Docker