huskyのpre-commitが動かなかったのでなんとかした話

以下の動画でTypeScript を勉強しようと思った。 www.youtube.com

ESLintとPrettierまではうまくいったけど、huskyがうまく動かない。。。 動画でも同じように動いていなかったので、ここまではある程度想定通り。 でも、動画での対処法をやってみたけど、うまくいかなかった。。。

いろいろ調べてなんとかhuskyが使えるようになったので、その方法を紹介。

動画内の解決方法

ls -al .git/hooks 確認

動画の通り、ls -al .git/hooksを実行したら、*.sampleしかなかった。

$ ls -al .git/hooks
total 120
drwxr-xr-x  15 murae  wheel   480  4  8 06:03 .
drwxr-xr-x   9 murae  wheel   288  4  8 06:03 ..
-rwxr-xr-x   1 murae  wheel   478  4  8 06:03 applypatch-msg.sample
-rwxr-xr-x   1 murae  wheel   896  4  8 06:03 commit-msg.sample
-rwxr-xr-x   1 murae  wheel  4655  4  8 06:03 fsmonitor-watchman.sample
-rwxr-xr-x   1 murae  wheel   189  4  8 06:03 post-update.sample
-rwxr-xr-x   1 murae  wheel   424  4  8 06:03 pre-applypatch.sample
-rwxr-xr-x   1 murae  wheel  1643  4  8 06:03 pre-commit.sample
-rwxr-xr-x   1 murae  wheel   416  4  8 06:03 pre-merge-commit.sample
-rwxr-xr-x   1 murae  wheel  1374  4  8 06:03 pre-push.sample
-rwxr-xr-x   1 murae  wheel  4898  4  8 06:03 pre-rebase.sample
-rwxr-xr-x   1 murae  wheel   544  4  8 06:03 pre-receive.sample
-rwxr-xr-x   1 murae  wheel  1492  4  8 06:03 prepare-commit-msg.sample
-rwxr-xr-x   1 murae  wheel  2783  4  8 06:03 push-to-checkout.sample
-rwxr-xr-x   1 murae  wheel  3650  4  8 06:03 update.sample

なんで、husky-upgradeを実行して、もう一度ls -al .git/hooks

$ ./node_modules/.bin/husky-upgrade
husky > upgrading /Library/WebServer/Documents/test/typescript/ts-basic/package.json
husky field in package.json isn't empty, skipping automatic upgrade

$ ls -al .git/hooks
total 120
drwxr-xr-x  15 murae  wheel   480  4  8 06:03 .
drwxr-xr-x   9 murae  wheel   288  4  8 06:03 ..
-rwxr-xr-x   1 murae  wheel   478  4  8 06:03 applypatch-msg.sample
-rwxr-xr-x   1 murae  wheel   896  4  8 06:03 commit-msg.sample
-rwxr-xr-x   1 murae  wheel  4655  4  8 06:03 fsmonitor-watchman.sample
-rwxr-xr-x   1 murae  wheel   189  4  8 06:03 post-update.sample
-rwxr-xr-x   1 murae  wheel   424  4  8 06:03 pre-applypatch.sample
-rwxr-xr-x   1 murae  wheel  1643  4  8 06:03 pre-commit.sample
-rwxr-xr-x   1 murae  wheel   416  4  8 06:03 pre-merge-commit.sample
-rwxr-xr-x   1 murae  wheel  1374  4  8 06:03 pre-push.sample
-rwxr-xr-x   1 murae  wheel  4898  4  8 06:03 pre-rebase.sample
-rwxr-xr-x   1 murae  wheel   544  4  8 06:03 pre-receive.sample
-rwxr-xr-x   1 murae  wheel  1492  4  8 06:03 prepare-commit-msg.sample
-rwxr-xr-x   1 murae  wheel  2783  4  8 06:03 push-to-checkout.sample
-rwxr-xr-x   1 murae  wheel  3650  4  8 06:03 update.sample

だめ。ここまで動画通り

huskyを再インストール

$ npm uninstall husky


removed 13 packages, and audited 707 packages in 3s

70 packages are looking for funding
  run `npm fund` for details

5 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
$ npm install -D husky

added 1 package, and audited 708 packages in 1s

71 packages are looking for funding
  run `npm fund` for details

5 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

んでもう一回ls -al .git/hooks

