GitHub Actions のセルフホストランナーがサービスとして登録可能になってた

GitHub Acitons では Self-hosted runner を利用して、独自のビルド環境でワークフローを実行することができます。

docs.github.com

企業内のプロキシサーバ配下のマシンでも利用できるので、

  • CI のたびにソフトウェアのインストールをしなくてもよい*1
  • 社外に出せないライブラリを利用したビルドが可能
  • GItHub Actions Runner の使用制限を超えてビルドマシンのリソースを自前で用意できる

などのメリットがあります。仕事でも EC2 の Ubuntu AMI を使って Self-hosted runner を構築しています。

GitHub Actions の初期の頃から Self-hosted runner の機能は提供されていましたが、ユーザープロセスとして起動するため、ホストマシンに SSH 接続して runner.sh を起動する必要がありました。runner.sh & とかでバックグラウンドで起動するといつの間にかプロセスが死んでたりするし、tmux で起動して detouch しておくのも信頼性に乏しいし・・。Docker コンテナ化して常時起動している人のブログも発見しましたが Docker がらみの CI で DinD 問題が発生するし・・ということでターミナルを1つ専用に上げっぱなしにして使っていました*2

runner.sh は標準出力にジョブの成功・失敗のログを出力するので Web UI 見なくても結果がわかります。セルフアップデート機能もあり、アイドリング時に自身のバージョンを自動的にアップデートしているようでした。

少し前にドキュメントを眺めてたら、Self-hosted runner をサービスとして登録できるようになっていました。

docs.github.com

Mac / Windows / Linux いずれの runner でも登録可能で、それぞれ launchd / PowerShell / systemd を利用したサービス化が可能です。Mac では plist、Linux では serviced も利用可能なようです。

ドキュメントの手順通り Service 登録したところ、実行ユーザは従来通りの non-root ユーザ (Linux なら ubuntu ユーザ) なので、ワークフローやシェルスクリプトには変更不要でした。

Terminal で見ていたログも、Linux では journalctl を使って runner のログをウォッチできます*3

$ sudo journalctl -u actions.runner.octo-org-octo-repo.runner01.service -f

docs.github.com

これで Self-hosted runner の運用がかなり楽になりました。

*1:ただし immutable なクリーン環境でのテストにならないというデメリットもあります。

*2:SSH セッション切れてもプロセスは残っているようでしたが。

*3:Windows では PowerShell でイベントログを見ることになります。

VS Code で Jupyter Notebook を使う

VS Code + Microsoft の Python 拡張だけで Jupyter Notebook が使えるのを知りました。

code.visualstudio.com

コマンドパレットから Notebook を新規作成できます。

f:id:kondoumh:20200723135306p:plain

あらかじめ Anaconda などで環境を構築するようガイドされています。とりあえず venv で環境を作りました。

% python3 -m venv jupyter_local
source jupyter_local/bin/activate
(jupyter_local) %

Notebook を開くとガチャガチャっとセルがレンダリングされ Jupyter や IPython などがインストールされてローカルに Jupyter Server が起動されます。Kernel が事前作成した環境で起動され Idle 状態になれば OK です。

f:id:kondoumh:20200723171219p:plain

セルにコードを入力して実行できることを確認。

f:id:kondoumh:20200723162533p:plain

venv にライブラリを pip install すればセルで使えます。

f:id:kondoumh:20200723162831p:plain

workspace のテーマを Light 系にすると Jupyter っぽさが増します。

f:id:kondoumh:20200724104826p:plain

使用できる Kernel は Python に限定されますが VS Code だけで手軽に Notebook が使えるのは便利だと思います。コード補完も効きますし。この他リモートの Jupyter Server に接続する機能もあります。.py ファイルにエクスポートすればデバッグも可能なようです。

Work from Home 環境 (PC リニューアルしたい)

テレワークではリモートデスクトップで客先マシンに接続して作業をしていて、自宅マシンにはさほど性能が要求されてませんでした。最近社内アプリ開発に関与するようになり Kubernetes ベースの開発環境を構築したら MacBook Pro 13 Early 2015 のスペック不足が顕著になりました。メモリ(16GB)はもちろん Intel Haswell 世代の Dual Core CPU が弱いです。

取り急ぎ、いろんなタスクを手持ちのマシンに割り振りました。

  • MacBook Pro 2015 (第4世代 Corei 7 / 16GB RAM)
    • Docker Desktop (Kubernetes enabled), VS Code, Chrome
  • Let's note CF-SZ6 (第7世代 Core i5 / 8GB RAM)
    • Slack, Scrapbox, Twitter
  • iPad Air2
    • Zoom, YouTube, etc.

