Electron アプリのパッケージツールを electron-builder に移行

GitHub Actions で 野良 Scrapbox アプリの CI を 作った話の続きです。

blog.kondoumh.com

ほぼ同時ぐらいに azu さんが、同じテーマのブログを書かれてました。

efcl.info

僕のはビルドするところまででしたが、リリースまで実現されていて非常に参考になりました。特にパッケージツールとして使われている electron-builder が便利そうだったので早速移行することにしました。

www.npmjs.com

これまで electron-packager を使っていて electron-builder の存在は知ってたものの、試したことはありませんでした。各プラットフォームに対応した(完全に動作する)インストーラまで作ってくれます。

f:id:kondoumh:20190919214959p:plain

はなぢ出ました。

electron-packager の場合、インストーラを作成するには他の NPM パッケージとの併用が必要なので手をつけてませんでした。これでユーザーのインストール作業も簡単になります。

package.json にプラットフォーム毎の設定が書けるので npm script はプラットフォーム共通にできます。

  "build": {
    "productName": "sbe",
    "mac": {
      "icon": "icons/mac/sbe.icns"
    },
    "win": {
      "icon": "icons/win/sbe.ico"
    }
  },
  "scripts": {
    "start": "electron .",
    "pack": "electron-builder --dir",
    "dist": "electron-builder",
  },

インストーラ形式で生成されるため、各 OS のコマンドで成果物を zip 圧縮する必要もなくなりました。

おかげで GitHub Actions workflow の matrix.os による if expression も撲滅することができ、step も減らせて非常にスッキリしました。

GitHub Actions の Matrix build で各 OS 向けの Electron アプリをビルドする

Scrapbox の野良 Electron アプリ sbe をリリースするときは、macOS / Windows のバイナリをそれぞれ MacBook Pro や Windows ラップトップでビルドし GitHub の Release Draft にアップロードして公開しています。ビルドが1箇所でできないのは結構めんどくさいものです。

GitHub Actions の Matrix build を使うと複数の OS・複数のランタイム環境 (複数バージョンの Node.js 環境など) の組合せのビルドやテストを1つの Workflow で一気に実行できます。これを使って面倒な各 OS 向けのビルドを CI 化しようと思いました。

GitHub Actionsのワークフロー構文 - GitHub ヘルプ

Matrix build の Matrix パラメータには Ubuntu / Windows / macOS などを仮想環境として指定可能です。

LinuxおよびWindowsのGitHub Actions仮想環境は、GitHub Actions runnerがインストールされたMicrosoft AzureのStandard_DS2_v2仮想マシン上にホストされています。 GitHub Actions runner は、Azure Pipelines Agent のフォークです。 Standard_DS2_v2マシンリソースに関する詳しい情報については、Microsoft Azureドキュメンテーションの「DSv2-series」を参照してください。 GitHubは、macOS仮想環境のホストにMacStadiumを使用しています。

GitHub Actionsの仮想環境 - GitHub ヘルプ

GitHub が Microsoft に買収されたことで Azure の Windows Server 環境を Action の実行環境として使えるみたいですね。MacStadium は iOS / macOS アプリの CI/CD サービスのようです。

www.macstadium.com

今回は Matrix build により macOS と Windows 環境で下記ステップを実行します。

  • リポジトリへの tag push をトリガーとして開始する
  • Node.js 環境を構築する (最新の v12 系のみ)
  • OS に応じた npm script (electron-packager) を実行する
  • 生成されたバイナリーを zip 圧縮する
  • 圧縮されたバイナリーを成果物として保存する

実際の Workflow 定義です。

name: Build sbe binaries

on:
  push:
    branches:
      - "!*"
    tags:
      - "v*"

jobs:
  build:

    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [windows-latest, macos-latest]

    steps:
    - uses: actions/checkout@v1
    - name: setup nodejs
      uses: actions/setup-node@v1
      with:
        node-version: 12.x
    - name: install dependencies
      run: npm install

    - name: package for macOS
      if: matrix.os == 'macos-latest'
      run: |
        echo ${GITHUB_REF}
        npm run package-macos
        zip -ry sbe-darwin-x64/sbe-macos.zip sbe-darwin-x64/sbe.app
    - name: archive package for macOS
      if: matrix.os == 'macos-latest'
      uses: actions/upload-artifact@master
      with:
        name: sbe-v-macos
        path: ./sbe-darwin-x64/sbe-macos.zip

    - name: show ref tags
      if: matrix.os == 'windows-latest'
      run: echo %GITHUB_REF%
    - name: package for Windows
      if: matrix.os == 'windows-latest'
      run: npm run package-win32
    - name: zip package for Windows
      if: matrix.os == 'windows-latest'
      run: powershell Compress-Archive -Path sbe-win32-x64 -DestinationPath sbe-windows.zip
    - name: archive package for Windows
      if: matrix.os == 'windows-latest'
      uses: actions/upload-artifact@master
      with:
        name: sbe-v-windows
        path: sbe-windows.zip