$ ls -al .git/hooks
total 120
drwxr-xr-x  15 murae  wheel   480  4  8 06:03 .
drwxr-xr-x   9 murae  wheel   288  4  8 06:03 ..
-rwxr-xr-x   1 murae  wheel   478  4  8 06:03 applypatch-msg.sample
-rwxr-xr-x   1 murae  wheel   896  4  8 06:03 commit-msg.sample
-rwxr-xr-x   1 murae  wheel  4655  4  8 06:03 fsmonitor-watchman.sample
-rwxr-xr-x   1 murae  wheel   189  4  8 06:03 post-update.sample
-rwxr-xr-x   1 murae  wheel   424  4  8 06:03 pre-applypatch.sample
-rwxr-xr-x   1 murae  wheel  1643  4  8 06:03 pre-commit.sample
-rwxr-xr-x   1 murae  wheel   416  4  8 06:03 pre-merge-commit.sample
-rwxr-xr-x   1 murae  wheel  1374  4  8 06:03 pre-push.sample
-rwxr-xr-x   1 murae  wheel  4898  4  8 06:03 pre-rebase.sample
-rwxr-xr-x   1 murae  wheel   544  4  8 06:03 pre-receive.sample
-rwxr-xr-x   1 murae  wheel  1492  4  8 06:03 prepare-commit-msg.sample
-rwxr-xr-x   1 murae  wheel  2783  4  8 06:03 push-to-checkout.sample
-rwxr-xr-x   1 murae  wheel  3650  4  8 06:03 update.sample

・・・は?

まぁ、1年以上前の動画だから、こういうこともあるよね。 というわけでここから解決法。

huskyのバージョンを変更する

解決は結構簡単で以下のサイトにあるnpx mrm@2 lint-stagedを実行したらいい。 rinoguchi.net

$ npx mrm@2 lint-staged
Running lint-staged...
Update package.json
husky - Git hooks installed
husky - created .husky/pre-commit

あとは実際にcommitしてみる。

$ git add .    
$ git commit -m 'test' 
✔ Preparing...
✔ Running tasks...
✔ Applying modifications...
✔ Cleaning up...
✔ Preparing...
✔ Running tasks...
✔ Applying modifications...
✔ Cleaning up...
[master 70174f7] test
 2 files changed, 1 insertion(+), 3 deletions(-)

動いた。

原因はnpmのバージョン?

1年前の動画だから、nodeとnpmのバージョンも違ってるだろうから、今回のバグが起こったのかも。 詳しい原因は分かってないので、わかる人がいたら教えてください!!

同じように困っている人の助けになれば幸いです。

ローカル開発時のURLをIPから任意ドメインに変更する

開発をしていると、IPベースのURLを使用していると、ちょっと面倒だったりする。

例えば、家と会社でIPが違うことにより、それぞれの環境でURLを書き換えないといけない。 Chromeだとよく使うURLは覚えてくれるのだけれども、仕事を会社から家に持ち帰っていざ続きをやろうと思うと、会社IPのURLでアクセスしてう。 「あぁ、そうだった」 となってURLを書き換えて開発を再開、なんてことがよくある。

と言うことで、IPベースのURLをやめて、固定のURLで開発をする方法のお話。

hostsファイルを変更しよう。

やり方はとても簡単で、hostsファイルにアクセスしたいドメインを追記してやればOK。

$ sudo vi  /private/etc/hosts

# 末尾に追加(私はわかりやすく、{プロジェクト名}.localとしました。)
127.0.0.1 project.local

ブラウザでproject.localにアクセスして、問題なく表示されていればOK。

一度設定してしまえば、場所が変わっても常に同じURLでアクセスすることができるようになる。

これで少し開発が楽になるかな。

アンガーマネジメントについて考える

最近、仕事でちょっとしたことでイライラしてパフォーマンスが下がってしまうことがよくある。 そこで昔から名前だけは聞いたことがあった「アンガーマネジメント」について少し調べてみた。

こんな本を読んだ

早速図書館に行って本を物色。 するとこんな本があった。

どんな怒りも6秒でなくなる アンガーマネジメント・超入門 | 安藤 俊介, リベラル社, にしだ きょうこ |本 | 通販 | Amazon

厚くなく、文字も少ない本なんだけど、すごく分かりやすくていい本だった。 この本を読んで学んだことを紹介する。

現代人はイライラしやすい!

人は自分と価値観が違うことにイライラしやすい。 今はテレビを見ても、雑誌を見ても「多様性」が謳われている。