Electron アプリのリソース使用量もばかにならないため MacBook では極力起動しないようにしました。iPad はデスク横にマウントしっぱなしです。

f:id:kondoumh:20200723095621j:plain

2020.08.09 追記)

その後 iPad Pro 2018 を導入し、MacBook Pro は完全に 開発用のリモートマシンになりました。Let's note CF-SZ6 を作業用マシンにして VS Code Remote SSH と Windows Terminal で MacBook Pro に接続してます。

  • MacBook Pro 2015 (第4世代 Corei 7 / 16GB RAM)
    • Docker Desktop (Kubernetes enabled), 開発環境
  • Let's note CF-SZ6 (第7世代 Core i5 / 8GB RAM)
    • Chrome, VS Code, Windows Terminal, 自作 Electron アプリ
  • iPad Pro 2018
    • Zoom, YouTube, Slack etc.

ラップトップはクラムシェルで使ってサイドに置くようにして机の上が少しすっきり。

f:id:kondoumh:20200809164447j:plain

(追記終わり)

MacBook Pro 買った時は1台で全て賄えるのがいいと思っていました。

blog.kondoumh.com

在宅作業が長くなり、いろんなタスクをこなすことを考えるとこのスタイルもありかなあと思います。プロセス起動や切り替えによる CPU・メモリのスパイクも減らせますし。YouTube とか Twitter などがメイン画面を占有せず流し見できるのもよい気がします。

ところで Kubernetes 使う Cloud Native 世代の開発環境を構築するために PC をリニューアルしたくなってきました。

MacBook Pro 13 2020 よさそうだけど持ち歩くことがないなら割高に感じる。Mac mini はまだ Intel 第8世代でデスクトップ向け Processor 積んでない。利用アプリや開発環境構築の楽さではまだ macOS がいいんだけど・・。

PC 買うなら AMD Ryzen のコストパフォーマンスがいい。最低 6 Core (12 thread) 、メモリ32MB は欲しいところ。できれば 8 Core (16 thread) メモリ 64GB を狙いたい。しかしWindows 10 + WSL2 で yak shaving するのめんどくさいし Linux 専用機にする?・・いずれにしても発熱・騒音・電気代を考えると腰が引ける・・。

などなど悩み中です。

GitBook から HonKit に移行する

iEdit のユーザーズガイド

iedit.kondoumh.com

GitBook で作ってました。

blog.kondoumh.com

今年の2月に動作環境の文言を修正しようとして久々に更新した時 gitbook-cli が Deplicated になっているのに気付きました。

GitBook.com のホスティングサービス専用になって、OSS の方はメンテされなくなった模様です。

www.gitbook.com

ユーザーズガイドは GitHub Pages で公開していますが、今後 メンテされないとなると新規のドキュメントには使わない方がいいなあと思っていました。

最近 azu さんが GitBook を fork した HonKit という OSS の開発を開始されました。

github.com

自分はGitBook(legacy)の機能的にはある程度満足していたので、 主にコードベースの整理、TypeScript化、QやjQueryの依存を外すなど質的なメンテナンスが中心になる気がしています。

efcl.info

TypeScript 化や jQuery 依存の除去などは今後メンテナンスを続け、Contribute しやすくなるメリットがあると思います。

iEdit のドキュメントを HonKit でビルドしてアップデートしました。NPM 管理には移行していたので、gitbook-cli を honkit に置き換えて、script で使用するコマンドを gitbook -> honkit に変更するだけで移行完了。利用しているプラグインはそのまま動作しました。

  "devDependencies": {
-   "gitbook-cli": "^2.3.2"
+   "honkit": "^3.4.0"
  },
  "scripts": {
-   "serve": "gitbook serve",
-   "build": "gitbook build ./ ./docs"
+   "serve": "honkit serve",
+   "build": "honkit build ./ ./docs"
  },

HonKit を使えば、既存の GitBook 資産を Netlify や GitHub Pages などで安心してホスティングできるので、何より既存 GitBook ユーザには朗報ですね。

Blazor WebAssembly を触る

先月 Blazor WebAssembly 3.2.0 がリリースされ、.NET Core 3.1.300 以降にアップデートすることで使用できるようになりました。

devblogs.microsoft.com

すでに Infragistics など著名な UI コンポーネントベンダーが対応しておりプロダクションレディな感じが漂っています。

WebAssembly 上に .NET CLR が実装され、Client と Server で共通の C# コードが動き、ASP.NET Core の要領でモダンな Web UI が作れるという、なんだかすごいフレームワークに興味津々で .NET Core を更新。

dotnet.microsoft.com

前回インストールして試してから1年近く経ってました。

blog.kondoumh.com

ブログにあるようにコマンドを実行。