v で始まる名前の tag が push された場合に起動するようにトリガーを設定しています。

Job の Matrix パラメータ に windows-latestmacos-latest を指定して Matrix build を実行しています。

step 毎に if expression を使って Matrix パラメータ (os) を判定し実行するコマンドを使い分けています。macos では bash を、Windows では cmd.exe ( と PowerShell) で動作するコマンドを記述しています。

GitHub Actions (beta) の Windows 仮想環境では、run: で複数コマンドを実行できないようでしたので step を分割し1コマンドずつ実行するようにしました。

push された tag の名前はビルトインの環境変数 GITHUB_REF に格納されます。artifact のファイル名に tag 名を使いたいのですが、GITHUB_REF に設定される値は refs/tags/v1.0.2 のような形式なのでそのままファイル名に使用することができません。GitHub Actions の関数には文字列の join はあるのに split がないという状況です。

GitHub Actions のコンテキストおよび式の構文 - GitHub ヘルプ

ということで tag 名を upload-artifat の path に指定するのは断念し、echo で出力するのみとしています。

Workflow を実行すると OS 毎にジョブがパラレル実行され、ビルド済みのバイナリーが Artifact として保存されます。

f:id:kondoumh:20190915211234p:plain

GitHub Actions で各 OS 向けのバイナリのビルドを 1つの Workflow で実現できました。今後は、GitHub API で Release Draft にアップロードする Job や UI テストを実行する Job を追加していきたいと思っています。

追記) electron-packager -> electron-builder に移行することで OS 固有の処理がなくなり if expression はなくすことができました。

blog.kondoumh.com

参考記事:

www.kaizenprogrammer.com

GitHub Actions で Hugo のサイト生成と公開を自動化する

Hugo を導入してホームページ更新は楽になりました。

blog.kondoumh.com

ただ、「ビルド時の環境変数設定を忘れて Google Analytics のトラッキング ID が生成されてなかった」など凡ミスがあったり、生成したファイルをアップロードするのが面倒だったりと、まだ自動化の余地があります。

Netlify が使えれば超楽ですが、レンタルサーバーに配置してるので、ページの Markdown ファイルを編集して GitHub に push したら生成・公開してくれるとよいかなと。

自分のアカウントではすでに GitHub Actions が有効になっています。

blog.kondoumh.com

ということで、以下のステップからなるワークフローを追加してみました。

  • Hugo をインストール
  • サイトのコードを theme 用の submodule を含めて clone
  • hugo コマンドを実行して generate
  • 成果物を upload-artifact で保存
  • レンタルサーバーにアップロード

実際のワークフロー定義です。

name: Generate and publish site

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    
    steps:
    - name: install hugo
      run: |
        curl -L https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-64bit.tar.gz | tar -xz
        sudo mv hugo /usr/local/bin/hugo
      env:
        HUGO_VERSION: 0.57.2

    - name: checkout
      uses: actions/checkout@v1
      with:
        submodules: true

    - name: generate
      run: HUGO_ENV=production hugo

    - name: archive
      uses: actions/upload-artifact@master
      with:
        name: public
        path: ./public

    - name: publish
      run: |
        pushd ./public
        find . -type f -exec curl --ftp-create-dirs -T {} ftp://${{ secrets.FTP_USER }}:${{ secrets.FTP_PASSWD }}@${{ secrets.FTP_HOST}}/${{ secrets.ROOT_PATH}}/{} \;
        popd

Hugo のインストールは、curl でバイナリをダウンロードして、/usr/local/bin に配置するだけ。超シンプルです。sudo が必要だったので Action は non-root ユーザーで実行されるようですね。

インストールする Hugo のバージョンは 環境変数 HUGO_VERSION に設定してます。現状、環境変数は外部からは与えられないようです。

checkout action で submodules を true にすれば、clone 時に submodules も更新してくれます。

レンタルサーバーにアップロードするための秘密情報は、リポジトリに設定された secrets に設定してます。

f:id:kondoumh:20190914223552p:plain

${{ secrets.NAME_OF_ENV }} の形式で取得可能です。secrets を環境変数のように使えなくもないですが、一度設定してしまうと値を閲覧することすらできないのでやはり秘密情報専用に使う方がよいでしょう。