多様性が広まるということは、それだけ自分と違う価値観と触れ合う機会が増えることになる。

さらに、SNSやブログなどで自分の考えを発信することも増えている。 それは同時に受信することも増えるということだ。

違う価値観が増えて、それに触れる機会も増えるということはイライラしてしまうのもある程度仕方ないのかもしれない。

イライラしやすい社会だからといって、怒りをうまく付き合っていかないと、無駄に疲れてしまう。

この本はその「付き合い方」について紹介している。

怒りが起こる3ステップ

怒りが起こるには以下の3ステップがある。

  1. 物事が起こる
  2. 物事にラベリングする
  3. 怒りの感情が生まれる

物事が起こる

まず、物事が起こる。

それはいいことでも、悪いことでも、その種類、大小には関係がない。 ただ起きる。大事なのは次の「ラベリング」だ。

物事にラベリングする

  1. で起こった物事にラベリングする。 ポジティブなラベリングができれば、そもそも怒りは生まれない。

それが自分にとって無視できる、または許容できる範囲であれば怒りになることはない。

だが物事が許容できないレベルだと、怒りの感情が生まれてしまう。

この「許容できる」範囲を広げてあげることで怒りの感情が湧いてくるのを抑えることができる。

自分が何に対して許容できないのかを知る

人は自分の中の「はず」「べき」が裏切られると怒りが生まれる 「あのときはこうなったはず」 「あの人はこうするべき」 人によってその範囲は違っていて、わかりにくい。 ならその「わかりにくい」をわかろう。

怒りメモする

怒りが湧いたら、その場でメモを取るのがいいらしい。 怒りは通常6秒時間をおけば治まる。 メモを取ることでこの「6秒」をかせぐことができる。

メモの内容は以下の3つ。 1. いつ? 2. 何があった? 3. 自分の怒りレベルは?

メモを取ることによって、自分が何に対して「怒り」を感じているのかパターンがわかる。 パターンが分かれば対処できる。 対処できれば対応できる。 そうやって少しずつ自分の「許容できる範囲」を広げていくことができるようになる。

## 相手のことも考えてみる 自分のパターンはわかった。 何に対して許容できないのかもわかった。 自分のことがわかったら、次は相手のことも考えてみよう。

相手は私の「はず」や「べき」を裏切った。 でも、それは「なんでだろう?」

何か事情があったのかもしれない。

相手のことを考えて、「だったら仕方ないかもなぁ」と思えれば怒りも「許容できる」ようになる助けになる。

まとめ

この本ではその他にも上手な怒り方や、怒りとうまく付き合っていく方法が紹介されている。

全ての感情は人生をよくするためのギフトだと考えることができる。 怒りが持つ価値に気づき、生かすために怒りとの上手な付き合い方を身につける必要がある。

この本はそんな現代人に必須のスキルを身につけるためのはじめの一歩として指針になる素晴らしい本でした。

あなたの「べき」「はず」を手放してみませんか?

Cronの多重起動を防止する

PHPでDM配信システムを実装した。

仕組みは以下。

  • メールの件名、本文、配信先をDBに登録
  • Cronで5分間隔でmail_send.phpを実行。
  • mail_send.php 内でDBから配信済みフラグが0のレコードを70件取得し、メール配信
  • 配信が完了した宛先には配信済みフラグを1に変更
  • 以後繰り返し。

詳しい実装方法はまた別の記事で紹介するかも。

んで、Cronはこんな感じ

*/5 * * * * php /path/to/dir/mail_send.php

これはこれでうまく動くんだけど、なんらかの問題があって全てを配信できなかった場合、前回配信が終わらず配信フラグが0の配信先を再度取得してしまう。 結果、同じ配信先に2通のメールが配信されてしまうことになる。 これはまずい。

lockfileを作成して多重起動を防止

やり方は結構簡単で、Cronを実行した際に、lockfileを作成し、処理が全て終わったらlockfileを削除する。 Cronが回ってきた時、lockfileが存在する(処理が完了していない)場合は処理を実行しない。

コードはこんな感じ。

// 同階層にlockfileを作成する場合、__DIR__ . '/lockFile.txt';でもおk。
$lockFile = '/path/to/dir/lockFile.txt';

if (file_exists($lockFile)) {
  exit(0); // ファイルが存在する場合、プログラムを停止させる
}