f:id:kondoumh:20200618103342p:plain

localhost:5001 にアクセスすると、素敵な Webアプリが表示されます。

f:id:kondoumh:20200618104023p:plain

f:id:kondoumh:20200618104307p:plain

f:id:kondoumh:20200618104331p:plain

プロジェクトのファイルを覗くと ASP.NET MVC の Razor 構文に似たテンプレートと C# コードでできてます。

開発の雰囲気を掴むために、このアプリに何かページを追加してみます。

GitHub に ASP.NET Core Blazer の Extension が公開されてます。

github.com

Canvas では 2D グラフィックスや WebGL のレンダリングがサポートされてます。

github.com

これを使って Canvas に描画する Page を追加しようってことで dotnet add package を実行し Canvas 拡張を追加。

f:id:kondoumh:20200618123947p:plain

index.html に必要な JS ライブラリを追加。

<body>
    <app>Loading...</app>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="_content/Blazor.Extensions.Canvas/blazor.extensions.canvas.js"></script>
</body>

README に従って page (Canvas2D.razor) を追加

@page "/canvas2d"

<h1>Canvas 2D</h1>

<BECanvas Width="300" Height="400" @ref="_canvasReference" ></BECanvas>

@code {
    @using Blazor.Extensions
    @using Blazor.Extensions.Canvas
    @using Blazor.Extensions.Canvas.Canvas2D

    private Canvas2DContext _context;

    protected BECanvasComponent _canvasReference;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        this._context = await this._canvasReference.CreateCanvas2DAsync();
        await this._context.SetFillStyleAsync("green");

        await this._context.FillRectAsync(10, 100, 100, 100);

        await this._context.SetFontAsync("48px serif");
        await this._context.StrokeTextAsync("Hello Blazor!!!", 10, 100);
    }
}

Navigation に page を追加。iconify のアイコンを指定できるようです。

https://iconify.design/icon-sets/oi/

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">BlazorApp1</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
             :
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="canvas2d">
                <span class="oi oi-map" aria-hidden="true"></span> Canvas 2D
            </NavLink>
        </li>
    </ul>
</div>

