使用 Github Actions 自動部署 Angular 應用到 Github Pages

前言

最近在學習 Angular,一些基礎的語法也學習的差不多了,就在 github 上新建了一個代碼倉庫,準備用 ng-zorro 搭個後臺應用的模板,方便自己以後寫些小東西時可以直接使用。前端項目,最主要的還是能夠實際看到,因此考慮找個地方部署,因爲自己的博客是部署到 github page 上的,並且這個項目也只是一個靜態網站,所以這裏同樣選擇使用 github page

同時,考慮到發佈項目時,雖然使用 github page 已經幫我們省略了拷貝文件到服務器上這一步,但是還是需要自己手動的敲命令來完成項目的發佈,因爲發佈的流程很單一,所以這裏選擇通過 github action 這個自動化工具來實現程序的自動化部署

代碼倉庫地址:ingos-admin

預覽地址:https://yuiter.com/ingos-admin

Step by Step

2.1、手動部署

示例的 Angular 應用,你可以通過 Angular CLI 直接生成,如有需要,可以點擊此鏈接進行跳轉查看(電梯直達),這裏就不演示創建的過程了

按照正常的前端項目發佈流程,當我們需要發佈時,需要使用 npm 命令來完成項目的打包。整個項目中所涉及的 npm 命令,我們可以通過查閱項目的 package.json 文件中的 scripts 節點進行查看

這裏通過 Angular CLI 創建的項目可以通過 ng build 命令來完成項目的打包發佈

npm 命令

當 build 命令執行完成後,項目根路徑下 dist 文件夾中以項目名稱命名的文件夾就是我們需要部署的文件。此時,如果是部署到自己的服務器上,只需要把這個文件夾拷貝到服務器上,通過 nginx 之類的服務器指向文件所在路徑即可

同樣的,當我們想要部署到 github page 時,我們也只需要將文件提交到 github 代碼倉庫中即可,之後 github 會自動完成應用的部署工作

因爲 git 默認是會忽略編譯生成的 dist 文件夾的,此時,想要把編譯生成的文件推送到遠程倉庫,你需要修改 .gitignore 文件,或是通過 subtree 的形式,將 dist 文件夾作爲一個分支推送到遠程服務器

# 創建並切換到 gh-pages 分支
git checkout -b gh-pages
# 將 dist 文件夾下的文件添加到 gh-pages 分支
git add -f dist
# 提交到本地分支
git commit -m 'created gh-pages'
# 推送到遠程分支
git subtree push --prefix dist origin gh-pages

當然,這樣還是顯得有些麻煩,對於 angular 應用來說,我們完全可以使用社區提供的 angular-cli-ghpages 插件來簡化這個操作

首先我們需要通過 npm 將插件安裝到需要部署的程序中

ng add angular-cli-ghpages

安裝完成之後,我們就可以通過 ng deploy 命令來完成部署,插件會自動把打包生成的文件發佈到 github 上,並創建一個 gh-pages 分支作爲 github page 顯示的站點

ng deploy --base-href=/ingos-admin/

在之前學習 angular 中路由時有提到,在 angular 應用中,框架會將 index.html 文件中的 base 標籤的 href 屬性值配置爲組件、模板、模塊文件以及其它一些靜態文件的基礎路徑地址。而當我們將程序部署到 github page 時,實際對應的網站地址是 https://<username>.github.io/<repositoryname>,因此,這裏如果不指定 href 的話,程序會在根路徑下去尋找站點相關的靜態文件,毫無疑問,最終是無法找到的,所以這裏我們需要調整 href 屬性值 爲我們的倉儲名稱

可以看到,在打包生成的 index.html 文件中,插件已經幫我們修改了 base 標籤的 href 地址。以後當我們需要更新網站時,再使用上面的命令即可發佈到 github page 上

修改 base-href 配置

因爲每次執行 ng deploy 命令時都需要在命令中添加 base-href 參數,所以這裏我們可以在 package.json 文件中添加一個 script,這樣當後面我們需要發佈時,直接執行自定義的 ng deploy 命令即可

{
  "name": "ingos-admin",
  "version": "1.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "deploy": "ng deploy --base-href=/ingos-admin/",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  }
}

部署情況

2.2、自動部署

在上面的操作中雖然實現了將程序部署到 github page,但是還是需要我們手動的通過 npm 命令來完成部署,接下來就進行改造,通過 github actions 來實現自動部署

github actions 與其它的各種自動化工具相似,允許我們通過指定特定的 git 事件來觸發我們的自動化任務,例如這裏我需要在推送代碼到服務器的 master 分支時自動觸發程序的發佈事件

你可以在代碼倉庫的 Actions tab 頁面新增一個 workflow,也可以直接在本地代碼根路徑中新建一個 .github/workflows 文件夾來存放相關的腳本,因爲 github actions 的執行腳本採用的是 yaml 格式,所以這裏對於代碼格式有着嚴格的要求,而每一個 yaml 文件則是一個單獨的 workflow

Github Actions

這裏我通過直接調整 github 默認的 workflow 文件來實現自動化部署功能,整個 yaml 文件包含了如下的三個部分

  • name:當前 workflow 配置的名稱
  • on:任務觸發時機,這裏是在向 github 上的 master 分支提交代碼以及提交 PR 時進行觸發
  • jobs:需要觸發的任務信息,一個 workflow 可以包含多個的 job,這裏只有一個名爲 build 的 job
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

# 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

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@v2

    # Runs a single command using the runners shell
    - name: Run a one-line script
      run: echo Hello, world!

    # Runs a set of commands using the runners shell
    - name: Run a multi-line script
      run: |
        echo Add other actions to build,
        echo test, and deploy your project.