// 実行する前にファイルを作成する
touch($lockFile);

****************************************************
メール配信処理
****************************************************

///処理が終わったらlockfifleを削除する
unlink($lockFile);

やってみると多重起動は防止できていることがわかると思うる。

念の為、自動でlockfileを削除する処理を追加する

万が一lockfileの削除ができなかった場合、処理が終わってないと判断され、手動でlockfileを削除しない限りメール配信がされないことになってしまう。

そこで、作成から一定時間経過したlockfileは削除するという処理を追加する。

// 同階層にlockfileを作成する場合、__DIR__ . '/lockFile.txt';でもおk。
$lockFile = '/path/to/dir/lockFile.txt';

// 作成時間から5分経過していたらlockfileを削除する
$limit = 5;
if (strtotime(date('Y-m-d H:i:s')) - filemtime($lockFile) / 60 > $limit) {
  unlink($lockFile);
}

if (file_exists($lockFile)) {
  exit(0); // ファイルが存在する場合、プログラムを停止させる
}

// 実行する前にファイルを作成する
touch($lockFile);

****************************************************
メール配信処理
****************************************************

///処理が終わったらlockfifleを削除する
unlink($lockFile);

これでCronの多重起動が防止できました。

よかったら参考にしてみてください。

Dockerを勉強してみる

今年の年末年始休みはDockerを勉強してみることにした。

仕事ではずっとMAMPを使って環境構築をしてきた。 簡単に環境も構築できるし、特に問題も出てこなかったので愛用してきた。

だけど、最近サーバーでは動くけど、ローカルでは動かないということがたまに出てくるようになった。 合わせて、同僚に環境を構築してもらうとき、MAMPのバージョン(MySQLのバージョン)によってうまくインストールができないということが出てきた。

ここは最近デファクトとなったDockerを勉強したらこれらの問題が解決するのでは?ということで勉強してみることにした。

参考にしたもの

とりあえず、ざっくり概要が知りたかったので、以下の本を参考にした。

Dockerに手を出そうとして挫折した「プログラマ」は、まず最低限触ってみるところからリスタートしてみよう

それじゃ、いってみよう。

Dockerとは?

  • 仮想環境の一種
  • 古くからあるVMwareなどに比べて軽量、カスタマイズ性が高い
  • 環境を共有しやすい

ふむふむ。とりあえず、軽くて共有しやすい仮想環境って感じでおぼえておけばいいのかな。(よくない)

コンテナとイメージ

コンテナ

  • 仮想環境の単位
  • この「コンテナ」単位でデータやプログラムを管理する
  • 用途に応じて複数作成する

イメージ

  • コンテナを作るテンプレート
  • https://hub.docker.com/で管理していて、ダウンロードして利用する

なるほど。大体わかった。

コンテナを作る

# Docker Hubから「httpd」というapacheのイメージをダウンロードして、バックグラウンド(-d)で実行
$ docker container run --name myContainer -d -p 8080:80 httpd
0977ed7a06349576e1eaaa1c8ed3a275c49e61ed1c4e356b85e876872fad9eb5

# 起動確認
$ docker container ls
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                    NAMES
0977ed7a0634   httpd                   "httpd-foreground"       41 minutes ago   Up 41 minutes   0.0.0.0:8080->80/tcp     myContainer

# 以下のコマンドで起動していないコンテナを含めて確認できる
$ docker container ls -a

# docker container ls は以下のコマンドでも確認OK
$ docker ps 

# コンテナを停止
$ docker container stop myContainer

# 停止確認。STATUS列が「Exited」となっていればOK
$ docker ps -a
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS                      PORTS                    NAMES
0977ed7a0634   httpd                   "httpd-foreground"       46 minutes ago   Exited (0) 2 seconds ago                             myContainer

コンテナ・イメージを削除

# 削除
$ docker container rm myContainer

# 確認
$ docker ps -a
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS                      PORTS                    NAMES

# イメージの削除
$ docker rmi httpd

# 確認
$ docker images
REPOSITORY              TAG          IMAGE ID       CREATED         SIZE

なるほど。コマンドは大体わかった。

Dockerfileとは?

  • 予め必要なパッケージ、アプリケーション、各種設定を盛り込んだイメージを作るための設計図。

Docker Composeとは?

  • docker container runの集合体みたいなもの。
  • httpd, DBなど複数のコンテナで構成されるシステムを扱う場合に使う。