@code {
    private bool collapseNavMenu = true;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

そして、dotnet run するとなんか出ました。

f:id:kondoumh:20200618125927p:plain

次に、WebGL グラフィックスを描画するサンプルです。こちらのテストプロジェクトからコードを持ってきました。

Canvas/test/Blazor.Extensions.Canvas.Test.ClientSide/Pages at master · BlazorExtensions/Canvas · GitHub

テストプロジェクト通りに razor ファイルと cs ファイルを分離して @inherits を使って書いてみたのですが、cs 側で持ってる BECanvasComponent 型のフィールドを暗黙型変換できないというエラーが解消できませんでした。仕方なく Canvas 2D 同様 razor の @code ブロックに直書きしました。

なんか出ました。

f:id:kondoumh:20200618214213p:plain

C# と Razor のコードしか書いてないので、昔ながらの ASP.NET MVC 開発の感覚になります。React や Vue でおなじみの Live Reloading 機能はまだないらしく、ファイルを編集したら Ctrl-C で中断し再び dotnet run してブラウザ側を更新・・というちょっとめんどくさいワークフローになってます*1

VS Code を当然使ってるわけですが、C# 拡張の他にデバッグのため JavaScript Debugger (Nightly) を導入することが推奨されています。

marketplace.visualstudio.com

launch.json の設定をして、デバッグ用の Chrome が起動したのですが、僕の環境ではブレークポイントで実行が止まってくれませんでした。

今回のお試しコード

dotnetcore-study/BlazorApp1 at master · kondoumh/dotnetcore-study · GitHub

Blazor アプリのホスティングモデルの説明を読むとブラウザで完結する Blazor WebAssembly モデルとBlazor サーバーモデルがあり、今回見たのは Blazor WebAssembly の方です。Blazor サーバーは、ASP.NET Core アプリで WASM が実行され、ブラウザと SignalR で通信します。Blazor サーバーモデルではブラウザが WASM 対応している必要はないようです。Blazor WASM モデルだと規模が大きくなってくると、ダウンロードやローディングの時間が気になるレベルになりそうです。

docs.microsoft.com

今回初めて触りましたが完成度高い感じしました。WASM を基盤としているため Silverlight のようなプラグインが不要なのと、まんま ASP.NET のプログラミングモデルということで C#er には受け入れられやすい気がします。

*1:やり方を知らないだけという可能性はあります。

Scrapbox ページ一覧と Graph 可視化のプロト PWA 作成

以前 Scrapbox から API でデータを取得して、ページ間リンクを可視化する (ための Graphviz dot ファイルを吐く) CLI を作成しました。

blog.kondoumh.com

その後 Graphviz よりインタラクティブな可視化ができる技術として D3.js の force simulation を使ったサンプルを作ってました。

まだ色々改善ポイントありますが、ひとまず動いてます。

野良 Scrapbox アプリでは、ページ一覧を作っています。

github.com

これらの機能を PWA にしてモバイルからも閲覧できるようにしたいと思い、プロトタイプの PWA を作りました。

sb-data-kondoumh.netlify.app

Scrapbox の API は CORS を許可してないのでビルド時にデータ取得してアプリと一緒にデプロイしてます。

一覧画面。野良 Scrapbox アプリと違ってクエリについての制約がなくなったので検索機能とか追加してます。

f:id:kondoumh:20200610222921p:plain

Home と Full List に同じ一覧画面があるのですが、これは Home で最新の更新情報を短いタイムスパンで、Full List で全ページの情報を比較的長めのタイムスパンで更新することを想定しているためです。

Graph 表示画面。D3.js の画面を無理やり Vue.js のコンポーネントにして表示してます。

f:id:kondoumh:20200610223306p:plain

About 画面は使用しているテクノロジースタックのリンク集になっています。

f:id:kondoumh:20200610223359p:plain

久々に Vue CLI で PWA をやってみましたが、iPadOS も PWA サポートが進んでます。以前は起動すると Safari のタブが開くだけだったのが、アプリっぽく動くようになりました*1

f:id:kondoumh:20200610230437j:plain

プラットフォーム側の対応が進んでいるのを感じます。

*1:このスクリーンショットは夜間に撮ったのでダークモードになってます。

ThinkPad TrackPoint Keyboard II 購入

今年初めに ThinkPad TrackPoint Keyboard のワイヤレス専用版がリニューアルされ Bluetooth に加えてワイヤレス USB 接続をサポートしました。そして先月 JP 版が発売になりました。

www.lenovo.com

昔 ThinkPad やスペースセーバーキーボードのユーザだったというのもあるのですが、ちょうど自宅でテレワーク用の端末と MacBook Pro で HHKB と Magic Keyboard の2台を取り替えて使ってるのが煩雑だったので、1台に統合できるならということで買ってみました。もちろん JP 配列です。

ThinkPad のキーボードらしくキートップの下側に R が入ってます。近年のモデルにあるタッチパッドも省かれているためコンパクトです。クリックボタンの左右がちょっとしたパームレストにもなります。

f:id:kondoumh:20200605083509j:plain

上部側面に Bluteooth - ワイヤレスの切り替えスイッチ、Windows と Android の切り替えスイッチ、充電用の USB-C ポート、ワイヤレスのドングル格納ソケットが配置されています。電源スイッチは右側面にあります。チルトスタンドは使った方が打ちやすい気がします。

f:id:kondoumh:20200605084818j:plain

軽量薄型キーボードとしてはストロークもそれなりにあって打ちやすいです。慣れれば Magic Keyboard よりいいかなと。

キー配列はコンパクトな JP キーボードとしてはまあ標準的です。Windows ではたまに使う Home と End がファンクションキーの並びにあるのはよいと思いました。しかし、右 Alt と Ctrl の間にねじ込まれている PrtSc は使わないので省いてピッチを広げて欲しかったですね。さらに PgUp/PgDn が左右カーソルキーのすぐ上に配置されているため、誤タイプでページングしてしまいびっくりします。ほぼ使わないので Fn のコンビネーションでいいと思いました。後述のようにリマップツールでカーソルキーにマッピングしちゃいました。

TrackPoint は専用のドライバーソフトウェアを導入しなくても Windwos / macOS 共に動作しました。ThinkPad X40 を使ってた頃はドームタイプのキャップを沢山ストックしてたりしましたが、今時は TrackPoint だけで頑張るのはつらいのでマウスや Trackpad と併用します。ホームポジションのままカーソルを動かせるのはやはりいいですね。

macOS では Karabiner-Elements でキーリマップしました。

HHKB でも使ってるやつです。

blog.kondoumh.com

Windows キーボードの共通設定。

f:id:kondoumh:20200607181302p:plain

TrackPoint Keyboard 固有の設定。

f:id:kondoumh:20200607181325p:plain

Windows では KeySwap を使いました。

KeySwap for XPの詳細情報 : Vector ソフトを探す!

かなり昔からあるレジストリ変更してキーマップを変えてしまうツールです。

f:id:kondoumh:20200607141657p:plain

もうちょいモダンなツールないかなとは思うのですが。

ともあれ、打ちやすいコンパクトキーボード1個で環境を切り替えられるようになったので満足しています。