GitHub Actions で Perl を動かすときのテンプレート

この記事は Perl Advent Calendar 2020 の14日目のものです。

最近、久しぶりに Perl のリポジトリをメンテする中で Travis CI から GitHub Actions に載せ替えたので、そのときに整理した Perl で GitHub Actions を使うときのテンプレを紹介します。 それだけだと量が微妙な気がしたため Actions の一部を切り出してみた話も書きます。

テンプレート

Carton を使用する場合のテンプレです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
name: test

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
test:
name: Run Test with Perl ${{ matrix.perl }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
perl:
- '5.30'
- '5.32'
steps:
- uses: actions/checkout@v2
- name: Setup perl
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: ${{ matrix.perl }}
- name: Cache local files
uses: actions/cache@v2
with:
path: ./local
key: ${{ runner.os }}-perl-${{ matrix.perl }}-${{ hashFiles('./cpanfile.snapshot') }}
- name: Coveralls
uses: mihyaeru21/actions-report-coveralls-perl@v1
with:
flag-name: perl-${{ matrix.perl }}
- run: carton install
- name: Run tests
env:
HARNESS_PERL_SWITCHES: '-MDevel::Cover=+ignore,^local/|^t/'
run: carton exec -- prove -lrv t

やっていることを箇条書すると以下のような感じです。

  • 複数のバージョンの Perl で実行する
    • fail-fast が true だと1つのバージョンで失敗したときに CI 全体が止まる
    • 独立して動かしたかったからこれは false にする
  • 依存モジュールをキャッシュする
    • 依存モジュールは OS x Perl バージョン x snapshot をキーにして独立させる
  • Coveralls にカバレッジを投げる

Actions に切り出す

もともとは、カバレッジに関するモジュールである Devel::Cover::Report::CoverallsDevel::Cover を cpanfile の on 'test' として追加していましたが、あらためて考えたらこれらは CI でしか使わないものだったので開発環境に入れる必要はありませんでした。 GitHub Actions の共通のやつを何か作ってみたかったので、インストールしたりカバレッジを送信する部分を切り出すという小粒なネタはちょうどよかったです。

作ったのは https://github.com/mihyaeru21/actions-report-coveralls-perl です。 こいつは以下のことをします。

  • uses を書いたステップで Devel::Cover::Report::Coveralls をインストールする
  • 通常のステップがすべて終了した後のタイミングでカバレッジデータを送信する

ぶっちゃけ CI 設定の yaml が数行短くなって、カバレッジに関する依存を明示しなくてよくなるだけなので自己満足感は否めないです😇

やり残し

インストールする部分を毎回実行するのが無駄なのでいい感じに cache できればなーと考えています。

最後に

切り出すやつを作る上では Perl というより TypeScript を書くことになりました。 Perl については CI というか Actions でどこまで面倒を見るのか調べる過程で prove が標準モジュールなのをいまさらながら知りました。 そして自分が Perl から離れている間に Test2 という新しいテストのフレームワークが出てきていることを知り、 Perl の進化がまだまだ止まっていないことを実感しました。

Windows 起動時に WSL2 の環境への ssh 設定を自動でするやつ

やりかた

以下のコードを setup-ssh.bat とかの名前で好きな場所に置き、

1
2
3
4
5
wsl -d Ubuntu -u root exec service ssh restart

for /F %%i in ('wsl -d Ubuntu exec hostname -I') do set ip=%%i
netsh interface portproxy delete v4tov4 listenport=22
netsh interface portproxy add v4tov4 listenport=22 connectaddress=%ip%

タスクスケジューラにて以下の設定でタスクを追加しておけばOKです。

  • 全般
    • 最上位の特権で実行する: on
  • トリガー
    • タスクの開始: ログオン時
    • 遅延時間を指定する: 30秒間
  • 操作
    • 操作: プログラムの開始
    • プログラム/スクリプト: 上記のファイルを置いたパス

メモ

参考にした Qiita 記事の方法だと WSL2 内にもファイルを置かないといけなかったため、その記事のコメント欄にあった方法を参考に Windows 側だけで実行したら良いようにしました。さらに WSL2 内の sshd も自動で起動してほしかったので、そのコマンドも追加してあります。

参考

WSL2で外部からssh接続 - Qiita

jellybeans を設定するぞ

Vim の jellybeans という colorscheme 設定をちょっといじったからメモ。
Vim といっても実際に使ってるのは Neovim。

色を良い感じにする

長い間この colorscheme を使っていたのに最近までちゃんと認識していなかった事象として GVim や MacVim で表示したときと iTerm や Alacritty のターミナルエミュレータで表示したときとで微妙に色が違うというのがあった。
これは jellybeans の仕様で、フルカラーの場合とそれ以外の色が少ない場合の両方に対応しているから。
色の設定自体はフルカラーでやっていて、それを256色とかに減色してる。
ターミナル側が対応していれば↓を設定すればOK。

1
set termguicolors

tmux を使っている場合は tmux 側の設定にて↓もやっとく。
参考: https://qiita.com/yami_beta/items/ef535d3458addd2e8fbb

1
2
set-option -g default-terminal screen-256color
set-option -ga terminal-overrides ",xterm-256color:Tc"

背景を透過する

ターミナルで背景を透過させても Vim を起動すると透過されないのが急に気になりはじめて調べてみたら対処する方法が README に載ってたから設定した。

1
2
3
4
5
6
let g:jellybeans_overrides = {
\ 'background': { 'ctermbg': 'none', '256ctermbg': 'none' },
\}
if has('termguicolors') && &termguicolors
let g:jellybeans_overrides['background']['guibg'] = 'none'
endif

✌️

これで良い感じに透過するようになった。

Ubuntu で notify-rust を使おうとしたらエラーになった

Rust から OS の通知を使ってみようと思って notify-rust を動かそうとしたらエラーが出たのに対処したメモ。
発生したエラーは以下のやつ。(/home/mihyaeru/tmp/notification はプロジェクトディレクトリ)

1
2
3
4
5
6
7
8
$ cargo build
Compiling libdbus-sys v0.2.1
error: failed to run custom build command for `libdbus-sys v0.2.1`

Caused by:
process didn't exit successfully: `/home/mihyaeru/tmp/notification/target/debug/build/libdbus-sys-bb7c2267590697eb/build-script-build` (exit code: 101)
--- stderrthread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Failure { command: "\"pkg-config\" \"--libs\" \"--cflags\" \"dbus-1\" \"dbus-1 >= 1.6\"", output: Output { status: ExitStatus(ExitStatus(256)), stdout: "", stderr: "Package dbus-1 was not found in the pkg-config search path.\nPerhaps you should add the directory containing `dbus-1.pc\'\nto the PKG_CONFIG_PATH environment variable\nNo package \'dbus-1\' found\nPackage dbus-1 was not found in the pkg-config search path.\nPerhaps you should add the directory containing `dbus-1.pc\'\nto the PKG_CONFIG_PATH environment variable\nNo package \'dbus-1\' found\n" } }', src/libcore/result.rs:1084:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

↓も確かにエラーになる。

1
2
3
4
5
$ pkg-config --libs --cflags dbus-1
Package dbus-1 was not found in the pkg-config search path.
Perhaps you should add the directory containing `dbus-1.pc'
to the PKG_CONFIG_PATH environment variable
No package 'dbus-1' found

dbus って何だろう?と思って調べたら Unix 系の OS で IPC するやつだった。
notify-rust の依存ライブラリの dbus-rs が出力しているエラーで、 libdbus-1-dev というパッケージを入れる必要があった。
以下で入れたら通るようになった。

1
$ sudo apt install libdbus-1-dev

もちろん pkg-config の方も。

1
2
$ pkg-config --libs --cflags dbus-1
-I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -ldbus-1

このライブラリを使うとめっちゃ簡単にデスクトップの通知を投げられて便利っぽい。

Rails でどこでも after_commit したい話

この記事は裏freee developers Advent Calendar 2018の16日目の記事です。 裏感なく普通にtips的な内容です。


ありがち?なバグ

かなり大雑把に表現すると↓のようなコードがありました。 do_something1 で新しく Model を作ったり更新したりしたあと、最終的な状態に基づいてメールを送信するという具合です(記事中の Model という言葉は ActiveRecord で表現される app/models 以下のやつらを指します)。 send_email は内部で ResqueMailer に処理を投げています。 do_something1 の部分で操作した Model をidベースで Mailer に渡し、Mailer 側ではidを使って取得するようになっています。

1
2
3
4
5
6
7
8
9
10
11
class Hoge
def exec
ActiveRecord::Base.transaction do
do_something1
send_email(model.id)
do_something2
end
end
end

Hoge.new.exec

do_something2 の処理が完了する前(=トランザクションがコミットされる前)に Mailer の処理が動いてしまうと、古い状態の Model が見えてしまったり、存在しない Model を取得しようとしてエラーになってしまいます。

ちょいちょい発生していたエラーを追っていたら、以上のような構造になっていました。

シュっと対応

トランザクションがコミットされる前に Resque 経由で Mailer が動いてしまうことが問題なので Resque に積むタイミングをトランザクションがコミットされた後にすれば解決します。(この例の場合なら do_something2 の位置をずらせばほぼ解決ですが)

1
2
3
4
5
6
7
8
9
10
11
12
class Hoge
def exec
ActiveRecord::Base.transaction do
do_something1
do_something2
end

send_email(model.id)
end
end

Hoge.new.exec

めでたしめでたし……?

ダメじゃん

これではダメです。 次のように ActiveRecord::Base.transaction がネストしているケースで問題が発生します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Hoge
def exec
ActiveRecord::Base.transaction do
do_something1
do_something2
end

send_email(model.id)
end
end

class Fuga
def exec
ActiveRecord::Base.transaction do
do_fuga1
Hoge.new.exec
do_fuga2
end
end
end

Fuga.new.exec

実際のDBのトランザクションは Fuga 側のブロックの終わりにコミットされるため、トランザクションの外に追いやったはずの send_email がトランザクションの中残ったままになってしまっています。

after_commit が使えれば良いのですが、 after_commit は ActiveRecord のコールバックなので Model 以外では使えません。 Perl を書いていたときに使った DBIx::TransactionManager::EndHook を思い出し、それっぽいのものがないのかを探しました。

after_commit_everywhere

この記事を見つけ、そのコメント中で宣伝されていた after_commit_everywhere という Gem がインタフェース的にまさに欲しかったものでした。 中身を読んでみたところかなりコンパクトで、いざとなったらまるまるメンテできそうで安心したので採用しました。

after_commit_everywhere を使用して書き直すと以下のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Hoge
include AfterCommitEverywhere

def exec
ActiveRecord::Base.transaction do
do_something1

after_commit do
send_email(model.id)
end

do_something2
end
end
end

class Fuga
def exec
ActiveRecord::Base.transaction do
do_fuga1
Hoge.new.exec
do_fuga2
end
end
end

Fuga.new.exec

これで Hoge が意図せずトランザクションの中で実行されたとしても send_email はコミットされた後に実行され、 Mailer が処理を行う時点で最新の Model を取得できるようになりました。

終わりに

多くのケースでは ActiveRecord のコールバックを普通に使えば十分ですが、たまに ActiveRecord ではない部分でもコミットをトリガーとして処理を実行したくなるかと思います。 使いすぎると可読性がヤバいことになりそうなのでご利用は計画的に。


明日17日はyo_wakaによる新作発表らしいです。お楽しみに。

ブログをConoHaからS3に移動しました

ホストの引っ越しついでにDark Advent Calendar 2017の23日目の記事です。 余裕の遅刻です。

概要

ConoHa VPSからS3+CloudFrontに引っ越しました。

発端というか愚痴

ConoHaの運営から以下のメールが来ました(一部抜粋)。
Twitterを検索すると、似たようなメールが来て止められている事案がちらほらあるようです。

1
2
3
4
5
6
7
8
9
10
上記IPアドレスにてご利用のVPSにつきまして、CPUの使用率が
高い状況が継続しております。

一時的なものであれば問題ございませんが、継続する場合、
収容ホストへの負荷影響や、他のお客様への影響が懸念されます。

そのため、大変恐縮ではございますが、該当VPSのシャットダウンを
実施させていただきました。

なお、ご運用状況の見直しもご検討くださいますと幸いです。

半年くらい前から1GBと2GBの2つのプランのVPSでマイニングをしていました。 CPU使用率がほぼ0%だとこちらが損だったので出来る限り使っておきたかった、かつ変なコインが欲しかったのもあり、採算度外視で掘り始めました。
2GBの方は blog.mihyaeru.com を運用していたサーバーです。 1GBの方は、もうちょっと掘りたくなったので2GBの方で掘り始めて数日経ったくらいの頃に追加して、マイニング専用としていました。

止める前に警告を出してから止めるならわかるのですが、いきなり止めた後に事後報告をしてくるという姿勢と、こちらは100%使わないと損なのに100%使ってはいけないという運営の方針が嫌だったので、言われた通り「運用状況の見直し」として全て解約して別の場所に乗り換えることを即座に決めました。

AWSをいじる練習として、いずれS3に乗り換えるつもりだったので良い機会になりました。
これでお互い幸せなんだと思います。

引っ越し

やりたかったのは、S3 + CloudFront + 独自ドメイン + HTTPSという構図です。
詳しい手順については、それぞれリンクした記事などを参照すれば良いので書きません。

第一段階: 新規WebサイトでS3 + 独自ドメイン + HTTPS

参考: https://qiita.com/Ichiro_Tsuji/items/c174d580587a622d3358#fnref1

wwwsample. というサブドメインで作っていました。
問題なく順調に終わったので特に書くことは無いです。

第二弾階: 新規サイトでS3 + CloudFront + 独自ドメイン + HTTPS

参考: https://qiita.com/74th/items/62aaf34c080e747ba420

ドメインの認証に使うためのメールアドレスの用意に手こずりました。 MXレコードを設定し忘れたため、メールを受信できていないというオチでした。 実はメールで認証する必要はなく、DNSレコードをいじることで認証することができました。 参考にした記事が1年以上前のものだったので、新しい方式が追加されたことがわからない感じでした。

もう1点ハマったのが、「US Eastリージョンの証明書でないとCloudFrontで使用できない」という点です。
明らかに証明書を作成できているのに、それをCloudFront側から参照できなくて???となっていました。
最終的に https://stackoverflow.com/questions/44230614/aws-cloudfront-custom-ssl-certificate-disabled にたどり着いてこの事実を知りました。

第三弾階: ブログをS3 + CloudFront + 独自ドメイン + HTTPSに移動させる

お試しサイトを動かしたことでやり方は全て理解したので、ほとんどはさくさくーっとできました。
いくつかハマったのでメモっておきます。

なぜか blog.mihyaeru.com にアクセスすると、S3ぽいURLにリダイレクトされてしまうという問題が発生して謎でした。
アクセスログを見たらstatusが307になっていたので、「s3 cloudfront 307」とかでググったら http://miyasakura.hatenablog.com/entry/2016/12/28/200000 が見つかり、Invalidateして事なきを得ました。

その後もう1つ、 /archives/ のような root 以外のディレクトリにアクセスした際に /archives/index.html が表示されるのではなく403だか404ぽくなってしまう問題が発生しました。
これもテキトーにググッた結果 https://qiita.com/naoiwata/items/3c6626cbeacbb44d4aa8 が見つかり、CloudFrontでS3のバケットを直接originに設定せずに、WebホスティングしているURLをoriginに設定することで、想定通りの動きになってくれました。

Hexoのデプロイ

hexo-deployer-s3hexo-deployer-s3-cloudfrontがあり、CloudFrontを噛ませている場合はInvalidateを実行するために後者の方を使うのが楽そうな感じでした。
が、地味にhexo-deployer-s3からフォークした後に差が開いてしまっているようで、「なんで本家にオプション機能としてマージしなかったんだー」感が強くなってしまい、hexo-deployer-s3を使いつつInvalidateはaws-cliでやることにしました。どっちみち make deploy でラップしているので手間は変わらないかなーという感じです。

終わりに

数時間でできると思っていたらハマりまくりで、けっこう時間を使ってしまいました。 その代わりS3, CloudFront, Route 53, ACM, SNS, SESあたりをざっくりいじったりドキュメントを読んだりできて良い経験になりました。
参考にした記事だけだと基本的な情報が不足していたので、いじった周辺の公式も後から読みました。 やはり基本から順を追って説明してくれる公式のドキュメントはありがたいなと感じました。 ドキュメントがしっかりしていると入門者的にとてもありがたいです。

マイニングは、とりあえず家で余っているPCたちで細々とやっていきます。
年明けたら仮想通貨の取引で儲けた分でマイニング用のマシンを組もうかなと考えています。

それでは良いお年を(?)。

転職してから1ヶ月経ったらしい

実は転職初日に書こうと思っていたのに気づいたら1ヶ月経っていた😇
一応、ネット上では明示的には所属組織を明らかにしていないマンなので、その辺りはふわっとさせておく。

転職の動機

一言でまとめると、いわゆる音楽性の違いというやつ。
もちろん下記以外にも他にもいろいろある。

経営の意思決定内容に一社員として納得感が持てないことが多くなってきたことによる、経営方針へのミスマッチ。詳しい話はNDA的によくなさそうなので割愛。

個人的にソシャゲのガチャが好きではなかったのに、それを提供する側になっていたことによる、事業内容のミスマッチ。他と比較するとガチャの厳しさはゆるかったが、それでも違和感を感じてしまっていた。

個人的にどうありたいかという方針と会社の方針がずれることは仕方のないことだと思う。無理に合わせたりするのではなく、その時々で方針がマッチするところに所属するのが幸せそうだ。

転職先はどう選んだか

人づてだったり転職サイトとかで興味のある会社へ話を聞きに行った。話を聞きに行った場合は中のエンジニアの方と話すスタイルだった。

急いで今すぐに転職したい感じではなかったので、中の人と話してみて自分の中の条件と合う会社があれば、1社ずつ順番に受けていこう、ダメだったらまた探す所から始めよう、という感覚で転職活動を行っていた。新卒の時の、並行して何社も受けて、いろんな会社で面接をして、最終的に決めた会社以外は辞退して、、、みたいな構図が個人的にはかなり心理的な負担だったため、そいう方針にした。

会社を選ぶときの条件というか基準はこんな感じだった。
ミッションへの共感は一番強く、他はだいたい順不同。

  • 会社のミッションに確かな価値を感じ、を自分もそれ実現したいと思えるか
  • 技術的に広い範囲を触ることができるか
  • オープンな社風か
  • 働き方に自由があるか
  • 確率によらない価値を提供する事業を持っているか
  • 強い人が多いか
  • (家から近いか)
  • (他にもいろいろあった気がする)

話を聞きに行くこと5社目くらいで、今の会社にたどり着いた。
最初に話を聞きに行った後のタイミングで「ここだな」と確信した記憶がある。
自分でもかなりマッチしていると確信していたので、これは通るという謎の自信があった。
無事選考1社目で内定をいただき、初めての転職活動を終わらせた。

実際に転職してみて

外から見て感じていたイメージや、面談面接時に聞いたイメージ通りの雰囲気だったので安心した。社内の価値基準が社員に浸透しているのが日常から受け取れる。
イメージ以上だったのは、全体的なテンションの高さ。

働く時間は明らかに増えた。前職が業界内では残業がかなり少ない部類だったので想定通り。早くコードベースに慣れるために時間をかけてる感じがする。
ハードめに働けるのは個人的には20代のうちくらいかな、という感覚があるので頑張っていきたい。

夕飯を会社負担で食べられるのが地味に便利。好きなカレー屋さんのカレーを会社で注文できてしまい、完全に太る気配が忍び寄ってきている。

Web系の会社らしく、GitHubにSlackにMackerelにKibanaにみたいな感じで使用するツール等が前職とあまり変わらず、ツール的な意味で馴染むのは簡単だった。
コミュ力が足りないので人的な意味で馴染むのは数カ月掛かりそうだ。

最後てきとうになったけど、あとは、やっていきの気持ちだ。

ニート日報 2016-10-02

ニート最終日

最終日も特に特別なこと無く終わり。
マイクラをやっていた時間が多くて、この先心配になってしまう。

dotfilesのセットアップをmakeに移行する作業をひとまず終わらせた。
もう少しやりたかったけどマイクラに時間を吸い取られてダメだった。
強い自制心が必要だ。

ブログじゃないサイトのトップページもデザインなしのやつを作ろうと思っていたけど、これもマイクラに時間を(ry

最終日になって、もっともニートっぽい1日を送った気がした。

全体を振り返って

自制心を保つために設定したTODOだったが、とくに技術系の「やっておくと何かの役に立つけど緊急ではないもの」に手を出すモチベーションがなかなか上がらなかった。
残ったものは、働きながらの日常でこなしていくことになるだろう。
残したと言いつつ、前からやりたかったことはチマチマで進められたからある程度は満足している。

とくに後半は休養という名目でダラダラしていたのが目立った。
しかしそのおかげで、退職直前から続いた体調不良も治すことができた。
が、体調のために関西旅行を犠牲にしたのは痛かった。
数年以内に大きな休みを作って行くぞ。

23連休という膨大なお休みだったけど予想通り終わってみればあっという間だった。
またいずれ、落ち着いたタイミングで長期休暇が取れたら嬉しい。
(退職じゃなくて普通にまとまった大きな休みが取れたらいいなーという希望)

というわけでたくさん休んだことだし、明日からお仕事頑張るぞい!

TODO進捗

https://gist.github.com/mihyaeru21/7ec2e6b408d0c7f546274fd4b5a1e610

  • dotfilesのセットアップ移行完了

ニート日報 2016-10-01

ニート22日目

ニート生活残り2日。
前日から急に生活のリズムが崩れて睡眠時間帯が6時間くらいずれてしまった。

あとちょっとで終わるところだった本を終わらせた。
人工無能の本はちょっと古いけど、それなりにRubyの練習にもなった。

dotfilesを整理していたらMinecraftを始めることになってしまった(?)。

天一の日

天一botが今回限りで活動終了なのが悲しかった。
↓が天一に行ってきた様子。

Minecraft

なんと残すところ1日ちょいの段階でマイクラを始めてしまった。
閉じた?鯖でまったりやってる。
初めてだからいろいろと新鮮で面白い。
これは時間を吸い取られてしまうのもわかる。

TODO進捗

https://gist.github.com/mihyaeru21/7ec2e6b408d0c7f546274fd4b5a1e610

  • 恋するプログラム終わり
  • dotfilesの整理