大數據

GitHub Actions,臥槽!牛批!

廣告
廣告

前段時間我更新了我的分布式爬蟲管理框架—— Gerapy

現在 DevOps 的理念可謂是相當火,其中 CI/CD(持續集成、持續部署)是必不可少的環節。有了它們,我們開發完軟件之后,一些測試、構建、部署的環節就可以自動化完成了。

我開發的的這款分布式爬蟲管理框架—— Gerapy,代碼也是放在了 GitHub 上面,但在之前 GitHub 上面是缺少原生的 CI/CD 功能支持的,可能需要根據第三工具或者 Webhook 等來配合實現項目的自動測試、構建和部署。

比如我可能有這么一些需求:

?每次合并代碼到 master 分支時,想測試這個項目能否在各個版本的 Python 環境下正常安裝和運行。

?我為 Gerapy 新建了一個獨立的 Repo,叫做 Gerapy/Gerapy,在?docs 文件夾下存放文檔說明,但我還另外新建了一個 Repo 專門用來存放文檔,叫做 Gerapy/Docs,希望能把 Gerapy/Gerapy 的 docs 子文件夾下的內容整個自動同步到 Gerapy/Docs 這個 Repo 的根目錄。

?每次 Gerapy 發布新版本的時候,自動構建 Docker 鏡像,并上傳到 Docker Hub,打上 latest 標簽和版本號標簽。

?每次 master 分支提交代碼的時候,自動構建 Docker 鏡像,并上傳到 Docker Hub,打上 master 標簽,代表當前 master 分支版本。

上面的功能之前有一部分工作是手工操作的,有一部分是借助于第三方工具來自動操作的,感覺并不是一個很好的解決方案

在最近一段時間,GitHub 上面上線了 Actions 功能,它就是為 CI/CD 而生的,和 GitHub 項目原生緊密結合。然而幾個月以來一直處于內測階段。就在 11 月 13 日,GitHub Actions 功能正式上線了。

上線之后,我就開始正式使用這個功能了,是真的香!

上面的四個需求,我用 GitHub Actions 已經完全實現了自動化,非常簡單方便。

接下來簡單介紹下我的一些實現方式。

GitHub Actions

首先簡單介紹下 GitHub Actions,其官方介紹頁面為:https://github.com/features/actions,介紹語如下:

Automate your workflow from idea to production. GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.

簡而言之就是提供了一個高效易用的 CI/CD 工作流,幫助我們自動構建、測試、部署我們的代碼。

GitHub Actions 的官方文檔可以見:https://help.github.com/en/actions/automating-your-workflow-with-github-actions,如果大家想好好研究下的話,一定要好好看看。

下面我就介紹我使用 GitHub Actions 實現上文所述的四個需求的方法。

自動測試

