Reduce GitHub actions workflow duration using brew on macOS runner

This article is based on my own experiences, and it can not be best way. So please comment and share something you find.

TL;DR

  • Skip brew update if possible
  • Use HOMEBREW_NO_AUTO_UPDATE to skip automatically update in brew install
  • Use HOMEBREW_NO_INSTALL_CLEANUP to skip automatically clean up in brew install
  • actions/cache cannot reduce duration so much, sometimes increase

Details

update

  • Most of duration seems used for updating, so it is important to skip that
  • Of course it can occur side effects, you have to consider
  • It is not enough to skip brew update for skipping update completely
  • Use HOMEBREW_NO_AUTO_UPDATE to skip automatically update in brew install
    • Specify as environment variable in step using brew install
      env:
        HOMEBREW_NO_AUTO_UPDATE: 1

or

      run: HOMEBREW_NO_AUTO_UPDATE=1 brew install foobar

cache

  • actions/cache provides system to cache and restore directory tree
  • But there are some difficulties to cache brew artifacts
    • Modules installed by brew don't exist in unified dir tree, so it is difficult to cache them
      • If you can defeat difficulties and cache installed modules completely, it can reduce duration so much
    • Download cache dir is usually ~/Library/Caches/Homebrew
      • It can skip downloading if cache that directory, but it doesn't reduce duration so much or it sometimes increases duration
      • It takes a few minutes to restore cache
      • It is better to call brew cleanup -s for shrink cache size, but it takes a few minutes

tap

  • I have not investigated enough, but it may make little effect tobrew untap unnecessary pre-installed taps
    • Because it may caused already skipping update

Something felt

constexpr function で引数を unused にする

  • bool を返す constexpr function
  • 互換性の関係で引数を省略できない
  • 実装的には、引数は使用せず常に false を返す
  • C++11 の constexpr function なので (void)param; を置いて回避する手は使えない
  • Doxygen に怒られるので仮引数の型だけ残して仮引数をコメントアウトする手は使えない

という条件でどうやって compiler, Doxygen, cppcheck の警告を完全回避できるんだ…と思ったんだが、 世の中には同じことを既に解決している人が既に居た。

stackoverflow.com

constexpr bool isfoo(int param) {
  return (void)param, false;
}

なるほど…。 constexpr function で , 演算子を使うのは当たり前にやってるけど、 このケースで組み合わせるのは思い付かなかった…。

2020私的5大ニュース

【第1位】頸椎椎間板ヘルニア & 変形性頚椎症

まぁ、今年はこれに振り回されました。 春先から左肩〜肘〜手首〜親指にかけて痛みとしびれがあって、 COVID-19とかもあってだましだまし過ごしてたのですが、 7月に思い切って整形外科へ行って判明。 投薬、カラーによる固定、リハビリを併用して、 おかげさまで今は週1くらいでしびれが出るのと 首を大きく後ろに反らせたときに左上腕に痛みが出る以外は 日常は特に何も不自由なく過ごせてます。

【第2位】 3度コケる

歳のせいだとは思いたくないのですが…。

1度目は旅先の福井一乗谷朝倉氏遺跡にて、 雪解け水で濡れた石階段に滑って尻もち。

2度目は1度目の直後、 あまりに恥ずかしくて早々に立ち去ろうとして 今度は前にコケて額を強打。 これでカメラがイカれました(滝涙)。 額から血が少しにじむ状態で一乗谷朝倉氏遺跡資料館へ行ったのですが、 受付の方が気づいてカットバンとか下さった優しさは忘れてません。

3度目は実家近くにて。 この交差点 goo.gl を小走りで渡ったところで アスファルトがコブになってるところに躓いて 手のひらと肘を結構すりむく。 いやー、いつもは転びそうになっても踏ん張れる人なんですが、 このときは踏ん張ろうとしたせいでかえって勢いついて 派手にコケてしまいました、 久々に宙に浮いてBotWばりにスローモーションになりましたよw この交差点はストリートビューで見ると分かりますが 国道と市道それぞれ片側1車線の交差点なんですが、 市道側の10m先に踏切があるのと 数十m離れたところに信号があるので、 信号がないんですよね。 国道側は久喜-騎西-加須-羽生-館林-太田あたりを繋ぐ 主要道路の一つで結構な交通量ですし、 市道側も千代田町邑楽町大泉町あたりへ抜ける道 かつ太田方面への迂回路にもなってるのでそこそこの交通量。 なので間隙をついて小走りで渡ったのが良くなかったのかな…。

【第3位】 某ゲームで英語 alliance に加盟