一個 workflow 文件中最重要的就是包含的 jobs,它表明了當前 workflow 所能實現的功能,一個 job 任務主要包含了如下的屬性

  • runs-on:當前 job 需要運行在的系統環境
  • steps:實現一個 job 需要執行的各個步驟
  • env:當前 job 執行時需要的各種環境變量
  • needs:當我們定義多個 job 時,默認是並行執行的,但是存在 job2 需要等 job1 執行完成後纔可以執行的情況,這時,我們就可以在 needs 屬性中指定 job2 依賴於 job1,從而確保整個 workflow 的正確執行

在 steps 節點中,定義了當前 job 需要執行的各個步驟,step 分爲兩種,一種是我們使用 users 屬性來直接引用別人已經發布的 action,例如這裏通過引用 github 官方的 actions/checkout@v2 在宿主機中執行 git checkout 命令來拉取代碼;另一種,則是我們通過 run 屬性來手動編寫腳本

對於我們想要的實現的功能,其實只包含了如下的四步:拉取代碼 =》安裝 node.js 環境 =》還原依賴 =》部署發佈

對於拉取代碼以及安裝 node.js 環境,我們可以使用 github 官方的 action 來簡化我們的腳本,因爲我們在每次構建時都需要執行 npm install 命令來還原項目所需的各種依賴,因此這裏在執行 install 命令之前,我們可以通過官方的 actions/cache@v2 來緩存項目依賴,以加快構建的過程

這裏在還原依賴時,使用到了 npm ci 而不是 npm install,從命令的名稱就可以看出,ci 主要是在各種自動化環境構建時使用,通過讀取 package-lock.json 文件中所包含的具體的依賴版本信息來加快還原過程

steps:
  # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
  - uses: actions/checkout@v2

  # Install node js
  - name: Setup Node.js environment
    uses: actions/setup-node@v1
    with:
      node-version: 12.x

  # Cache node modules
  - name: Cache node modules
    uses: actions/cache@v2
    env:
      cache-name: cache-node-modules
    with:
      # npm cache files are stored in `~/.npm` on Linux/macOS
      path: ~/.npm
      key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
      restore-keys: |
        ${{ runner.os }}-build-${{ env.cache-name }}-
        ${{ runner.os }}-build-
        ${{ runner.os }}-

  # Install required dependencies to build app
  - name: Install dependencies
    run: npm ci

當還原完成之後,就可以執行 package.json 文件中的 deploy 命令了,這裏需要注意,因爲在 action 中執行的命令更多的都是隻讀權限,所以爲了能夠有足夠的權限執行發佈操作,我們需要在執行時在環境變量中附加上 GITHUB_TOKEN 變量

steps:
  # Use angular-cli-ghpages to deploy app
  - name: Deploy to github pages
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    run: npm run deploy

secrets.GITHUB_TOKEN 因爲是 github 默認創建的,因此我們可以在 workflow 中直接使用,而對於一些另外需要授權的服務,直接將密碼寫在 yaml 文件中會不安全,這時你就可以在代碼倉庫的 settings tab 下通過設置 secrets 密鑰信息,然後就可以通過變量的方式在 workflow 中直接使用

設置密鑰

當我們添加了環境變量之後,還需要對我們的實際執行的 npm 命令腳本進行一個調整

在本地執行發佈命令時,本地的 git 配置中已經包含了相關的賬戶信息,而當在 workflow 中執行時因爲處於一個匿名的狀態,angular-cli-ghpages 沒辦法知道具體的執行人是誰,因此,我們需要在 ng deploy 命令中添加上 git 賬戶相關的配置參數

{
  "name": "ingos-admin",
  "version": "1.0.0",
  "scripts": {
    "deploy": "ng deploy --no-silent --base-href=/ingos-admin/ --name='賬戶名' --email='密碼'",
  }
}

至此,完整的 workflow 腳本如下,當我們將本地代碼推送到 github 倉庫時,就會自動完成程序的發佈部署

# This is a basic workflow to deploy angular app into github pages
name: Deploy Github Pages

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [master]

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

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Install node js
      - name: Setup Node.js environment
        uses: actions/setup-node@v1
        with:
          node-version: 12.x

      # Cache node modules
      - name: Cache node modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          # npm cache files are stored in `~/.npm` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-

      # Install required dependencies to build app
      - name: Install dependencies
        run: npm ci

      # Use angular-cli-ghpages to deploy app
      - name: Deploy to github pages
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npm run deploy

這裏需要需要注意,因爲代碼中包含了 workflow 文件,可能在推送到 github 時遇到如下的錯誤,此時需要我們對 access token 進行重新的設置

權限不足

打開 GitHub Personal Access Tokens 頁面,點擊右側的 Generate new token 按鈕,選擇新建一個 token 信息,在編輯權限時確保 workflow 有被勾選上,

創建 token

複製生成的 token 信息,打開電腦的憑據管理器,在 Windows 憑據標籤內,找到 github 相關的憑據,此時你可以將已經存在的憑據密碼更新成剛纔複製的 token 信息,或者直接將已經存在的 github 憑據刪除,這樣再推送到 github 時會要求你進行登錄,重新登錄時將密碼錄入爲你複製的 token 信息即可

修改憑據

當推送成功之後,再次點擊代碼倉庫的 Actions 菜單,則會顯示已經執行的 workflow 記錄,當我們點擊具體的一個 workflow 記錄,則可以顯示出 workflow 中每個步驟的執行詳情,你可以根據執行情況自行調整,至此,也就完成自動化部署的功能

執行詳情

參考

  1. GitHub Actions 入門教程
  2. 是時候體驗一下github action的魅力了
  3. npm-ci
  4. Git Extensions is a great tool but the credential management is very weak
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章