しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Pipelines で VuePress のビルドとデプロイを自動化する

これまで Grav を使って shibayan.jp にペライチのコンテンツを配置していたのですが、メンテナンスが面倒だったりパフォーマンスに問題があったので移行を考えていました。

そして今日もアップデートが失敗して Composer からやり直しになった結果、三宅さんに教えてもらった VuePress への移行を決意しました。

さっと公式サイトとドキュメントを眺めた感じでは、Markdown で書いてしまえばビルド時に静的な html やアセットが生成されるようでした。

それを App Service にデプロイすれば快適に動作すると確信したので、一気に CI / CD 含めて移行しました。

VuePress で簡単なサイトを作る

この辺りはドキュメントを読みながら進めましたが、CI のことを考えて VuePress はグローバルにインストールしないようにしました。

適当に package.json を用意して、簡単に開発とビルドが行えるようにします。

{
  "name": "shibayan.jp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vuepress dev src",
    "build": "vuepress build src"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vuepress": "^1.0.2"
  }
}

Node.js 力が低いのでこれであってるのか分からないですが、問題なく動いてはいます。

最初はリポジトリのルートにそのまま Markdown ファイルを置いてましたが、分かりにくくなったので src という名前でディレクトリを切って、その中に VuePress 用のファイルを入れるようにしました。

f:id:shiba-yan:20190701162824p:plain

VuePress の設定が出来れば、後は Grav から Markdown を殆どそのまま移行しました。ほぼペライチのサイトだったので、ページ自体は一瞬で移行出来ました。

元々のサイトでは Web.config を使って、カスタムドメインへのリダイレクト強制や HSTS などの設定を行っていたので、.vuepress/public に Web.config を置いてデプロイされるようにしました。

Azure Pipelines で VuePress をビルドする

サイト自体は一瞬で完成したので、次は Azure Pipelines を使ってビルドとデプロイのパイプラインを構築します。これまでは Classic Editor を使って書いてきましたが、今回は YAML を使ってみました。

UI に従ってビルドするリポジトリを選ぶと、ファイルをスキャンして推奨されるテンプレートを表示してくれます。今回は通常の Node.js テンプレートを使いました。

f:id:shiba-yan:20190701154410p:plain

Node.js のテンプレートを選ぶと npm installnpm run build だけ行われる定義が生成されます。テンプレートを選ぶだけで、必要なタスクの半分は完成しています。

Azure Pipelines の YAML エディタが結構使いやすかったのと、GitHub とのインテグレーションがかなり強力だったので結構いけてました。

YAML を編集し、保存する際には同じブランチにコミットを作るか、それとも別ブランチに作るか聞いてくれます。GitHub のエディタと近い挙動です。

f:id:shiba-yan:20190701154421p:plain

Pull Request をまだ作っていなくても、保存したコミットを Queue に入れてビルドする機能もあるので、ビルド定義を書いている時のテストが行いやすかったです。

最終的には以下のような YAML を書いて VuePress のビルドを行います。

# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'

- script: |
    npm install
    npm run build -- --dest dist
  displayName: 'npm install and build'

- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: '$(Build.SourcesDirectory)/dist'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildNumber).zip'
    replaceExistingArchive: true
  displayName: 'Archive artifact'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'
  displayName: 'Publish artifact'

VuePress のビルド結果を zip で圧縮して、Azure Pipelines の Artifact として保存するだけの簡単な定義です。

f:id:shiba-yan:20190701154625p:plain

ビルドは 1 分以内で大体終わっていました。ビルド結果は保存されているので、後は Release パイプラインで App Service にデプロイするだけです。

App Service に Run From Package としてデプロイ

VuePress でのビルド結果は静的なファイルなので Run From Package を使ってデプロイします。

実行時に処理する部分がないので Azure Storage の Static website hosting でも良いですが、カスタムドメインと HTTPS のことを考えると App Service の方が楽です。

Release パイプラインは例によって Azure Web App タスクを使ってデプロイします。

f:id:shiba-yan:20190701164856p:plain

Deployment options で Run From Package を選ぶのを忘れないように気を付けましょう。

f:id:shiba-yan:20190701164808p:plain

後は Continuous deployment trigger の設定をすれば、ビルド完了後にデプロイが行われます。

実際にコミットすると、自動的にデプロイまで実行されることが確認できます。

f:id:shiba-yan:20190701154636p:plain

もちろん App Service にアクセスすると、VuePress で作成したサイトが表示されます。静的なサイトかつ Run From Package で動作しているので、App Service の弱点である I/O 周りを改善できます。

まだ全然 VuePress の機能を使えていないですが、CI 周りを組んでしまえば更新が非常に楽になるので、これから時間のある時を見つけて作業していく予定です。

あともう少し Azure Pipelines の YAML 周りを深堀したいとも思ってます。