レンタルサーバが FTP しか受け付けないので、生成したファイルを curl で FTP アップロードするワンライナーを実行しています。

実行結果です。

f:id:kondoumh:20190914224518p:plain

うまくいきました。

これで、ホームページ更新のワークフローが自動化され GitHub リポジトリで完結するようになりました。

Android 10 on Pixel 3 XL

Pixel 3 XL に Android 10 がインストール可能になったので早速入れてみました。

グループアイコンのフチがくっきりしたり、スクリーンロックアイコンがアニメーションするようになりました。

ダークテーマにしたら、標準アプリはだいたいダークになりました。

Gmail アプリは未対応のようですが、他には Slack も対応してて自動で切り替わってました。

ダークモード、消費電力が少なそうで、目にキツくない感じしますね。

Android 10 からの機能ではないと思いますが、ライブ壁紙?が追加されたので設定してみました。iOS の壁紙のように見る角度によって変わったり、昼と夜でも変わったり。

共有画面で連絡先とアプリが同時に出るようになったので、タップミスしなくなりました。これまでは、アプリが出た後に時間差で連絡先が出て座標がズレるため、あらぬ場所を押してしまう現象があったのでした。

期待のデスクトップモードは正式リリースではなく開発者オプションで有効化する必要があります。Pixel 3 の場合、USB-C からのディスプレイ出力には対応しておらず、なんらかのアダプターが必要な感じがします。ショボーン

.NET Core と VS Code によるクロスプラットフォーム Web 開発環境

.NET Core が成熟してきているというのをヒシヒシと感じていて、元祖 .NET Framework はメンテナンスモードだし、.NET Core ファミリーは来年には .NET 5 として大統一されるみたいだし、ちょっと触っておきたいという気持ちになりました。

devblogs.microsoft.com

Visual Studio 2019 Community の最新版を入れていても、.NET Core SDK の最新版は入っていないっぽいので、ダウンロード・インストールします。

dotnet.microsoft.com

Windows 版

f:id:kondoumh:20190828085947p:plain

C:\> dotnet --info
.NET Core SDK (global.json を反映):
 Version:   2.2.401
 Commit:    729b316c13

ランタイム環境:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.2.401\

Host (useful for support):
  Version: 2.2.6
  Commit:  7dac9b1b51

.NET Core SDKs installed:
  2.1.503 [C:\Program Files\dotnet\sdk]
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.1.801 [C:\Program Files\dotnet\sdk]
  2.2.401 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

macOS 版

f:id:kondoumh:20190828225609p:plain

$  dotnet --info
.NET Core SDK (global.json を反映):
 Version:   2.2.401
 Commit:    729b316c13

ランタイム環境:
 OS Name:     Mac OS X
 OS Version:  10.14
 OS Platform: Darwin
 RID:         osx.10.14-x64
 Base Path:   /usr/local/share/dotnet/sdk/2.2.401/

Host (useful for support):
  Version: 2.2.6
  Commit:  7dac9b1b51

.NET Core SDKs installed:
  1.0.4 [/usr/local/share/dotnet/sdk]
  2.0.0 [/usr/local/share/dotnet/sdk]
  2.1.505 [/usr/local/share/dotnet/sdk]
  2.1.701 [/usr/local/share/dotnet/sdk]
  2.2.401 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.9 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.12 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.6 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.9 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.12 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.6 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.6 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

バージョンや runtime 同じですね。

docs.microsoft.com

チュートリアルを Visual Studio ではなく、dotnet コマンドと VS Code で進めていきます(チュートリアルには両方の手順が書かれています)。

dotnet コマンドリファレンスは↓にあります。

docs.microsoft.com

空のソリューションを作成します。

$ mkdir WebApiSample
$ cd WebApiSample
$ dotnet new sln
テンプレート "Solution File" が正常に作成されました。
$ ls
WebApiSample.sln

WebApi のプロジェクトを作成します。

$ dotnet new webapi -o TodoApi
テンプレート "ASP.NET Core Web API" が正常に作成されました。

作成後のアクションを処理しています...
'dotnet restore' を TodoApi/TodoApi.csproj で実行しています...
  TodoApi.csproj の復元が 1.51 sec で完了しました。

正常に復元されました。

$ ls
TodoApi          WebApiSample.sln

ソリューションに TodoApi プロジェクトを追加してビルドします。

$ dotnet sln WebApiSample.sln add TodoApi/TodoApi.csproj
プロジェクト `TodoApi/TodoApi.csproj` をソリューションに追加しました。