某海外製のゲームやっててUIの日本語翻訳がいまいちで英語モードを使ってたんですが、 その流れで見ず知らずの英語の alliance に加盟してみました。 ロンドンあたりの連中が中心、 ピークタイムが大きくズレてるのですが、 まぁ別に普通に必要なコミュニケーションはとれてます。 でもやっぱりくだけた英語を使ってる native 同士のやり取りは「??」ってなることが多いですね…。 私自身はおかげさまでビジネス英語とか技術英語の読み書きは何とかできるし、 話す・聞くはすぐには上達しないのでそこはともかくとして…。 読み書きだけでもこなれた英語とかくだけた英語とかが使えるようになって チャットだけでももう少し上達したいのですが、 道は険しそうです。 ちなみにゲームの alliance というと身内ばっかりの閉鎖的なところか、 ビジネス以上にビジネスライクにゲームしてる連中の寄り合いみたいなところが多いと思うのですが、 自分の今いるところは日常の話とか 「いま子供とモノポリーやっててちょっと中座してきたんだけど その間に何かズルするんじゃないかと気が気じゃないw」 みたいな割と他愛のない会話してて居心地よいです。

【第4位】 歯が折れる & 抜歯デビュー

正直いつ折れたのか分からないのですが、 正月明けたぶんジャンボコーンを食べてたときだと思うんだな…。 「奥歯がギザついてて舌に触るな…」 と思って歯医者に行ったら 「おそらく虫歯になってたところから折れましたねー、 神経に割と近いところです」 と。もうこの際だからと親知らず抜歯も含めて 3ヶ月くらい通って悪いところ全部直してもらいました。

【第5位】 突然20%痩せる

特にダイエットとか意識もしてなかったんですが、 去年の今頃のピークに太かったときから比べて20%くらい痩せました。 影響してそうなのは

  • テレワークで3食自炊になった
  • 夕食が早くなった

くらいなのですが…。 ちなみに1年で20%ではなく、 今年の前半で一気に痩せて夏以降は停滞ですね…。

Windows 向けの GitHub Actions で PATH を通すとき

はじめに

TL;DR

  • 普通の Windows 形式のパスなら何も考えずに $GITHUB_PATH のファイルに追記すれば OK
    • 例(shell: pwsh の場合): echo C:\Users\foo\bar >> $Env:GITHUB_PATH
  • ホームディレクトリ以下を指定したい場合は (Resolve-Path ~\bar\).Path >> $Env:GITHUB_PATH とかすれば OK
  • Windows 形式、 cygwin 形式どっちが必要かわからなくても Windows 形式で足しておけば問題ない

バックグラウンド

GitHub Actions での環境変数周辺

