takeda_san’s blog

KotlinとVRを頑張っていく方向。

Firebaseで業務アプリケーションを構築しよう 4:GitHub Actionsでデプロイフローの構築

シリーズ

前回のあらすじ

一覧画面と編集画面の追加、CloudStoreにデータの保存ができるようになりました。
Firebaseで業務アプリケーションを構築しよう 3:一覧画面と編集画面の追加、CloudStoreにデータの保存 - takeda_san’s blog

GitHub ActionsでCIできるようにする

第一回の記事でCircleCIでCI/CDフローを構築すると言ったな。
あれは嘘だ。

というわけでGitHub Actionsを使ってまずは、Pushをトリガーにビルドとテストがされるようにする。
やり方は検索下手すぎて、ベータ版の頃の記事と区別がつかないので公式を見に行きましょう。
GitHub Actions Documentation - GitHub ヘルプ

テンプレートからワークフローを作る

Node.js向けのワークフローのテンプレートを使うと手早く設定が書けるのでありがたく利用しましょう。
他にもテンプレ豊富なのでイチから作ることはあんまりないのかな…?

f:id:takeda_san:20191204230853p:plain

nodeのバージョン指定を12だけにしたのみで、ほぼ、そのまんまです。

name: Node CI

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [12.x]

    steps:
    - uses: actions/checkout@v1
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - name: npm install, build, and test
      run: |
        npm ci
        npm run build --if-present
        npm test
      env:
        CI: true

GitHub上のエディタがドキュメント参照しながら書けるので、そのまん書いてコミット&pushしたほうが楽かもしれない。
push時に動く設定なので動作確認もすぐできるし。
こんな感じでばっちりログも見れます。

f:id:takeda_san:20191204231238p:plain

やったね。ビルド成功!

f:id:takeda_san:20191204231421p:plain

おハマリポイント その1

先頭に . が付くディレクトリの指定がWindowsと違うぞ!ではまる

rimraf functions/ssr && mkdirp functions/ssr && cpx .nuxt/dist/** functions/ssr/dist

というコマンドでビルドした資材をfunctions用にコピーしてるわけなんですが、ここ

cpx .nuxt/dist/** functions/ssr/dist

ここのディレクトリの指定 .nuxtGitHub Actionsで指定してる環境(Ubuntu)だとダメらしく、cpxのコマンドエラーが出る。
ちゃんと囲もんで指定しようねという話。
(当たり前です)

cpx '.nuxt/dist/**' functions/ssr/dist

おハマリポイント その2

これ完全にGitHub Actions関係ないのですが、初めてテスト走らせた時のおハマリ。
jestでのテスト実行時にファイルが見つからんとのこと。

    Could not locate module @/components/Logo.vue mapped as:
    /home/runner/work/yukito/yukito/components/Logo.vue.

    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^@\/(.*)$/": "/home/runner/work/yukito/yukito/$1"
      },
      "resolver": null
    }

      1 | import { mount } from '@vue/test-utils'
    > 2 | import Logo from '@/components/Logo.vue'
        | ^
      3 | 
      4 | describe('Logo', () => {
      5 |   test('is a Vue instance', () => {

      at createNoMappedModuleFoundError (node_modules/jest-resolve/build/index.js:501:17)
      at Object.<anonymous> (test/Logo.spec.js:2:1)

確かにLogo.vueは <root-dir>/app/components 配下だからそこにはない。
というわけで jest.config.jsディレクトリ設定にappを追加しましょう。
こんな感じ。

module.exports = {
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/app/$1',
    '^~/(.*)$': '<rootDir>/app/$1',
    '^vue$': 'vue/dist/vue.common.js'
  },
  moduleFileExtensions: ['js', 'vue', 'json'],
  transform: {
    '^.+\\.js$': 'babel-jest',
    '.*\\.(vue)$': 'vue-jest'
  },
  collectCoverage: true,
  collectCoverageFrom: [
    '<rootDir>/app/components/**/*.vue',
    '<rootDir>/app/pages/**/*.vue'
  ]
}

ここでの変更はこちら。
ディレクトリの指定変更 · takedasan/yukito@b2aa3c5 · GitHub

Firebase Functionsにデプロイできるようにする

ビルドができたので、デプロイもできるようにしましょう。
本当はFirebaseのCLIをインストールして…secretsをオプション指定して…としなきゃいけないのですが、MarketplaceのActionsにFirebaseデプロイ用のものがあるので、ありがたく使いましょう。

GitHub Action for Firebase · Actions · GitHub Marketplace · GitHub

このページの通りなのですが、ローカルで firebase login:ci を叩いてsecrets用のトークンを取得します。
こんな感じで FIREBASE_TOKEN としてさっき取得したトークンを設定します。
これが環境変数としてうまいこと差し込まれる模様。

f:id:takeda_san:20191204232905p:plain

こんな感じで書き直し。

name: Node CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]
    steps:
    - uses: actions/checkout@v1
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - name: npm install, build, and test
      run: |
        npm install
        npm run build
        npm run build --prefix ./functions
    - name: Archive Production Artifact Dist
      uses: actions/upload-artifact@master
      with:
        name: dist
        path: functions/ssr/dist
    - name: Archive Production Artifact Lib
      uses: actions/upload-artifact@master
      with:
        name: lib
        path: functions/lib

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - name: Checkout Repo
      uses: actions/checkout@master
    - name: Download Artifact
      uses: actions/download-artifact@master
      with:
        name: dist
        path: functions/ssr/dist
    - name: Download Artifact
      uses: actions/download-artifact@master
      with:
        name: lib
        path: functions/lib
    - name: npm install
      run: |
        npm install
        npm --prefix ./functions install ./functions
    - name: Deploy to Firebase
      uses: w9jds/firebase-action@master
      with:
        args: deploy
      env:
        FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
        PROJECT_ID: <projectid>

感覚的にはCircleCIのYAMLと同じ感覚で書けて学習コストが少なそうですね。

f:id:takeda_san:20191205012817p:plain

動作確認ヨシ!(保存されているデータの様子がおかしい)

f:id:takeda_san:20191205020520p:plain

感想