$ dotnet build
.NET Core 向け Microsoft (R) Build Engine バージョン 16.2.32702+c4012a063
Copyright (C) Microsoft Corporation.All rights reserved.

  WebApiSample/TodoApi/TodoApi.csproj の復元が 48.07 ms で完了しました。
  TodoApi -> WebApiSample/TodoApi/bin/Debug/netcoreapp2.2/TodoApi.dll

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:03.44

以上、.NET Core SDK に含まれる dotnet コマンドだけで、ソリューション作成、プロジェクトの作成と追加、ビルドまでできてしまいました。

ここで VS Code でプロジェクトフォルダを開くと拡張のインストールを促されます。

marketplace.visualstudio.com

これは OmniSharp が開発する Language Server Protocol 準拠の拡張で、本家 Visual Studio レベルのコード補完、エラー解析機能を提供します。その他必要なソフトウェアが一式インストールされます。

チュートリアルに従ってコードを追加していきます。

データクラス

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

Entity Framework の DbContext

using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
  public class TodoContext : DbContext
  {
    public TodoContext(DbContextOptions<TodoContext> options) : base(options)
    {
    }
    public DbSet<TodoItem> TodoItems { get; set; }
  }
}

これを Startup クラスに DbContext としてインジェクションします。UseInMemoryDatabase なんての使えるので開発が楽ですね。

using Microsoft.EntityFrameworkCore;
 :
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
        :
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
            opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }
       :
    }
}

あとは、Controller クラスに HTTP メソッドに対応するメソッドを追加していきます。

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TodoApi.Models;

namespace TodoApi.Controllers
{
  [Route("api/[controller]")]
  [ApiController]
  public class TodoController : ControllerBase
  {
    private readonly TodoContext _context;

    public TodoController(TodoContext context)
    {
      _context = context;

      if (_context.TodoItems.Count() == 0)
      {
        _context.TodoItems.Add(new TodoItem { Name = "Item1"});
        _context.SaveChanges();
      }
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
    {
      return await _context.TodoItems.ToListAsync();
    }
  
    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
    {
      var todoItem = await _context.TodoItems.FindAsync(id);
      if (todoItem == null)
      {
        return NotFound();
      }
      return todoItem;
    }

    [HttpPost]
    public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
    {
      _context.TodoItems.Add(item);
      await _context.SaveChangesAsync();
      return CreatedAtAction(nameof(GetTodoItem), new TodoItem{ Id = item.Id }, item);
    }
  }
}

VS Code によるコード補完の様子。

f:id:kondoumh:20190829201524p:plain

デバッグの様子です。

f:id:kondoumh:20190829200536p:plain

Windows でも macOS でも全く同じ DX です。Node.js + TypeScript で Express 開発の時も相当いいと思いましたが、もはやほぼ Visual Studio (≠ Code) です。C# のような静的型付け言語には専用の IDE が要ると思っていたのですが・・。サーバーサイドのコードだけならもう Visual Studio なくてもできます。

blog.kondoumh.com

.NET Core SDK と VS Code があれば、快適な ASP.NET Core 開発環境が構築できることが分かりました。

さらに Remote Development を使えばリモートマシンやコンテナイメージに .NET Core SDK を導入しておき、手元は VS Code だけで開発ってのもできるでしょう。

blog.kondoumh.com

OmniSharp に対応した拡張を使えば、ターミナル の Emacs や Vim でもいけそうです。

野良 Scrapbox アプリ - 自分が作成したページ一覧表示と v1.0 リリース

社内で Scrapbox を使っていると大量のページが日々作られ、作成したページが埋もれて忘れてしまうことがよくあります。書きかけで放置してしまうことも。

そこで、作成したページを時折見直し加筆修正する契機になるよう、自分が作ったページ一覧を表示する機能を追加しました。

Scrapbox の API でページ一覧を取得すると、ページ毎に作成ユーザの ID が取得可能です。そこで、作成者のユーザ ID がログインユーザ ID と一致するものをフィルタリングして独立したタブに表示するようにしています。

f:id:kondoumh:20190824173419p:plain

頻繁な API 呼び出しを避けるために取得したデータはローカルにキャッシュするようにしました。

自分では作成していないけど編集したページの情報も表示したいところですが、こちらは個別ページの API でしか取れず、通信量が多くなってしまうので実装はしませんでした。ひとまずクライアントサイドでできることはこのレベルかなと。

今回のリリースで v1.0 にしました。0.9 まで来てたというのもありますが、Electron v6 にアップデートできたのが大きいです。v5 では WebView で Scrapbox のページが表示されなくて、ずっと v4 から移行できずにいました。最新の Chrome に追従できたので 1.0 ということにしました。

f:id:kondoumh:20190825115910p:plain

Release v1.0.0 · kondoumh/sbe · GitHub

GitHub Actions (beta) を使ってみる

今年の5月にベータ公開されてすぐに申し込んでいました。3ヶ月ぐらい経って僕のアカウントにもローリングでリリースされました。

github.com

元々 HCL*1 ベースでグラフィカルな UI で構築する方式でしたが、僕が使えるようになった時には HCL は非推奨となり 他の多くの CI ツール同様 YAML が標準になりました。

ワークフローがない状態で Actions の画面を開くとプロジェクトの内容に応じたワークフローの雛形がサジェストされます。一度作ってしまうとサジェストされなくなりますが、雛形は以下のリポジトリに集まっているようです。

github.com

例によって Spring Boot のサンプルアプリで試してみます。

github.com

Maven の雛形とDocker image の雛形から作成しました。

f:id:kondoumh:20190822211854p:plain

f:id:kondoumh:20190822223252p:plain

2つのジョブから構成しています。