Kubernetesとは?

  • コンテナのオーケストレーションツール
    • システム、アプリケーション、サービスの設定/運用管理の自動化のこと。
  • 複数のコンテナを一度に管理できるものくらいの認識で今はOK(多分)

最後に

とりあえず、ざっくり概要はわかった。 明日はもうちょっと詳しく使い方を勉強して、実際のプロジェクトに導入して行ってみよう。

2022年の所信表明

現在、2022年1月1日 0:17。 2021年が終わり、2022年がスタートしました。

2021年は仕事でもプライベートでも成長を感じられる年でした。 ただ、何をしたのか、何を学んだのか、ログを残していなかったので、具体的に何ができるようになったのかが、ぱっと出てこないです。 今思えばもっとちゃんとログを取っておけば、自分の成長を実感できたんだろうなと、ちょっと残念。

なので、今年はもっとログをとっていこうと考えます。

ということで、今年の目標。

2022年の目標

はてなぶろぐやTwitterを利用してアウトプットをしていきたい。 毎日アウトプットしていければいいけど、できない日もあると思う。 完璧を求めると疲れてしまうから、できる範囲で続けていければと思います。

それでは今年もよろしくお願いします!!

配列に入れたキーワードにマッチした文字列をタグで囲むやつを作ってみた。

やりたいこと

とあるサイトで、ページ内にある文章から複数のキーワードに該当する文字列をタグで囲みたいことがありました。
ページが長く、動的に作成されるページだったので、jQueryで対応できないかなとやってみたら案外うまく言ったので、備忘録を兼ねてメモ。

作ったもの

こんなのができました。 codepen.io

devツールなどで見ると、配列に入れたキーワードごとにで囲まれているのがわかると思います。
さらに、キーワードのカテゴリーごとに別々のクラスが付与されています。

キーワードを配列に入れる

まずは配列にキーワードを入れています。

  // キーワードをカテゴリー別に配列に格納
  var sport = ['野球', 'サッカー'];
  var animal = ['犬', '猫'];
  var country = ['日本', 'アメリカ'];
  // カテゴリーを配列に格納
  var keyword = [sport, animal, country];

今回は複数のカテゴリーに分かれてキーワードが存在していたので、それらをまとめてkeywordという配列に入れています。

また、そのほかに使用する変数も用意しておきます。

  var i,j = 0;
  var $sample = $('.sample'); // 対象を指定
  var sourceStr = $sample.html(); // 対象のHTMLを抽出
  var targetStr = keyword; // キーワードを一度変数に格納
  var typeClass; // カテゴリーごとにクラスを振りたいので、変数を用意
  var regExp; // のちにキーワードを正規表現オブジェクトにするので変数を用意しておく

カテゴリーごとにループを回す

配列、変数の用意ができたら、最初にカテゴリーごとにループを回します。

  // カテゴリーごとにループを回す
  for(i in targetStr){
    // キーワードによって付与するクラスを変える
    if (i == 0) {
      typeClass = ' class="sport"';
    }else if (i == 1) {
      typeClass = ' class="animal"';
    }else if (i == 2) {
      typeClass = ' class="country"';
    }
  }

ここでは、カテゴリーごとに違うクラス名を指定したかったので、ループの値( i )によって変数typeClassに異なる値を入れています。

キーワードごとにループを回す

次に、カテゴリーに含まれるキーワードごとにループを回します。

    // カテゴリーに含まれるキーワードごとにループを回す
    for(j in targetStr[i]) {
      regExp = new RegExp( targetStr[i][j], "g" ) ;
      // 置換したものを、一度変数sourceStrに格納
      sourceStr = sourceStr.replace( regExp , "<span" + typeClass + ">$&</span>" ) ;
    }

正規表現で置換したかったので、regExp正規表現オブジェクトを作成しています。

ページ内で引っかかったキーワードを.replaceで置換します。

置換するキーワードを囲む には、キーワードに応じて先ほど用意したクラスを指定します。

ここで使っている &$ は「一致した対象文字を抽出する」というものなので、キーワードを<span class="animal">犬</span> とできます。

ページの内容を置換したもので置き換える

最後に対象を置き換えれば完成です。

$sample.html(sourceStr);

終わりに

配列に入れた複数のキーワードをタグで囲むことができました。
意外とこういう記事が見つからなかったので、苦労しましたがなんとかできました。

もし同じようなことをしたい人がいたら、使ってください。