1. 程式人生 > >為Github倉庫新增Github Actions實現持續整合: Android apk自動編譯釋出以及github pages同步推送coding.net

為Github倉庫新增Github Actions實現持續整合: Android apk自動編譯釋出以及github pages同步推送coding.net

> 內容轉載自[我的部落格](https://blog.whuzfb.cn/blog/2020/08/09/github_actions/) [TOC] ## 說明 對於普通的github倉庫,只需要在根目錄建立`.github/workflows/`資料夾即可自動使用Actions功能,具體執行的操作可以建立一個配置檔案(命名不限),如`build_apk.yml` [Github Actions產品](https://docs.github.com/cn/actions/getting-started-with-github-actions)對公開倉庫是完全免費的,對私人倉庫每月有2000分鐘使用時間,詳細說明見[費用](https://docs.github.com/cn/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions)。另外,github有許多官方[已經實現好的actions](https://github.com/actions/)可以供使用者直接呼叫,使用者只需用設定引數即可 每個配置檔案稱為一個工作流程(workflow),每個工作流程可以包含多個作業(job),每個作業可以包含一系列的步驟(steps),每個step可以稱為action,可以認為這是三個層級 * workflow的[基本語法](https://docs.github.com/cn/actions/reference/workflow-syntax-for-github-actions) * workflow語法的[基本資料型別、函式和內建變數](https://docs.github.com/cn/actions/reference/context-and-expression-syntax-for-github-actions) * workflow支援的所有[觸發條件](https://docs.github.com/cn/actions/reference/events-that-trigger-workflows),過濾[指定的觸發條件](https://docs.github.com/cn/actions/configuring-and-managing-workflows/configuring-a-workflow#manually-running-a-workflow) * 在workflow及以下層級[使用GITHUB_TOKEN祕鑰](https://docs.github.com/cn/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)的方法(內建,無需設定,直接呼叫) * 在workflow及以下層級[使用其他祕鑰](https://docs.github.com/cn/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets)的方法 * 在workflow的[多個job之間傳遞資料](https://docs.github.com/cn/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts)的方法 * job及其以下層級的[條件執行](https://docs.github.com/cn/actions/reference/workflow-syntax-for-github-actions#%E4%BD%BF%E7%94%A8%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84%E7%A4%BA%E4%BE%8B) * 在job的不同step之間傳遞資料的方法 * 在job的某個step裡面[使用Docker](https://docs.github.com/cn/actions/creating-actions/creating-a-docker-container-action)的方法 * 在job裡面[使用cache](https://docs.github.com/cn/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)來加快每次構建速度 * 為job下面的所有步驟的run命令[設定預設shell和工作目錄](https://docs.github.com/cn/actions/reference/workflow-syntax-for-github-actions#defaultsrun) ## 1. 編寫Android專案的CI配置檔案 這裡以專案[WhuHelper](https://github.com/zfb132/WhuHelper)為例,介紹如何使用YAML語法和Github Actions功能 * 原始倉庫的檔案版本為[c1a78da](https://github.com/zfb132/WhuHelper/tree/c1a78da55e34b064907a957ce5c20cad8b999e42) * 新增CI功能(自動進行`build test`、`build app-debug.apk`)以後的檔案版本為[4ef2e90](https://github.com/zfb132/WhuHelper/tree/4ef2e900c40c569a47f872ee42c138a3c8ad925d),只需要關注檔案[build_apk.yml](https://github.com/zfb132/WhuHelper/blob/4ef2e900c40c569a47f872ee42c138a3c8ad925d/.github/workflows/build_apk.yml)即可,其他檔案無變化 * 最終的CI功能包括自動進行構建測試、構建`app-debug.apk`、建立倉庫的release(只包括程式碼,且只在`push tag`時觸發)、為此次release新增apk檔案,檔案版本為[20fe364](https://github.com/zfb132/WhuHelper/tree/20fe36406e5d9c9114dadc2947d789b793e93f27),只需要關注檔案[build_apk.yml](https://github.com/zfb132/WhuHelper/blob/20fe36406e5d9c9114dadc2947d789b793e93f27/.github/workflows/build_apk.yml)即可,其他檔案無變化 主要涉及到的操作為:設定workflow及以下層級的每個操作名字、設定workflow的觸發條件、建立多個job、job的條件執行、呼叫別人寫好的actions、自己為某個step設定輸出引數供其他步驟呼叫、持久化build的結果、上傳build的結果供使用者下載、下載build的結果供下一步操作使用、多個job之間傳遞資料、多個step之間傳遞資料、使用環境變數 例項`build_apk.yml`檔案內容及解析如下: ```yaml name: Auto build debug apk # 設定workflow的觸發條件 # 在pull和push到主分支時觸發workflow # 在push tags時觸發workflow on: pull_request: branches: - 'master' push: branches: - 'master' # 在push tag時觸發 tags: - '*' # workflow的所有作業job jobs: # 單個job的名字:測試Android專案 # 每個job執行完畢會預設刪除所有檔案等 # 可通過cache來保留特定資料夾和檔案 # 也可使用upload-artifact上傳來實現保留檔案,再配合download-artifact實現多job之間的資料傳遞 test: # test這個作業的實際名字 # 也是執行build時Actions監控處顯示的名字 name: Run Unit Tests # job的執行平臺,還有windows、macos及不同版本可供選擇 runs-on: ubuntu-18.04 # test任務的具體步驟,可以有很多個步驟,都寫在這裡 steps: # 使用別人寫好的指定版本的actions指令碼,名稱是checkout # 這是步驟1,即每個'-'符號到下一個'-'符號之間的部分是一個步驟 - uses: actions/checkout@v2 # 這是步驟2,建立java環境,with裡面填寫actions的輸入引數 - name: set up JDK 1.8 uses: actions/setup-java@v1 # 設定setup-java指令碼的輸入引數 with: java-version: 1.8 # 步驟3,執行shell命令 - name: Unit tests run: bash ./gradlew test --stacktrace apk: name: Generate APK runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 - name: set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - name: Build debug APK run: bash ./gradlew assembleDebug --stacktrace # 利用upload-artifact實現build結果的儲存(可以在Actions的控制檯下載壓縮檔案) - name: Upload APK uses: actions/upload-artifact@v2 with: # 設定壓縮檔案的名稱,在控制檯會得到WhuHelper-debug.zip檔案的下載連結 # 下載後解壓縮,裡面直接可以看到app-debug.apk,沒有其他東西 name: WhuHelper-debug path: app/build/outputs/apk/debug/app-debug.apk deploy: name: Upload Release Asset # 依賴上一個job needs: apk runs-on: ubuntu-latest # 只在tag時執行,即在自己終端執行以下程式碼後才會觸發 # git tag -a v0.1.0 -m "release 0.1.0 version" # git push origin –-tags if: contains(github.ref, 'tags/') steps: # 自己編寫的shell命令 # 學習如何設定單個任務的輸出來被其他任務呼叫 - name: Prepare Release # 設定id一般是為了其他step呼叫本步驟的輸出 id: prepare_release run: | TAG_NAME=`echo $GITHUB_REF | cut -d / -f3` echo ::set-output name=tag_name::$TAG_NAME - name: Download build result for job apk # 只有上一步獲取到tag_name才繼續,下載前面apk任務裡面的WhuHelper-debug.zip檔案 # 自動解壓縮到當前資料夾,自動刪除原壓縮檔案 # 多工之間的資料交換 if: steps.prepare_release.outputs.tag_name uses: actions/download-artifact@v2 with: name: WhuHelper-debug - shell: bash # 手動更改apk名字 run: | mv app-debug.apk app-debug-${{steps.prepare_release.outputs.tag_name}}.apk # 釋出release,版本號是使用者git push的tag裡面的版本號,釋出的只有程式碼壓縮包(與手動預設釋出一致) - name: Create Release id: create_release # 只有上一步獲取到tag_name才繼續 if: steps.prepare_release.outputs.tag_name uses: actions/create-release@v1 env: # GitHub 會自動建立 GITHUB_TOKEN 密碼以在工作流程中使用 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 設定時區,預設是格林尼治時間 # TZ: Asia/Shanghai with: tag_name: ${{steps.prepare_release.outputs.tag_name}} release_name: Release ${{steps.prepare_release.outputs.tag_name}} by zfb draft: false prerelease: false # 這一步是對上一步釋出的release檔案的補充,呼叫github api上傳一個apk檔案 - name: Upload Release Asset id: upload-release-asset # 只有create_release成功得到輸出才繼續 if: steps.create_release.outputs.upload_url uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./app-debug-${{steps.prepare_release.outputs.tag_name}}.apk asset_name: app-debug-${{steps.prepare_release.outputs.tag_name}}.apk asset_content_type: application/vnd.android.package-archive ``` ## 2. 編寫Jekyll專案的CI配置檔案 ### 2.1 配置`coding.net` 主要包括以下步驟: * 首先新建一個空專案(如果已經有了的話就不需要再新建,但是要保證與Github的對應倉庫版本一致,防止無法commit) * coding.net的程式碼倉庫新建`訪問令牌`,授予倉庫許可權,假設名字為`GITHUB_AUTO_DEPLOY`,複製顯示的token備用 * 在該程式碼倉庫,找到`設定-->倉庫設定`,即可看到[設定本倉庫地址](https://zfbin.coding.net/p/zfbin/d/zfbin/git/settings/depot)的方法,本例子顯示為(格式為`https://e.coding.net/團隊名/專案名/倉庫名.git`) `git remote set-url origin https://e.coding.net/zfbin/zfbin/zfbin.git` 使用token來讀寫遠端倉庫(格式為`https://使用者名稱:[email protected]/團隊名/專案名/倉庫名.git`),使用如下命令自己測試一下,使用者名稱(預設是手機號碼)為`13677888877`,上一步得到的token是`cdd0b865cdd0b865cdd0b865cdd0b865cf87ce84`,團隊名稱是`zfbin`,專案的名稱是`zfbin`,程式碼倉庫的名稱是`zfbin`(這裡所有配置的敏感資訊都是示例): ```text ~/work/github/zfbin > git push "https://13677888877:[email protected]/zfbin/zfbin/zfbin.git" master:master Everything up-to-date ~/work/github/zfbin > ``` ### 2.2 配置`github` 開啟Github的[此倉庫的Secrets](https://github.com/zfb132/zfb132.github.com/settings/secrets)選項,新建以下祕鑰: ```text DEPLOY_CODING cdd0b865cdd0b865cdd0b865cdd0b865cf87ce84 CODING_USERNAME 13677888877 CODING_REF e.coding.net/zfbin/zfbin/zfbin.git ``` ### 2.3 自動部署到`coding.net` github的倉庫的原始檔案版本為[8570167](https://github.com/zfb132/zfb132.github.com/tree/857016713b4b3a191c5c5f86d213c6512c24137a),最終新增github actions之後的檔案版本為[0462a89e](https://github.com/zfb132/zfb132.github.com/tree/0462a89e81a1f05f59b03fa989cb3d3bfd26c351),不需要關注其他檔案,只考慮`.github/workflows/deploy_to_coding.yml`檔案,其內容如下: ```yaml name: Auto deploy to coding pages # 在push主分支時觸發構建 on: push: branches: - 'master' jobs: # job的名字:推送到coding deploy: name: Deploy to Coding # job的執行平臺 runs-on: ubuntu-18.04 # test任務的步驟 steps: # 使用別人寫好的指定版本的actions指令碼,名稱是checkout,下載本倉庫 - uses: actions/checkout@v2 - name: 設定提交者的個人資訊 # 這三個變數的值都放在 https://github.com/zfb132/zfb132.github.com/settings/secrets env: # 設定時區 TZ: Asia/Shanghai # 在coding.net的某個倉庫新建訪問令牌出現的祕鑰 coding_token: ${{ secrets.DEPLOY_CODING }} # 團隊中的某個人的使用者名稱,一般預設是本人手機號碼 coding_username: ${{ secrets.CODING_USERNAME }} # 格式為:e.coding.net/組織名/專案名/倉庫名.git coding_ref: ${{ secrets.CODING_REF }} run: | export message=$(git log --pretty=format:"%s" -1) [ -f CNAME ] && rm CNAME || echo "CNAME doesn't exist" rm -rf .github rm -rf .git git clone https://${coding_username}:${coding_token}@${coding_ref} coding_dir cd coding_dir && mv .git ../ && cd ../ && rm -rf coding_dir git config --local user.email "[email protected]" git config --local user.name "zfb" git config core.filemode false git remote set-url origin https://${coding_ref} git add . git commit -m "$message" git push --force --quiet "https://${coding_username}:${coding_token}@${coding_ref}" master:master ``` 具體執行的命令的解釋: * `export message=$(git log --pretty=format:"%s" -1)`是獲取github的提交的message * `rm CNAME`是刪除github倉庫的`CNAME`檔案,因為coding.net不需要此檔案 * `rm -rf .github`是刪除github actions的配置檔案,因為coding.net不需要進行CI * `rm -rf .git`是刪除github倉庫時的git資訊,為後面使用coding.net的git清理空間 * `git clone https://${coding_username}:${coding_token}@${coding_ref} coding_dir`是克隆coding.net的對應倉庫,主要為了`.git`資料夾,所以只是把此倉庫下載到一個臨時資料夾`coding_dir` * `cd coding_dir && mv .git ../ && cd ../ && rm -rf coding_dir`是把coding.net的`.git`資料夾替換掉原來的,並且刪除臨時資料夾 * `git config --local user.email "[email protected]"`是設定提交者的電子郵箱地址 * `git config --local user.name "zfb"`是設定提交者的名字 * `git config core.filemode false`忽略檔案屬性的問題,因為github的檔案模式(許可權)不一定與coding.net的相同 * `git remote set-url origin https://${coding_ref}`是設定遠端倉庫的地址為coding.net的倉庫 * `git add .`是新增檔案到暫存區 * `git commit -m "$message"`設定commit的資訊與github一致 * `git push --force --quiet "https://${coding_username}:${coding_token}@${coding_ref}" master:master`是強制推送到遠