PowerShell の事情

  • コマンドプロンプトと違って ~ とか使える
  • だけど echo ~\scoop\shims >> $Env:GITHUB_PATHとかすると~` の解決がされずにそのままファイルに追記されてしまう
    • ちゃんと確認してないけど ~ の状態じゃパスが通ってない扱いになる?
  • この辺のパス解決をさせるには (Resolve-Path ~\scoop\shims).Path とかすればいい
  • PowerShell では cygwin 形式のパスを PATH に設定しても効果がない

shell:bash on Windows での事情

というわけで、全部合わせると…

PowerShell (shell: pwsh) で解決する場合

(Resolve-Path ~/scoop/shims).Path >> $Env:GITHUB

bash (shell: bash) で解決する場合

cygpath ~/scoop/shims >> $GITHUB_PATH
  • bashpwshWindows 形式のパスを受け付けるのでそちらに統一してしまうのが良さそう
  • bash でしか使わないなら echo ~/scoop/shims >> $GITHUB_PATH でも良さそう (だけどあえてそうする理由もなさそう)
  • 今回私が遭遇したケースは PowerShellscoop をインストールした前提なので、普通にそのまま続けて PowerShellResolve-Path 使います

所感

  • そもそも何がイケなかったって「 shell: の違いを吸収して Windows <-> cygwin のパス変換」をやってくれるという錯覚を起こしたんですよね…それさえなければこんなにはハマらなかった気がする (という自己擁護)

Preview in plantuml-mode on macOS Emacs

I encountered 2 issues to preview in plantuml-mode on macOS Emacs. I resolved them but please tell me if you have better solution.

TL;DR

  • Upgrade your Java runtime to resolve CoreText warnings to stdout
  • Disable headless option
    • For plantuml-mode example
(setq plantuml-default-exec-mode 'jar)
(with-eval-after-load 'plantuml
  (setq plantuml-java-args
    (delete "-Djava.awt.headless=true" plantuml-java-args)))

Issues

  • There are 2 issues I encountered when using preview (C-c C-c) in plantuml-mode

Preview corruption

Cause
Solution
  • It has been resolved later version of Java runtime, so it can be solution to upgrade your Java environment
    • If you installed openjdk with brew, you can use brew upgrade openjdk
    • You have to consider because it may cause seemingly unrelated issue by upgrading your Java environment

headless exception

Information
Workaround
  • Disable passing -headless option to plantuml
    • plantuml-mode passes it to plantuml as default, so disable it
      • One of examples to disable it, put the codes at TL;DR into your Emacs configuration file
(setq plantuml-default-exec-mode 'jar)
(with-eval-after-load 'plantuml
  (setq plantuml-java-args
    (delete "-Djava.awt.headless=true" plantuml-java-args)))
  • If using via plantuml command, add -gui option
    • plantuml command automatically adds -Djava.awt.headless=true if -gui is not specified

scoop でインストールした plantuml と plantuml-mode on Emacs でプレビューできない件

  • Windows
  • scoop でインストールした plantuml
  • Emacs の plantuml-mode
    • http://plantuml.com/ のオンライン変換を使うのではなく、以下のような設定でローカルで変換する
  (setq plantuml-executable-path (executable-find "plantuml"))
  (setq plantuml-default-exec-mode 'executable)

というケースで C-c C-c とかすると文字化けバッファが表示される。

Warning: -headless flag must be the first one in the command line

ってなのが最初についててその後ろに画像データがくっついているので、 Emacs が画像とみなさないようだ。

本質的には、 「画像も warning も同じ標準出力に出している」 と思われる plantuml に非があると推測するが、 Emacs の設定からどうコマンドラインオプションを指定しても どうしてもこの warning が消せない。

プレビュー機能を諦めて2ヶ月くらい放置してたんだが、 今日たまたま

(executable-path "plantuml")

とかしてて plantuml.cmd の中身を見てて原因がわかった。 scoop が作る plantuml.cmd は graphviz の dot のパスをコマンドラインオプションで plantuml.jar へ渡すようになってて、 plantuml.cmd に対して指定したコマンドラインオプションは必ずその後ろに付加される書き方になってる。 だから、この問題は plantuml.cmd の外側 ≒ Emacs plantuml-mode の設定 では解決できないんだ。

なので、plantuml.cmd でこう↓なっているのを

@java -jar "D:\Users\mino\scoop\apps\plantuml\1.2020.19\plantuml.jar" -graphvizdot "D:\Users\mino\scoop\shims\dot.exe" %*

こうしてしまえば warning は出なくなる。

@java -jar "D:\Users\mino\scoop\apps\plantuml\1.2020.19\plantuml.jar" %* -graphvizdot "D:\Users\mino\scoop\shims\dot.exe"

ひとまず解決したのは良かったけど、まぁ釈然とはしないなぁ…w

あ、一応この plantuml.cmd を生成してる scoop extras bucket の修正 PR は出しておきました。 個人的には解決しちゃったので、マージされなくてもちっとも困らないんですが、 今後ハマる人が少しでも少なくなれば。

emacs --daemon + emacsclient で起動したときも、daemon 使わず起動したときも期待通りの設定で動くようにする (途中)

途中なんだけどメモっておかないと忘れるので。

やりたいことは…

  • Emacs の起動高速化したい、 emacs --daemon が使えそう
  • 今すでにある「環境によらず同じ初期化ファイル」というのはキープしたい
  • emacs --daemon + emacsclient も、単に emacs を起動しても動くようにしたい
  • text terminal で emacs -nw で起動した場合も、GUIで起動した場合も動くようにしたいが、それぞれで見た目とか設定を変えたい可能性もある

↑こんな感じ。

で、こんなの↓を作ってみて

github.com

それでわかった?ことは…

  • emacs --daemon で初期化ファイルを読み込んだときは window-systemnil なので一部設定ができない
  • emacsclient で起動したときに設定を遅延すればよくて使えそうな hook が after-make-frame-hook
  • daemon 使用時と非使用時(普通に emacs 起動したとき)で初期化ファイルを共有するためには…
    • GUI 設定を関数にまとめとく
    • その関数を after-make-frame-hook にひっかけておく
    • when (window-system) のときは hook が呼ばれるのを待たずにその関数を呼んじゃう
    • これだけだとフレーム作るたびに関数が呼ばれるので、関数の最後で自分自身を remove-hook しとく
  • after-make-frame-hook は frame 生成後に呼ばれるので default-frame-alist とかをそこで設定しても frame には反映されない?
    • とりあえず (modify-frame-parameters (selected-frame) default-frame-alist) 的なことをすれば解決はできそう

まぁ、何が言いたいかというと、 emacs --daemon がもうちょっと使いやすいと嬉しい、と。