时光心语 發表於 2020-7-20 09:44:00

使用 Github Actions 自动部署 Angular 应用到 Github Pages

<h2 id="前言">前言</h2>
<p>最近在学习 Angular,一些基础的语法也学习的差不多了,就在 github 上新建了一个代码仓库,准备用 ng-zorro 搭个后台应用的模板,方便自己以后写些小东西时可以直接使用。前端项目,最主要的还是能够实际看到,因此考虑找个地方部署,因为自己的博客是部署到 github page 上的,并且这个项目也只是一个静态网站,所以这里同样选择使用 github page</p>
<p>同时,考虑到发布项目时,虽然使用 github page 已经帮我们省略了拷贝文件到服务器上这一步,但是还是需要自己手动的敲命令来完成项目的发布,因为发布的流程很单一,所以这里选择通过 github action 这个自动化工具来实现程序的自动化部署</p>
<p>代码仓库地址:ingos-admin</p>
<p>预览地址:https://yuiter.com/ingos-admin</p>
<h2 id="step-by-step">Step by Step</h2>
<h3 id="21手动部署">2.1、手动部署</h3>
<p>示例的 Angular 应用,你可以通过 Angular CLI 直接生成,如有需要,可以点击此链接进行跳转查看(电梯直达),这里就不演示创建的过程了</p>
<p>按照正常的前端项目发布流程,当我们需要发布时,需要使用 npm 命令来完成项目的打包。整个项目中所涉及的 npm 命令,我们可以通过查阅项目的 <code>package.json</code> 文件中的 <code>scripts</code> 节点进行查看</p>
<p>这里通过 Angular CLI 创建的项目可以通过<code>ng build</code>命令来完成项目的打包发布</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201602775-978334239.png" alt="npm 命令" loading="lazy"></p>
<p>当 build 命令执行完成后,项目根路径下 dist 文件夹中以项目名称命名的文件夹就是我们需要部署的文件。此时,如果是部署到自己的服务器上,只需要把这个文件夹拷贝到服务器上,通过 nginx 之类的服务器指向文件所在路径即可</p>
<p>同样的,当我们想要部署到 github page 时,我们也只需要将文件提交到 github 代码仓库中即可,之后 github 会自动完成应用的部署工作</p>
<p>因为 git 默认是会忽略编译生成的 dist 文件夹的,此时,想要把编译生成的文件推送到远程仓库,你需要修改 .gitignore 文件,或是通过 subtree 的形式,将 dist 文件夹作为一个分支推送到远程服务器</p>
<pre><code class="language-bash"># 创建并切换到 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
</code></pre>
<p>当然,这样还是显得有些麻烦,对于 angular 应用来说,我们完全可以使用社区提供的 angular-cli-ghpages 插件来简化这个操作</p>
<p>首先我们需要通过 npm 将插件安装到需要部署的程序中</p>
<pre><code class="language-bash">ng add angular-cli-ghpages
</code></pre>
<p>安装完成之后,我们就可以通过 ng deploy 命令来完成部署,插件会自动把打包生成的文件发布到 github 上,并创建一个 gh-pages 分支作为 github page 显示的站点</p>
<pre><code class="language-bash">ng deploy --base-href=/ingos-admin/
</code></pre>
<p>在之前学习 angular 中路由时有提到,在 angular 应用中,框架会将 index.html 文件中的 base 标签的 href 属性值配置为组件、模板、模块文件以及其它一些静态文件的基础路径地址。而当我们将程序部署到 github page 时,实际对应的网站地址是 <code>https://&lt;username&gt;.github.io/&lt;repositoryname&gt;</code>,因此,这里如果不指定 href 的话,程序会在根路径下去寻找站点相关的静态文件,毫无疑问,最终是无法找到的,所以这里我们需要调整 href 属性值 为我们的仓储名称</p>
<p>可以看到,在打包生成的 index.html 文件中,插件已经帮我们修改了 base 标签的 href 地址。以后当我们需要更新网站时,再使用上面的命令即可发布到 github page 上</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201623146-1008434142.png" alt="修改 base-href 配置" loading="lazy"></p>
<p>因为每次执行 ng deploy 命令时都需要在命令中添加 base-href 参数,所以这里我们可以在 package.json 文件中添加一个 script,这样当后面我们需要发布时,直接执行自定义的 ng deploy 命令即可</p>
<pre><code class="language-json">{
"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"
}
}
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201638906-418190456.png" alt="部署情况" loading="lazy"></p>
<h3 id="22自动部署">2.2、自动部署</h3>
<p>在上面的操作中虽然实现了将程序部署到 github page,但是还是需要我们手动的通过 npm 命令来完成部署,接下来就进行改造,通过 github actions 来实现自动部署</p>
<p>github actions 与其它的各种自动化工具相似,允许我们通过指定特定的 git 事件来触发我们的自动化任务,例如这里我需要在推送代码到服务器的 master 分支时自动触发程序的发布事件</p>
<p>你可以在代码仓库的 Actions tab 页面新增一个 workflow,也可以直接在本地代码根路径中新建一个 .github/workflows 文件夹来存放相关的脚本,因为 github actions 的执行脚本采用的是 yaml 格式,所以这里对于代码格式有着严格的要求,而每一个 yaml 文件则是一个单独的 workflow</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201651074-65463961.png" alt="Github Actions" loading="lazy"></p>
<p>这里我通过直接调整 github 默认的 workflow 文件来实现自动化部署功能,整个 yaml 文件包含了如下的三个部分</p>
<ul>
<li>name:当前 workflow 配置的名称</li>
<li>on:任务触发时机,这里是在向 github 上的 master 分支提交代码以及提交 PR 时进行触发</li>
<li>jobs:需要触发的任务信息,一个 workflow 可以包含多个的 job,这里只有一个名为 build 的 job</li>
</ul>
<pre><code class="language-yaml"># 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:
pull_request:
    branches:

# 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.
</code></pre>
<p>一个 workflow 文件中最重要的就是包含的 jobs,它表明了当前 workflow 所能实现的功能,一个 job 任务主要包含了如下的属性</p>
<ul>
<li>runs-on:当前 job 需要运行在的系统环境</li>
<li>steps:实现一个 job 需要执行的各个步骤</li>
<li>env:当前 job 执行时需要的各种环境变量</li>
<li>needs:当我们定义多个 job 时,默认是并行执行的,但是存在 job2 需要等 job1 执行完成后才可以执行的情况,这时,我们就可以在 needs 属性中指定 job2 依赖于 job1,从而确保整个 workflow 的正确执行</li>
</ul>
<p>在 steps 节点中,定义了当前 job 需要执行的各个步骤,step 分为两种,一种是我们使用 <code>users</code> 属性来直接引用别人已经发布的 action,例如这里通过引用 github 官方的 <code>actions/checkout@v2</code> 在宿主机中执行 git checkout 命令来拉取代码;另一种,则是我们通过 run 属性来手动编写脚本</p>
<p>对于我们想要的实现的功能,其实只包含了如下的四步:拉取代码 =》安装 node.js 环境 =》还原依赖 =》部署发布</p>
<p>对于拉取代码以及安装 node.js 环境,我们可以使用 github 官方的 action 来简化我们的脚本,因为我们在每次构建时都需要执行 npm install 命令来还原项目所需的各种依赖,因此这里在执行 install 命令之前,我们可以通过官方的<code>actions/cache@v2</code> 来缓存项目依赖,以加快构建的过程</p>
<p>这里在还原依赖时,使用到了 npm ci 而不是 npm install,从命令的名称就可以看出,ci 主要是在各种自动化环境构建时使用,通过读取 package-lock.json 文件中所包含的具体的依赖版本信息来加快还原过程</p>
<pre><code class="language-yaml">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
</code></pre>
<p>当还原完成之后,就可以执行 package.json 文件中的 deploy 命令了,这里需要注意,因为在 action 中执行的命令更多的都是只读权限,所以为了能够有足够的权限执行发布操作,我们需要在执行时在环境变量中附加上 GITHUB_TOKEN 变量</p>
<pre><code class="language-yaml">steps:
# Use angular-cli-ghpages to deploy app
- name: Deploy to github pages
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    run: npm run deploy
</code></pre>
<p>secrets.GITHUB_TOKEN 因为是 github 默认创建的,因此我们可以在 workflow 中直接使用,而对于一些另外需要授权的服务,直接将密码写在 yaml 文件中会不安全,这时你就可以在代码仓库的 settings tab 下通过设置 secrets 密钥信息,然后就可以通过变量的方式在 workflow 中直接使用</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201716007-1141117786.png" alt="设置密钥" loading="lazy"></p>
<p>当我们添加了环境变量之后,还需要对我们的实际执行的 npm 命令脚本进行一个调整</p>
<p>在本地执行发布命令时,本地的 git 配置中已经包含了相关的账户信息,而当在 workflow 中执行时因为处于一个匿名的状态,angular-cli-ghpages 没办法知道具体的执行人是谁,因此,我们需要在 ng deploy 命令中添加上 git 账户相关的配置参数</p>
<pre><code class="language-json">{
"name": "ingos-admin",
"version": "1.0.0",
"scripts": {
    "deploy": "ng deploy --no-silent --base-href=/ingos-admin/ --name='账户名' --email='密码'",
}
}
</code></pre>
<p>至此,完整的 workflow 脚本如下,当我们将本地代码推送到 github 仓库时,就会自动完成程序的发布部署</p>
<pre><code class="language-yaml"># 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:

# 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
</code></pre>
<p>这里需要需要注意,因为代码中包含了 workflow 文件,可能在推送到 github 时遇到如下的错误,此时需要我们对 access token 进行重新的设置</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201742354-2141285956.png" alt="权限不足" loading="lazy"></p>
<p>打开 GitHub Personal Access Tokens 页面,点击右侧的 Generate new token 按钮,选择新建一个 token 信息,在编辑权限时确保 workflow 有被勾选上,</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201755414-93204448.png" alt="创建 token" loading="lazy"></p>
<p>复制生成的 token 信息,打开电脑的凭据管理器,在 Windows 凭据标签内,找到 github 相关的凭据,此时你可以将已经存在的凭据密码更新成刚才复制的 token 信息,或者直接将已经存在的 github 凭据删除,这样再推送到 github 时会要求你进行登录,重新登录时将密码录入为你复制的 token 信息即可</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201808847-1370477155.png" alt="修改凭据" loading="lazy"></p>
<p>当推送成功之后,再次点击代码仓库的 Actions 菜单,则会显示已经执行的 workflow 记录,当我们点击具体的一个 workflow 记录,则可以显示出 workflow 中每个步骤的执行详情,你可以根据执行情况自行调整,至此,也就完成自动化部署的功能</p>
<p><img src="https://img2020.cnblogs.com/blog/1310859/202007/1310859-20200719201821507-813498738.png" alt="执行详情" loading="lazy"></p>
<h2 id="参考">参考</h2>
<ol>
<li>GitHub Actions 入门教程</li>
<li>是时候体验一下github action的魅力了</li>
<li>npm-ci</li>
<li>Git Extensions is a great tool but the credential management is very weak</li>
</ol><br><br>
来源:https://www.cnblogs.com/danvic712/p/deploy-angular-app-to-github-pages-with-github-actions.html
頁: [1]
查看完整版本: 使用 Github Actions 自动部署 Angular 应用到 Github Pages