由于我開發的 Gerapy 是一個 Python Package,因此我看重的是測試它是否可以在各個 Python 平臺下安裝和正常使用,于是我新建了一個 GitHub Action,它會自動在項目目錄下生成一個 .github/workflows/*.yml 文件,內容如下:

name: build
on: 
  push:
    branches: 
    - master
    - dev
jobs:
  test:
    runs-on: 
    - ubuntu-latest
    strategy:
      max-parallel: 3
      matrix:
        python-version: [3.5, 3.6, 3.7]
    steps:
    - uses: actions/[email protected]
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/[email protected]
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Dependencies
      run: |
        python -m pip install --upgrade pip
        pip install .
    - name: Run Gerapy
      run: |
        gerapy -v
        gerapy init
        cd gerapy
        gerapy migrate
        gerapy initadmin

其實在這里一個 Action 就是一個 YAML 文件,其后綴為 yml,它規定了一系列語法規則,我們根據它的語法規則寫出一些工作流,在符合一定條件時,這些工作流會被觸發,自動執行。

比如這里最開頭,on 就是監聽某個事件,其內容為 push,意思就是當 push 代碼的時候,就會觸發。再進一步地,這里定義了兩個分支 master 和 dev。這什么意思呢?就是當我往 master 或者 dev 分支 push 代碼的時候,我們定義的工作流就會執行。

下面的 jobs 就是工作流的定義了,包括在什么平臺運行,具體執行什么步驟。

比如這里 runs-on 我就定義了在 ubuntu-latest 版本上運行,另外定義了一些并行策略和參數,比如這里就定義了 Python 的三個版本參數,在 3.5、3.6、3.7 版本上運行。

下面的 steps 就是具體執行哪些步驟了。第一步和第二步,我們可以看到它都有一個 uses 參數,內容都為 actions 開頭,這就說明我們使用了 GitHub 提供的寫好的 Action,我們只需要引用它的名字就能使用了。這兩步運行完畢之后,Python 環境會被初始化,同時會從 GitHub Clone Gerapy 項目代碼到本地。

在第三步和第四步,就是我自定義的 Task 了,這里自持直接寫入 Shell 腳本。在這里我分了兩步。

第三步 Install Dependencies 就是安裝 pip 和 Gerapy 安裝包,其中一句 pip install . 就是安裝當前 Gerapy 目錄下的內容到系統中,安裝完成之后,就可以使用 gerapy 命令了。

于是第四步 Run Gerapy 就是測試了 gerapy 命令的一些初始化使用,包括初始化工作環境、數據庫遷移、初始化賬號等等,當然還有更多,比如運行某些測試,運行服務等等,這里我只把一些必要的內容寫進去了。

好,基本內容就是這樣。

保存這個 Action,命名為 build.yml,它會保存為 .github/workflows/build.yml 文件。同時在保存的時候,我們就相當于執行了一次 Push 任務,這時候我們就可以看到這個 Action 已經啟動了,頁面如下:

我們所定義的每一個步驟以及對應的執行結果都會顯示在控制臺中,一目了然。

可以看到這里初始化了三個版本的 Python 環境,同時都運行了其中的測試流程。如果測試成功,會打綠色的勾,如果失敗,會提示紅色的叉,并有郵件提示。

這樣以來,一些自動化的測試就完成了!!!

同步文檔到新的 Repo

接下來我這個需求可以說稍微有點奇葩了。

寫項目免不了的要寫文檔,這里文檔我是用 Sphinx 來寫的,可以借助于 ReadTheDocs 自動構建并分發到 readthedocs.io 上面,類似這樣子:

但文檔的源代碼我是放在了 Gerapy/Gerapy 這個 Repo 的 docs 文件夾,向 Scrapy 看齊,是這樣子的:

但我想著還新建一個 Repo,來單獨存放文檔,比如我新建一個 Gerapy/Docs 這個 Repo,我在 Gerapy/Gerapy docs 子文件夾下的內容可以被自動同步到 Gerapy/Docs 根目錄下面,這樣我只需要往 Gerapy/Gerapy 上面提交代碼,docs 子文件夾下面的內容變了,Gerapy/Docs 下面的內容也會跟著變。

那這個能不能做到呢?能!(我問你答,快樂神仙;自問自答,法力無邊~~

這個流程可以分為四步:

?下載 Gerapy/Gerapy Repo 的源代碼。?利用 git 的 subtree 命令將 docs 文件夾下的內容分離到新的分支。?將新分離的分支推送到 Docs 這個 Repo 下面。?推送 Docs 這個 Repo 到遠程 Gerapy/Docs Repo。

這里面就有一個關鍵地方,那就是怎樣無需密碼將內容推送到遠程 Gerapy/Docs 這個 Repo 下面,當然就是 SSH 了。(啊,超爽der)

那 SSH 的話應該怎么設置呢?我們首先要有一對公鑰和私鑰,這個我們用 ssh-keygen 命令自己生成就好了。

那接下來 Gerapy/Docs 里面需要存有公鑰,怎么辦呢?我們可以借助于 GitHub 提供的 Deploy Key 配置好公鑰即可:

嗯,做好這兩部分工作之后,接下來完善一下 yml 文件就好了,內容如下:

name: sync docs
on: 
  push:
    branches: 
    - master
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
    - name: Set SSH Environment
      env:
        DOCS_DEPLOY_KEY: ${{ secrets.DOCS_DEPLOY_KEY }}
      run: |
        mkdir -p ~/.ssh/
        echo "$DOCS_DEPLOY_KEY" > ~/.ssh/id_rsa
        chmod 600 ~/.ssh/id_rsa
        ssh-keyscan github.com > ~/.ssh/known_hosts
        chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
        git config --global user.email "[email protected]"
        git config --global user.name "Germey"
    - name: Sync Docs of Gerapy
      run: |
        cd /tmp
        git clone [email protected]:Gerapy/Docs.git docs
        cd docs
        git branch -D docs || true
        git push origin --delete docs || true
        git clone https://github.com/Gerapy/Gerapy.git gerapy
        cd gerapy
        git subtree split --prefix=docs --squash -b docs
        git checkout docs
        git push /tmp/docs docs:docs
        cd /tmp/docs
        git checkout docs
        git checkout -b master || git checkout master || true
        git reset --hard docs
        git push origin master --force

可以看到,這里主要就分了兩步。

第一部分就是設置虛擬機的 SSH 環境,這里 secrets.DOCS_DEPLOY_KEY 就是我們剛才在 Secrets 里面定義的私鑰,對應的運行命令就是將私鑰添加到 ~/.ssh/id_rsa 里面。

第二部分就是分離 docs 文件夾到新的分支,然后將其上傳到新的 Repo 下了。

那么這里有兩條比較關鍵的命令:

git subtree split --prefix=docs --squash -b docs

這條命令就是將 docs 文件夾的內容分離到一個新的分支的根目錄下,新的分支的名稱為 docs。

git push /tmp/docs docs:docs

這條命令就是將本地的分支推送到另外一個本地 Repo 下,注意這里 push 的目標不一定是遠端的 Repo 地址,也可以是本地的 Repo 地址。

最后,將新的 Repo 內容強制推送到遠程即可。

這樣我們就可以實現,Gerapy/Gerapy Repo docs 文件夾下內容的變動,會自動更新到 Gerapy/Docs Repo 了。

例如 docs 下是這樣的:

Gerapy/Docs Repo 下和子文件的內容會一直維持同步,并在 master 分支上面:

自動構建 Docker 鏡像

由于 Gerapy 是一個 Web 工程,所以它非常適合于打包一個 Docker 鏡像。對于 Docker 的鏡像,我期望有三個版本:

?當前 master 分支的版本,比較穩定,但未發布版本。?最新版本,latest,代表最新的發布版本。?每個歷史版本,每次發布版本的版本號,都標記一個 tag。

最后我們自動構建的鏡像都自動 Push 到 Docker Hub 上面,這樣大家都可以使用了。

那這個怎么做到呢,同樣借助于 GitHub Action 也可以輕松做到。

首先 master 版本,由于沒有發版,所以前端需要自行 build,然后 Python Package 需要安裝本地代碼。廢話不多說了,上代碼:

name: build docker image master
on:
  push:
    branches: 
    - master
    paths:
    - .github/workflows/**
    - gerapy/**
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout Source
      uses: actions/[email protected]
    - name: Docker Login
      run: docker login -u germey -p ${{ secrets.DOCKERHUB_LOGIN_PASSWORD }}
    - name: Setup Node.js
      uses: actions/[email protected]
      with:
        version: 10.x
    - name: Build Frontend Source
      run: |
        cd gerapy/client
        npm install
        npm run build
    - name: Build the Docker Image
      run: |
        docker build -t germey/gerapy:master -f ./docker/Dockerfile .
    - name: Push the Docker Image
      run: docker push germey/gerapy:master

可以看到這里,監聽了 master 分支的變動,同時限定了路徑 workflows 文件夾和 gerapy 文件夾下變動。

流程包括了前端的構建和 Docker 的打包,Docker 打包的時候使用了 -f 命令指定了 Dockerfile 的路徑,并將打包完成之后的鏡像標記為 gerapy:master,推送到 Docker Hub 即可。

對于發布新版本的時候,則直接監聽 tag 的變動即可:

name: build docker image release
on:
  push:
    tags:
      - 'v*.*.*'
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout Source
      uses: actions/[email protected]
    - name: Docker Login
      run: docker login -u germey -p ${{ secrets.DOCKERHUB_LOGIN_PASSWORD }}
    - name: Setup Node.js
      uses: actions/[email protected]
      with:
        version: 10.x
    - name: Build Frontend Source
      run: |
        cd gerapy/client
        npm install
        npm run build
    - name: Build and Push the Docker Image
      run: |
        tag=${GITHUB_REF:11}
        echo "Build Tag '$tag'"
        docker build -t germey/gerapy:$tag -f ./docker/Dockerfile .
        docker push germey/gerapy:$tag
        regex='^([0-9]+\.){0,2}(\*|[0-9]+)$'
        if [[ $tag =~ $regex ]]; then
          echo "Build Stable Version '$tag'"
          docker tag germey/gerapy:$tag germey/gerapy:latest
          docker push germey/gerapy:latest
        fi

可以看到這里監聽的配置改成了 tags,tag 也變成了一個變量,可以通過 ${GITHUB_REF:11} 獲取到。

同時這里還加了一個正則判斷是不是正式的發版,如果是 beta、rc 版本,則不構建正式 latest 的 Docker 鏡像。

最后我們看看我再一次發版之后,構建完成之后,Docker Hub 的效果:

可以看到,我發布了 0.9.2 版本之后,它就自動構建了 0.9.2 版本的鏡像,同時將 latest 鏡像指向 0.9.2 版本。另外對應 maser 版本也構建了一個版本。

這樣,以后媽媽再也不用擔心我忘記打 Docker 鏡像啦。

以上便是我將 GitHub Actions 應用到我的開源項目上的記錄。

最后,如果大家對 Scrapy 爬蟲感興趣的話,也(非常)歡迎大家(高高興興的)了解一下我寫的 Gerapy 框架,利用它我們可以(無敵)更方便地管理(呀)、監控(呀)、(或者是)部署 Scrapy 爬蟲項目(什么的)。

其 GitHub 地址為:https://github.com/Gerapy/Gerapy,文檔:https://docs.gerapy.com/。

掰掰!

我還沒有學會寫個人說明!

區塊鏈如何改變當今的業務安全

上一篇

Stack Overflow上188萬瀏覽量的提問:Java 到底是值傳遞還是引用傳遞?

下一篇

你也可能喜歡

GitHub Actions,臥槽!牛批!

長按儲存圖像,分享給朋友

ITPUB 每周精要將以郵件的形式發放至您的郵箱


微信掃一掃

微信掃一掃
双色球常规走势图 盈策配资 雷速体育号如何发送收费比赛 欧洲杯2012即时赔率 黑龙江36选7 金配资 华体网即时赔率体网即时赔率 福建36选7 景天鑫配资 球探即时篮球nba比分 3d开机号 配资利息一般是多少 即时比分500