<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          利用 Github Action 實現(xiàn)博客自動發(fā)版

          共 10741字,需瀏覽 22分鐘

           ·

          2022-07-27 15:40

          背景

          先說下背景需求,在摸魚周報的整理流程中,最后一步需要生成公眾號的原文鏈接,原文鏈接指向的是個人博客地址。博客需要發(fā)布才能產(chǎn)生外部鏈接,發(fā)布到不費事,但是操作步驟重復,且因為涉及博客推送相關(guān)的配置都在我的個人電腦里,所有步驟必須由我來完成。來回多次之后就考慮將這個流程做成自動化了,目標是讓周報協(xié)作者都可以實現(xiàn)博客推送,用到的實現(xiàn)方式是 Github Action。

          實現(xiàn)思路

          在開始之前先了解下原先的發(fā)布流程,如下圖表示:

          整個過程涉及 3 個倉庫:

          • Moyu Repo。管理周報文章的公共倉庫,協(xié)作者可以通過它拉取和推送內(nèi)容。

          • Blog Repo。管理博客內(nèi)容的私有倉庫,周報只是其中一部分。

          • Blog Website。博客的網(wǎng)站,它部署在一臺騰訊云服務器上,它也是私有的。

          因為涉及兩個私有倉庫,普通協(xié)作者都沒有他們的訪問權(quán)限,所以發(fā)布流程都依賴我來完成。解決方案就是消除發(fā)布流程對權(quán)限的依賴,理想流程是這樣的:

          這樣觸發(fā)入口就都集中在了共有倉庫,協(xié)作者也可以參與博客發(fā)布。要實現(xiàn)這個流程需要將需求分為兩步:

          1、Moyu Repo 通過 Github Action 推送 Moyu 內(nèi)容到 Blog Repo。

          2、Blog Repo 通過 Github Action 發(fā)布內(nèi)容到網(wǎng)站。

          這其中最關(guān)鍵的是訪問私有倉庫時如何處理權(quán)限的問題。

          Github Action

          這里先簡單了解下 Github Action。它是 Github 提供的為倉庫定義自動化流程的方案,類似 Jenkins、GitLab CI/CD。Github Action 有一套自己的流水線配置方式,所有的流程都可以通過一個 yml 文件下發(fā)。Gtihub Action 有自己的虛擬機,支持 Windows Server/Linux/Mac,使用者無需關(guān)心環(huán)境配置問題,可以直接使用。

          配置入口如下圖所示:

          點擊set up a workflow yourself,即創(chuàng)建了一個用于編排自動化任務的 workflow,它對應一個 yml 文件,所有的配置流程都在這里進行。

          自動化任務配置前我們需要先考慮這幾個問題:什么時機觸發(fā)?在什么設(shè)備運行?如何執(zhí)行自動化任務?我們看一個簡單的例子來學習下 Github Action 如何定義這些行為:

          name: GitHub Actions Demo
          on: [push]
          jobs:
            Explore-GitHub-Actions:
              runs-on: ubuntu-latest
              steps:
                - run: echo "?? The job was automatically triggered by a ${{ github.event_name }} event."
                - name: Check out repository code
                  uses: actions/checkout@v3

          name 表示當前流水線的名字。

          什么時機觸發(fā)

          在什么場景觸發(fā),對應的key 是 on。上面Demo里的[push],表示倉庫發(fā)生push行為時觸發(fā)任務。on 還有其他幾種觸發(fā)途徑:

          • pull_request:提交 PR 時觸發(fā)
          • schedule:定時觸發(fā),可以按 cron 語法配置定頻
          • workflow_dispatch:手動觸發(fā),有用戶手動激活觸發(fā)行為

          在什么設(shè)備運行

          對應的關(guān)鍵詞是runs-on,Demo里指定值為ubuntu-latest,表示執(zhí)行設(shè)備是一個 ubuntu 設(shè)備。Github Action 還支持 macOS 環(huán)境,目前有三個 macOS 版本可以支持:

          虛擬環(huán)境YAML標簽
          macOS Monterey 12macos-12
          macOS Big Sur 11macos-latestmacos-11
          macOS Catalina 10.15macos-10.15

          需要注意:macos-latest 不是最新的 macos 版本,而是 macOS 11。iOS 開發(fā)中我們可能還會關(guān)心 Xcode 版本,Ruby 版本等。以 macOS 12 虛擬機為例,Xcode 版本:

          VersionBuildPath
          13.4.1 (default)13F100/Applications/Xcode_13.4.1.app
          13.413F17a/Applications/Xcode_13.4.app
          13.3.113E500a/Applications/Xcode_13.3.1.app
          13.2.113C100/Applications/Xcode_13.2.1.app
          13.113A1030d/Applications/Xcode_13.1.app

          Ruby版本:2.7.6/3.0.4/3.1.2。

          其他預制環(huán)境可以參考這篇文檔:macos-12-Readme[1]。

          另外 Github Action 還支持將自己的設(shè)備定義為運行機,你可以在這里了解:About self-hosted runners[2];支持聯(lián)機調(diào)試,可以通過這個插件了解:A debugger for actions[3]。

          如何執(zhí)行自動化任務

          有兩種執(zhí)行任務的方式,一種是直接在 yml 文件里編輯腳本,關(guān)鍵詞是run。像是 Demo 里的 echo 命令,我們可以直接輸入 shell 命令進行執(zhí)行。

          另一種方式是插件市場,像下面這種形式:

          - name: Check out repository code
            uses: actions/checkout@v3

          就是使用了 actions/checkout@v3 這個插件。Github 有一個插件市場,可以搜索所需插件。像是 Code review,SSH 登錄等都有封裝好的插件可以直接使用。

          實現(xiàn)方案

          有了這些 Github Action 知識,我們就可以開始實現(xiàn)我們的需求了。最終效果分成兩個需求。

          Moyu Repo 向 Blog Repo 推送內(nèi)容

          我們按照前面的三個問題來設(shè)計這個功能。

          什么時機觸發(fā)?

          發(fā)布之前需要經(jīng)過多次修改,會有多個 PR 和 Push 行為,而 Blog 發(fā)布需要等所有內(nèi)容都準備完成才會執(zhí)行,一般只有一次。所以考慮使用手動發(fā)布的方式,以下是配置內(nèi)容:

          # Action name
          name: Weekly Article Deploy
          # Controls when the workflow will run
          on:
            # Allows you to run this workflow manually from the Actions tab
            workflow_dispatch:
              inputs:
                weekly_index:
                  description: 'weekly index for deploy'  

          手動發(fā)布還補充了一個 inputs,用于接收輸出參數(shù),weekly_index為參數(shù)名,用于表示要發(fā)布第幾期。執(zhí)行效果如下所示:

          在什么設(shè)備運行?

          這個需要根據(jù)執(zhí)行任務來定,這里只涉及一些文本轉(zhuǎn)換和倉庫操作,所以任意機器都滿足需求,ubuntu 資源比較多,調(diào)度會快那么一點點,所以都可的情況優(yōu)先選 ubuntu。

          # A workflow run is made up of one or more jobs that can run sequentially or in parallel
          jobs:
            # This workflow contains a single job called "build"
            build:
              # The type of runner that the job will run on
              runs-on: ubuntu-latest

          Github Action 里有幾個名詞:workflow,job,steps,這里簡單捋一下。整個 Yml 文件對應為一個 workflow,它表示一次完整的自動化任務運行過程。當前倉庫的整個配置都是一個 workflow。

          一個 workflow 可以包含一個或多個 job,這里的 jobs 下面一級內(nèi)容就是各個 job。不同 job 之間可以串行也可以并行。build為會其中一個 job,也是本 workflow 唯一的 job。

          如何執(zhí)行自動化任務?

          這個流程需要做的事情是把 Moyu Repo 內(nèi)容轉(zhuǎn)成 Blog Repo 的格式,然后推送到 Blog Repo 里。前一步可以封裝成一個腳本,后一步往私有倉庫推送需要生成一個具有推送私有倉庫權(quán)限的 token。

          token 的生成需要到這里:個人頭像 -> Settings -> Developer settings -> Personal access tokens,點擊 Generate new token。這一步需要輸入密碼,然后我們可以選擇所需權(quán)限去生成一個token。對于私有倉庫的推送,我們選中這一個權(quán)限就可以了:

          為了安全考慮,這個token生成之后只會可見一次,因為后面的步驟會使用,所以我們需要做好保存。

          注意這個 token 是用戶級別的,它可以用于訪問修改該賬戶名下的任意倉庫。

          為了讓 Github Action 可以訪問到這個token,需要給它做一個配置。配置路徑是:在該倉庫下的 Settings(注意這個是倉庫下的設(shè)置而非個人下的設(shè)置) -> Secrets -> Actions 點擊 New repository secret。

          Name 的話可以命名為 ACCESS_TOKEN,Value 為上一步生成的訪問 token。這里配置的任意內(nèi)容都可以通過Github Action 訪問到,且是加密的,創(chuàng)建之后只能看到 Name 看不到 Value。

          下面是具體配置:

          env:
            ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}

          # Steps represent a sequence of tasks that will be executed as part of the job
          steps:
            - name: print inputs
              run: |
                echo "Weekly Index: ${{ github.event.inputs.weekly_index }}"

            - name: Git Config
              run: |
                git config --global user.email [email protected]
                git config --global user.name moyuweekly
            # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
            - uses: actions/checkout@v3

            # Runs a single command using the runners shell
            - name: Run a one-line script
              run: ./Script/ci_run.sh ${{ github.event.inputs.weekly_index }}
              shell: bash

          secrets.ACCESS_TOKEN 表示的是該倉庫下面 secrets 里 name 為 ACCESS_TOKEN 的內(nèi)容。${{}}為 action 語法獲取變量的寫法。

          因為我把對私有倉庫的獲取和推送都放到了執(zhí)行腳本里,所以這里通過環(huán)境變量的形式把這個值傳給腳本。

          steps 用于表述運行步驟,這里是順序執(zhí)行的。上述流程涉及到4個執(zhí)行步驟:

          1、打印外部傳參。${{github.event.inputs.weekly_index}} 表示輸入的參數(shù)。

          2、配置 git user 的 email 和 name。因為執(zhí)行內(nèi)容涉及提交操作,這里是為了標記自動化流程的提交。

          3、uses 語法對應的是插件功能,這里輸入插件名即可執(zhí)行對應插件配置的功能。actions/checkout@v3 是官方插件,用于拉取本倉庫代碼的。

          4、執(zhí)行腳本。我把私有倉庫的拉取,內(nèi)容的格式化,私有倉庫推送都放到了這個腳本里。

          私有倉庫的管理需要考慮 Git 鏈接的形式,Git 鏈接有兩種方式,一種是給 SSH 形式,這對于本地機器比較容易,對于不固定的打包機配置起來較為麻煩。第二種是 HTTPS 形式,HTTPS 是公有鏈接無法處理權(quán)限問題,但 Github 支持把 token 傳入鏈接的形式來管理權(quán)限。這里選擇使用HTTPS形式,配置的 Git 地址如下:

          https://{github_token}@github.com/username/repo.git

          對倉庫的操作使用這個鏈接就可以解決權(quán)限問題了,執(zhí)行結(jié)果如下:

          左邊是 job 描述,右邊是 steps 描述,每個 steps 都可以展開查看詳情。因為這里的步驟只有代碼拉取推送和格式處理,所以執(zhí)行很快。

          Blog Repo 發(fā)布網(wǎng)站

          這個階段對應的是 Blog Repo 推送內(nèi)容到騰訊云服務器。還是按上面的流程設(shè)計實現(xiàn)方式:

          如何觸發(fā)任務?

          這個歷程是上一步的承接,前一步已經(jīng)定好了推送頻率,這里可以接收到 push 即觸發(fā)任務。

          push:
              branches: [ "master" ]

          在什么機器觸發(fā)?

          這需要考慮到所使用的博客框架,如果是 Hexo/Jekyll 使用 Ubutu 就可以了。因為我將博客框架遷移到了 Publish[4],Publish 是一個由 Swift 編寫的靜態(tài)博客框架,所以運行機器只能是 macOS。測試時發(fā)現(xiàn) Publish 引用了libswift_Concurrency.dylib 這個庫,所以還需要指定版本為 macos-12。

          jobs:
            build:
              # macOS Monterey 12
              runs-on: macos-12

          如何執(zhí)行自動化任務?

          執(zhí)行流程大概是這樣的:編譯 publish -> 使用 publish 把 md 源文件轉(zhuǎn)成靜態(tài)網(wǎng)站格式 -> 發(fā)布到騰訊云。

          正常能獲取到 publish 執(zhí)行文件是無需編譯的,但因為我為了讓它兼容 hexo 的格式,做了一些魔改,所以我使用的 publish 是一個動態(tài)的版本,它需要隨修改隨時編譯。

          發(fā)布至騰訊云,也需要考慮權(quán)限問題,個人服務器沒有 Github 那種 token 授權(quán)形式,只能借助于 SSH 了。

          SSH

          在開始之前再簡單回顧下 SSH 登錄的一點原理。SSH 支持密碼和密鑰兩種登錄方式,我們一般為省去繁瑣的密碼輸入,會采用密鑰登錄的形式。密鑰登錄使用的是對稱加密,一般的做法是登錄端生成一對公私鑰,把公鑰放到服務端,私鑰保存在本地。對稱加密解決的是信息傳輸不會被篡改的問題,它無法防止中間人攻擊,因為它沒有HTTPS 那樣的 CA 來驗證可信性。SSH 選擇的是通過手動驗證的方式,關(guān)于手動驗證不知你是否還還記得這段內(nèi)容:

          The authenticity of host 'host (172.168.*.*)' can't be established.
          RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
          Are you sure you want to continue connecting (yes/no)?

          它就是用來手動驗證的,我們需要通過 host ip 驗證該鏈接是來自于可信的服務器還是中間人。確定過一次之后,這個信息會被寫到本地的 known_hosts 文件中,之后對于同一 ip 的服務器登錄就不會再彈這個驗證了。對于自動化流程來說,我們應該將私有服務器的驗證信息直接填入known_hosts文件,跳過阻塞式的二次確認。

          流程配置

          有了以上知識,我們對于密鑰的配置流程應該是如下圖所示:

          藍色的鑰匙為 pub_key,紅色鑰匙為 private_key,帶鑰匙的文件是 know_hosts。Github Action Runner 的配置流程如果都手動實現(xiàn)比較麻煩,我們可以使用install-ssh-key[5]這個插件快速實現(xiàn)這個功能:

          - name: Install SSH Key
                uses: shimataro/[email protected]
                with:
                  key: ${{ secrets.SSH_PRIVATE_KEY }}
                  # it's value doesn't matter
                  known_hosts: 'knowen_host_value for ssh-rsa'

          它要求兩個參數(shù),key 為 ssh 的 private key。SSH 私鑰可以使用上個章節(jié)介紹的 Secrets Actions 進行存儲,將其命名為 SSH_PRIVATE_KEY。

          known_hosts 是對 Server 端的信任記錄,用于免去手動確認的流程。這個內(nèi)容的獲取,有兩種方式,你可以查看本地的 known_hosts 文件找到對應的目標服務器的記錄,也可以利用 ssh-keyscan 去手動查找。

          $ ssh-keyscan -H <host-ip>

          這個結(jié)果會按多種加密算法產(chǎn)生多個結(jié)果,我們需要選擇類型為 ssh-rsa 的內(nèi)容,因為Github Action 僅支持這一種加密結(jié)果[6]。

          我們把這一條內(nèi)容添加 known_hosts 參數(shù)即可。當然你也可以選擇使用密鑰的形式存放。

          最重要的步驟已經(jīng)完成了,下面就可以編譯 publish 并發(fā)布內(nèi)容了。

          - name: Create Publish
            run: |
              git clone https://github.com/zhangferry/Publish.git ./publish
              cd publish
              make
              cd ..
          - name: Blog Deploy
            run: |
              echo "begin deploy"
              ./publish/.build/release/publish-cli deploy

          最后執(zhí)行結(jié)果:

          遺留問題

          往騰訊云服務器推送內(nèi)容時遇到一個騰訊云給我發(fā)了告警郵件,說是檢測到異地登錄,來源IP是美國,危險等級高危。這個登錄應該指的是 Github Action Runner 設(shè)備的登錄,這個目前還沒有找到有效的解決辦法,因為IP是動態(tài)的,無法通過手動加白的形式避免。

          另外也可關(guān)閉異地登錄的報警,在告警設(shè)置里關(guān)閉異地登錄報警選項即可。但這種方式也存在一定的安全風險,因為它不是解決問題而是無視問題。

          我暫時沒有找到更好的解決方案,如果有人知道更好的處理方式,歡迎告知啊。

          總結(jié)

          到此整個配置過程就完成了,簡單回顧下,我們利用兩個項目的兩個 Workflow 把自動化任務串聯(lián)起來,實現(xiàn)從共有倉庫發(fā)布博客的能力。這里的難點并不在于 Github Action 的配置,而是如何把我們的需求像是私有庫維護、秘鑰管理、Swift 項目編譯等有效的嵌入到自動化流程里。所以對于自動化流程的設(shè)計,重點是需要提前想好自己的需求,把這些要點一個個列出來,嘗試去找每一個步驟的解決方案。

          希望本篇文章能讓你對 Github Action 的能力有個大概認識,可以的話,也把它引入到自己的工作流中吧。

          引用資料

          [1]

          macos-12-Readme: https://github.com/actions/virtual-environments/blob/main/images/macos/macos-12-Readme.md

          [2]

          About self-hosted runners: https://docs.github.com/cn/[email protected]/actions/hosting-your-own-runners/about-self-hosted-runners

          [3]

          A debugger for actions: https://github.com/marketplace/actions/a-debugger-for-actions

          [4]

          Publish: https://github.com/JohnSundell/Publish

          [5]

          install-ssh-key: https://github.com/marketplace/actions/install-ssh-key

          [6]

          Deploying to a server via SSH and Rsync in a Github Action: https://zellwk.com/blog/github-actions-deploy/


          瀏覽 86
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本三级片东京热 | 国产高清黄色电影 | 欧美精品久久久久久久久 | 熟女精品视频 | 91精品国产91久久久久久吃药 |