  • package: Spring Boot アプリのパッケージ(ビルド、テスト、JAR 作成)
  • build-image: Docker イメージビルド

各ジョブは別の Docker インスタンスで実行されます。build-image は needs を使って package の後続ジョブとしています*2

name: Example CI

on: [push]

jobs:
  package:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: Set up JDK 1.8
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    - name: Build with Maven
      run: ./mvnw package

    - uses: actions/upload-artifact@master
      with:
        name: sb-sample-service.jar
        path: ./target/sb-sample-service.jar

  build-image:

    needs: package
    runs-on: ubuntu-latest
 
    steps:
    - uses: actions/checkout@v1
    - uses: actions/download-artifact@master
      with:
        name: sb-sample-service.jar
        path: ./target

    - name: Build the Docker image
      run: docker build . --file Dockerfile --tag sb-sample-service:$(date +%s)

ビルド成果物の JAR ファイルを ジョブ間で受け渡しできるよう、公式 Action から upload-artifact と download-artifact を使ってみました*3

github.com

github.com

Actions のタブから実行結果を確認できます。

f:id:kondoumh:20190822224105p:plain

ステップ毎に詳細なログを取得できます。upload-artifact によって保存された JAR ファイルをダウンロードすることも可能です。

イメージのビルドもログを見ると成功してタグ付けされたものができているようです。

Run docker build . --file Dockerfile --tag sb-sample-service:$(date +%s)
Sending build context to Docker daemon  33.23MB

Step 1/3 : FROM openjdk:8-jdk-alpine
8-jdk-alpine: Pulling from library/openjdk
e7c96db7181b: Already exists
f910a506b6cb: Pulling fs layer
c2274a1a0e27: Pulling fs layer
f910a506b6cb: Download complete
f910a506b6cb: Pull complete
c2274a1a0e27: Verifying Checksum
c2274a1a0e27: Download complete
c2274a1a0e27: Pull complete
Digest: sha256:94792824df2df33402f201713f932b58cb9de94a0cd524164a0f2283343547b3
Status: Downloaded newer image for openjdk:8-jdk-alpine
 ---> a3562aa0b991
 Step 2/3 : COPY ./target/sb-sample-service.jar sb-sample-service.jar
 ---> f103d9d489ff
Step 3/3 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/sb-sample-service.jar"]
 ---> Running in be018d0c3ee0
Removing intermediate container be018d0c3ee0
 ---> 7297e5983b31
Successfully built 7297e5983b31
Successfully tagged sb-sample-service:1566479900

今回はイメージをビルドして終わりでしたが、これまたベータ公開が始まっている Package Registry を使ってビルドしたイメージを Publish することができるようになると思われます*4

github.com

ところで、GitLab もリポジトリ単位で CI / CD を定義できましたが、登録できるパイプライン定義は1つでした。

blog.kondoumh.com

このため、単体テスト、結合テスト、リリースビルドなど様々な目的でパイプラインを作成すると .gitlab-ci.yml が巨大で複雑なものになりがちです。GitHub Action ではワークフローが複数定義可能ですので、様々な目的のワークフローを程よい単位で作成できるのではないでしょうか。

以上、GitHub Actions を簡単に試してみました。リリース版ではさらに完成度が上がっていることを期待しています。

参考記事:

www.kaizenprogrammer.com

*1:HashiCorp configuration language

*2:Docker の Multi-stage build でも同じようなことができますが、ジョブの連鎖として定義することで JAR 作成時のテストとイメージビルドが分離できて、CI の結果が分かりやすくなります。

*3:廃止になったグラフィカルなエディタがあれば、このような Action をオーサリングするのが楽だったのでは・・と思います。

*4:現時点では僕のアカウントではまだ使えません。