睡眠負債の解消

2024年のゴールデンウィークは適正な睡眠時間の把握、睡眠負債の解消を目的に、睡眠に注力して過ごした。

きっかけは、睡眠に関する情報をテレビで目にする機会が増えたこと。番組の中では、適正な睡眠時間を知る方法として、一定期間寝たいだけ寝る方法が紹介されていた。

その方法は下記の記事でも言及がされている。

これに関して興味深い実験があります。それは、「どれだけ眠れば寝不足は解消できるのか」を検証するために、健康な10人を14時間、毎日ベッドに入れ続けた調査です。

https://toyokeizai.net/articles/-/164998?page=3

実験

  • 4/28 - 5/5の7日間、寝たいだけ寝る
  • Fitbit charge 5で計測をする

寝たいだけ寝るのだが、そうは言っても14時間布団に入っているのは現実的ではないので12時間とした。21時に入り9時には起きるイメージ。

結果

f:id:kuranari_tm:20240526185737p:image

毎日の睡眠時間は10-11時間程度。

Fitbitのダッシュボードは8.5時間になっているが、夜間の覚醒時間の1.5-2時間は睡眠時間に含まれない。

睡眠負債の解消には3週間程度かかるという論文の報告通り、必要睡眠量はまだ多めなのだろう。予想としては、8.0-8.5時間が適正な睡眠時間なのではないかと感じる。

別の指標としては、安静時心拍数が下がった。

f:id:kuranari_tm:20240526110457j:image

ただし、睡眠中は心拍数が下がるから、単純に睡眠量が増えたから平均が引き下げられただけという可能性がある。さらにゴールデンウイーク中は階段の上り下りの回数が減ったこと、仕事中は心拍数が上がりがちだが全日休みだった、などの事情から睡眠との因果関係は不明である。

日中の感覚としては、思考がとてもクリアになった。これまで脳にモヤがかかっていた状態だったのに、それに気づけていなかったのは危険な状態だったようにも思う。寝る前にビール350mlを飲んでも次の日にはスッキリ目覚められた。

まとめ

1週間まとまった睡眠をとったことで、日頃いかに必要な睡眠を取れていないか自覚することができた。

睡眠量を減らして仕事をするよりも、きっぱり寝た方がよい意思決定ができるということも感じられた。睡眠時間の確保に重点を置いて生活をしていこうと思う。

 

参考文献

 

Emacs org-modeへの初コントリビュート体験記

背景

2023/11にEmacsのorg-modeにコントリビュートを行った。 OSSに対してGitHubのPull Requestでコントリビュートしたことは何度かあるが、Emacs / org-modeに対するコントリビュートは初めてで、さらにいうとメーリングリストでパッチを送るということ自体が初めてだった。

パッチの概要、時系列のタイムライン、この経験での学びを記載する。

パッチの概要

org-special-ctrl-a/etになっているという前提。 C-u 2 C-a のように前置引数が正の整数で org-beginning-of-line を実行すると、本当は見出し記号の直後にカーソルが移動することを期待するが、実際には行頭に移動してしまう。なお、C-u 0 C-aのようなファイル先頭方向に移動する際には期待通りの挙動を示す。

この挙動はmarkdown-modeに対して org-beginning-of-line と同等の機能を実装していくなかでの自動テストで発見した。 前置引数ありで org-beginning-of-line を呼び出し、それが運よく(運悪く?)見出しやリスト行に当たるということは少ないだろうから、markdown-mode向けの再実装をしなければ見つけられなかったと思う。

実際のパッチ

From 739c6636cd9e015ed214a6ccaed20cf75301a8d5 Mon Sep 17 00:00:00 2001
From: Tomohisa Kuranari <tomohisa.kuranari@gmail.com>
Date: Fri, 22 Sep 2023 22:38:26 +0900
Subject: [PATCH] org-beginning/end-of-line: Fix when moving to different line

* lisp/org.el (org-beginning-of-line, org-end-of-line): Fix issue with `org-special-ctrl-a/e' not working correctly when moving to different line
* testing/lisp/test-org.el (test-org/beginning-of-line, test-org/end-of-line): Add new tests.
---
 lisp/org.el              |  6 ++--
 testing/lisp/test-org.el | 62 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index d0b2355ea..7cd313c30 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -20331,7 +20331,7 @@ With argument N not nil or 1, move forward N - 1 lines first."
    (if (eq special 'reversed)
        (when (and (= origin bol) (eq last-command this-command))
          (goto-char refpos))
-    (when (or (> origin refpos) (= origin bol))
+     (when (or (> origin refpos) (<= origin bol))
        (goto-char refpos)))))
      ((and (looking-at org-list-full-item-re)
       (org-element-type-p
@@ -20347,7 +20347,7 @@ With argument N not nil or 1, move forward N - 1 lines first."
    (if (eq special 'reversed)
        (when (and (= (point) origin) (eq last-command this-command))
          (goto-char after-bullet))
-    (when (or (> origin after-bullet) (= (point) origin))
+     (when (or (> origin after-bullet) (>= (point) origin))
        (goto-char after-bullet)))))
      ;; No special context.  Point is already at beginning of line.
      (t nil))))
@@ -20402,7 +20402,7 @@ With argument N not nil or 1, move forward N - 1 lines first."
           (goto-char tags)
         (end-of-line)))
          (t
-         (if (or (< origin tags) (= origin (line-end-position)))
+          (if (or (< origin tags) (>= origin (line-end-position)))
           (goto-char tags)
         (end-of-line))))))
      ((bound-and-true-p visual-line-mode)
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 8355e2d77..63fd16b40 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -4460,6 +4460,16 @@ asd
      (let ((org-special-ctrl-a/e '(nil . nil)))
        (org-beginning-of-line)
        (looking-at "Headline"))))
+  (should
+   (org-test-with-temp-text "* TODO [#A] Headline\n<point>"
+     (let ((org-special-ctrl-a/e t))
+       (org-beginning-of-line 0)
+       (looking-at-p "Headline"))))
+  (should
+   (org-test-with-temp-text "<point>\n* TODO [#A] Headline"
+     (let ((org-special-ctrl-a/e t))
+       (org-beginning-of-line 2)
+       (looking-at-p "Headline"))))
   ;; At an headline with reversed movement, first move to beginning of
   ;; line, then to the beginning of title.
   (should
@@ -4480,6 +4490,18 @@ asd
       (this-command last-command))
        (and (progn (org-beginning-of-line) (bolp))
        (progn (org-beginning-of-line) (looking-at-p "Headline"))))))
+  (should
+   (org-test-with-temp-text "* TODO Headline\n<point>"
+     (let ((org-special-ctrl-a/e 'reversed)
+      (this-command last-command))
+       (and (progn (org-beginning-of-line 0) (bolp))
+       (progn (org-beginning-of-line) (looking-at-p "Headline"))))))
+  (should
+   (org-test-with-temp-text "<point>\n* TODO Headline"
+     (let ((org-special-ctrl-a/e 'reversed)
+      (this-command last-command))
+       (and (progn (org-beginning-of-line 2) (bolp))
+       (progn (org-beginning-of-line) (looking-at-p "Headline"))))))
   ;; At an item with special movement, first move after to beginning
   ;; of title, then to the beginning of line, rinse, repeat.
   (should
@@ -4488,6 +4510,14 @@ asd
        (and (progn (org-beginning-of-line) (looking-at-p "Item"))
        (progn (org-beginning-of-line) (bolp))
        (progn (org-beginning-of-line) (looking-at-p "Item"))))))
+  (should
+   (org-test-with-temp-text "- [ ] Item\n<point>"
+     (let ((org-special-ctrl-a/e t))
+       (org-beginning-of-line 0) (looking-at-p "Item"))))
+  (should
+   (org-test-with-temp-text "<point>\n- [ ] Item"
+     (let ((org-special-ctrl-a/e t))
+       (org-beginning-of-line 2) (looking-at-p "Item"))))
   ;; At an item with reversed movement, first move to beginning of
   ;; line, then to the beginning of title.
   (should
@@ -4496,6 +4526,18 @@ asd
       (this-command last-command))
        (and (progn (org-beginning-of-line) (bolp))
        (progn (org-beginning-of-line) (looking-at-p "Item"))))))
+  (should
+   (org-test-with-temp-text "- [X] Item\n<point>"
+     (let ((org-special-ctrl-a/e 'reversed)
+      (this-command last-command))
+       (and (progn (org-beginning-of-line 0) (bolp))
+       (progn (org-beginning-of-line) (looking-at-p "Item"))))))
+  (should
+   (org-test-with-temp-text "<point>\n- [X] Item"
+     (let ((org-special-ctrl-a/e 'reversed)
+      (this-command last-command))
+       (and (progn (org-beginning-of-line 2) (bolp))
+       (progn (org-beginning-of-line) (looking-at-p "Item"))))))
   ;; Leave point before invisible characters at column 0.
   (should
    (org-test-with-temp-text "[[https://orgmode.org]]<point>"
@@ -4598,6 +4640,14 @@ asd
        (and (progn (org-end-of-line) (looking-at-p " :tag:"))
        (progn (org-end-of-line) (eolp))
        (progn (org-end-of-line) (looking-at-p " :tag:"))))))
+  (should
+   (org-test-with-temp-text "* Headline1 :tag:\n<point>"
+     (let ((org-special-ctrl-a/e t))
+       (org-end-of-line 0) (looking-at-p " :tag:"))))
+  (should
+   (org-test-with-temp-text "<point>\n* Headline1 :tag:\n"
+     (let ((org-special-ctrl-a/e t))
+       (org-end-of-line 2) (looking-at-p " :tag:"))))
   (should
    (org-test-with-temp-text "* Headline2a :tag:\n** Sub"
      (org-overview)
@@ -4625,6 +4675,18 @@ asd
       (this-command last-command))
        (and (progn (org-end-of-line) (eolp))
        (progn (org-end-of-line) (looking-at-p " :tag:"))))))
+  (should
+   (org-test-with-temp-text "* Headline3 :tag:\n<point>"
+     (let ((org-special-ctrl-a/e 'reversed)
+      (this-command last-command))
+       (and (progn (org-end-of-line 0) (eolp))
+       (progn (org-end-of-line) (looking-at-p " :tag:"))))))
+  (should
+   (org-test-with-temp-text "<point>\n* Headline3 :tag:\n"
+     (let ((org-special-ctrl-a/e 'reversed)
+      (this-command last-command))
+       (and (progn (org-end-of-line 2) (eolp))
+       (progn (org-end-of-line) (looking-at-p " :tag:"))))))
   (should
    (org-test-with-temp-text "* Headline2a :tag:\n** Sub"
      (org-overview)
-- 
2.42.0

https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=93ebd64de

タイムライン

  • 2023/08/05
    • Copyright Assignmentのリクエスト
  • 2023/08/15
    • AssignmentのPDFを受信(from kuranari)
  • 2023/09/02
    • PDFにサインをしてEmailで返送。2023年時点では書類の郵送の必要はなく、メールで完結した。
    • (印刷、スキャンが手間でタスクを積みっぱなしにしていたら、事務局からリマインドをいただいてしまった
  • 2023/09/20
    • Assignmentのプロセスが完了の連絡受信
  • 2023/09/26
  • 2023/10/05
    • yantar92さんからレビューをもらう
    • line-number-at-posは使わないほうがいいのじゃないかという指摘。納得すぎる
  • 2023/10/08
    • レビューでの指摘を対応し再提出
  • 2023/11/08

不安な日々

メールを送る機会が少なくなっていて、メールの送信者を日本語の本名で送ってしまった。 またGmailでパッチファイルを添付したのだが、他の人が読めるファイル形式になっているのか、返信をもらうまで不安を抱えていた。

この辺りは、送信者名はAscii文字列でなければないだろうし、何か失敗があってもコントリビュートは恥をかきながら覚えようということで開き直ったりもしていた。

レビュワーへの感謝

レビュワーのyantar92さんからは、コミットメッセージの書き方、コードフォーマットの作法、効率的なアルゴリズムなどを丁寧に指摘していただいた。パッチに対してレビュワー自身がコードを改変したほうが労力は少なかっただろうに、一見さんの私に対して丁寧な教育をしてもらえたのがとても嬉しかった。業務、OSSを問わず、レビューをする際にはこの経験を生かしたいと思う。

まとめ

org-modeへの初のコントリビュートについてまとめた。 メーリスへの投稿から数週間レスがない時期などは、もしかして忘れられてないだろうかと不安になることもあったが、最終的にマージされた時の嬉しさは格別だった。

マージについてお礼を言った際に返ってきた

Music to our ears - thanks to you !

というお洒落な返事も嬉しさを大きくさせてもらった。

世界で使われているソフトウエアに貢献できるのであれば、せっかくならば英語ももう少し勉強してみようかなと思ったものだった。

参考文献

著作権譲渡の手続きやメーリングリストへの投稿方法は下記の記事が参考になった。

spacemacsにコントリビュートをした話

実際のプルリクエスト

github.com

背景

2022年の年末頃から、日本語文章の執筆用途としてEmacsを使い始めた。

1から設定を積み上げていくのはそれなりに大変であることが予想されたので、Spacemacsを導入した上で、個別の設定を追加している。

Spacemacsでコード補完の候補を表示するレイヤー(パッケージやデフォルト設定集)はauto-completion layerを使用していて、表示フロントエンドにはcompany-boxを使用している。実際の設定は下記の通り。

     (auto-completion :variables
                      auto-completion-enable-sort-by-usage t
                      auto-completion-use-company-box t
                      auto-completion-enable-help-tooltip 'manual
                      auto-completion-complete-with-key-sequence-delay 0.0
                      auto-completion-enable-snippets-in-popup t
                      auto-completion-minimum-prefix-length 1)

この設定で補完候補を表示した場合に、アイコンと文字列が中央揃えにならない、意図しない画像が表示される、という事象が発生していることに気づいた。

この不具合の原因を簡易版、やや厳密な説明版の2つで説明してみようと思う。

不具合の原因(簡易版)

company-boxで defvar を使って定義されている変数 company-box-icons-all-the-icons をuse-packageの :custom で設定をしようとしていため。

:custom に記述した内容は、パッケージが読み込まれる前に実行されるのだが、company-box-icons-all-the-icons はパッケージ読み込み前には当然未定義であるため、設定が正しく行えない

なおuse-packageは下記の記事でも解説を試みた。

qiita.com

不具合の原因(やや厳密な説明版)

少々込み入っているので、箇条書きで説明をすると、

  1. use-packageには:custom で設定した値が custom file に保存されることを防ぐことができるオプション( use-package-use-theme )がある
  2. 上記のオプションが有効になっている場合 :custom の変数定義は custom-theme-set-variables で行われる
  3. この custom-theme-set-variables は「変数が定義済みの場合には上書き、未定義の場合には指定したテーマのシンボルに対するプロパティの追加のみを行う
  4. 他方、上記でプロパティに設定を追加したテーマ(シンボル名: 'use-package)は常に無効な状態になっている

という、事象の掛け合わせで :custom の設定が反映されない状態になっていた。

厳密な説明を試みたものの正しく説明できている自信はないので「defvar で定義された変数を use-packageの :custom セクションで定義をすると設定が反映されないことがある」くらいに捉えてもらうのがいいと思う。

不具合の解消

パッケージが読み込まれる後に実行される :config セクションに移動し、 setq で上書きするように変更したことで修正が完了した。

spacemacsのこのレイヤーでは、自動テストなどは用意されていなかったため、コード差分と動作確認用のスクリーンショットをつけてプルリクエストを送った。

まとめ

変数がdefvarで定義されていることに気づくのもそれなりに時間がかかったが、それ以上になぜdefvarをuse-packageの:custom で上書きできないのか、という調査に時間を取られた。

ただ、時間をかけて原因追及をしたことで、Spacemacsのレイヤーの仕組み、use-package、変数定義(setq, defvar, defcustom)、マクロ展開、テーマなどの多くの知識を手に入れられた。 また、本記事では触れなかったがedebugを使ったデバッグなど、Elispの不具合発見方法に馴染むことができた。

今後もEmacsの設定や各種パッケージへのコントリビュートをしていこうと思う。

TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発[3.6 ~ 7章]

昨日の続き。 TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発[1 ~ 3.5章] - Kuranari::Log

3章

3.6章のNext.js入門は飛ばして4章から読もうと思ったけれど、4章は3.6章のプロジェクトがあることが前提だったため、Next.jsの準備として3章に戻る。 以前 Next.js のチュートリアルをやった際にSSR/SSG/CSRは試したことがあったのだけど、ISRは初めてだった。 ユーザー投稿型サービスかつ高速なレンダリングが求められるようなサービスだとISRも便利なのかもしれない。知識として頭の片隅に残しておく。

4章

今日の学習ポイント。styled-component や Storybookへのコンポーネント登録はあまり経験がなかった部分だったので重点的にキャッチアップ。 一方で jest や React Testing Library は多少馴染みがあったのでサラッと流す。

ここまで手を動かしながら読み進めておかげで、Hooksも手に馴染んできた。

5 ~ 7章

5章は写経しながら進めていたもののESLint関係のライブラリを npm install で列挙するあたりで挫折。 サンプルリポジトリpackage.json をコピペして進めようかとも思ったが、その後の記述量もかなり多そうだったので、リポジトリをcloseしてアプリケーション挙動やサンプルコードを眺める方針とした。

読み進める中で json-server や SWR のような便利そうなライブラリを知れたのはよかった。

6章はStorybook を起動してコンポーネントを眺めた程度で終了。実際にコンポーネント作成する時に戻ってくる。 MUIやReactstrapのようなUIライブラリを使わずに独自のデザインシステムを構築する場合は、結構気合入れて取り組まないと大変そうだなという感想。

7章も軽く読んで、実運用する段になったら再読することにした。個人開発ならVercelを使うこともあるかもしれないけれど、業務だと別のインフラ環境にデプロイすることになりそう。

感想

5~7章のアプリケーション開発の

  • 現時点での最新版のReact/Next.jsを使って
  • 現場で発生する要件をカバー(認証あり、複数のエンドポイント利用(POST含む)、ファイルアップロード、etc...)した中規模なアプリケーションを
  • 自作のデザインシステムで実装している

という組み合わせが、この本のよさを際立てていると感じた。

このバランスを取るために著者の方は構成に苦労しただろうなと思った。 (シンプルにするならGETだけのアプリケーションを取り上げるのだろうけど、それだと認証もFormバリデーションも不要になってしまうし、MUIなどのライブラリを使ったら見通しは良くなるけれど見栄えはサンプルアプリケーションの域を出ないし、、、)

サーバーサイドの複雑さは json-server などで隠蔽しつつ、フロントエンドのロジック・UIに注力した構成は、何かの折で参考にさせてもらいたい。

6章を丸々使ってUIコンポーネントの解説をしているなど、アプリケーションロジックに加えてUIコンポーネントの開発・管理手法に比重を置いているのが印象的だった。 逆に、APIクライアントのような説明は必要最小限に留められていて、飛ばし読みをすると実アプリケーションへの組み込みの全体像が掴みづらいかも知れない。 5章でSWRの紹介があり、6章で fetcher 関数やAPIクライアントを作るのだけれど、それを使うのは Atom / Molecules のコンポーネントを作った後になっていためだ。

個人的にクライアントアプリケーションの学習をする際には、APIクライアントの設計が特に気になることもあり、APIクライアントを作った直後に SWR や Context とのつなぎ込みについて補足を入れてもらえると嬉しかったなと思った。(とはいえ、リポジトリのコードを追ったら短時間で理解できたので大きな問題ではない)

Typescript, Hooks, テストのようなアプリケーションロジックによった部分は読み飛ばしつつ、Storybook / Atomic Design に時間をかけて理解を深められたのが、今の自分に足りていない知識を補うためにちょうどよく、「アプリケーションロジックの実装はできるけれど、UIコンポーネントやデザイン実装は苦手」という人にもおすすめできる。

TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発[1 ~ 3.5章]

『TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発』を読んでいる。

私がフロントエンド開発に注力していたのは2016年 ~ 2018年3月頃。当時はReact Nativeを使ったアプリ開発や、jQueryベースで作られたサービスを部分的にVue.jsで置き換えるような仕事をしていた。 当時からTypescript / Reactは存在していたものの、JS型付けの選択肢としてはFlowが有力な選択肢として残っていたし、ビルドツールもWebpackが優勢だったもののBrowserifyを採用しているプロダクトも多かった。SPAのフレームワークもReact, Vue.jsに加えて、Angular2, Riot.js, HyperApp(builderscon 2017 での発表が印象的だった) など大小様々な選択肢があった時代だった。

当時書いたフロントエンドのコードはほぼ残っていないのだけど、FluxアーキテクチャRuby実装した形跡が残っていた。

GitHub - kuranari/flux-ruby: 【学習用】FluxアーキテクチャのRuby実装

その後の転職を機にフロントエンド開発からは遠ざかっていた。 その間に Hooks や Context など新しいAPIが出ていたり、エコシステムもややデファクトが決まりつつある状態になってきて、周回遅れ感が否めないので今年の夏休みを使ってキャッチアップしている。

今日は1章から3.5章までを軽く手を動かしながら読んだ。明日は「4章: コンポーネント開発」から読み始め、3.6 Next.js入門に戻り、5章以降のアプリケーション開発に入っていこうと思う。 直近で必要になるのはSPAのReactの知識だけなのでNext.jsは必須ではないのだけれど、パラパラめくった感じそこまで無駄になる知識もなさそうなので、一通り読んでみることにする。

以下、読んでみた感想。

1章: Next.jsとTypeScriptによるモダン開発

4 ~ 5年フロントエンド開発から離れていた身としては、ここ数年の技術の変遷を総括してもらえるこの章はありがたいとともに懐かしさを感じた。 冒頭に書いたような技術選定の話もだし、懐かし話として楽しく読めた。

2章: TypeScriptの基礎

Typescript は軽く触ったことがあったので、軽く気になるところを動かす程度で。

3章: React/Next.jsの基礎

ゆるふわな理解だった Hooks の学習。useReducer は今回初めて使った。

useEffect の節では React v18 の <React.StrictMode>useEffect の組み合わせの影響か、サンプルコードそのままだとLocalStorageに値を保存してもリロードのたびにLocaleが en-US になってしまう挙動に悩まされた。

いろいろ試してみたのだけど

で解決できることがわかった。

React18におけるuseEffectの挙動の変化もコラムの情報から当たりがつけられた。出版日が2022/08/06なのに、React v18の情報を含んでいるのがすごい。

というわけで、今日は Typescript と React の API についてざっと調査ができたので、明日以降はコンポーネントカタログや実際のアプリケーション開発について読んでいこうと思う。

RailsプロジェクトのCircleCI2.0設定ファイルを定義した

自分のサンドボックス用プロジェクトのCircleCIを2.0移行したのでそのメモ。

今回の内容は下記のthoughtbotの記事を参考にすれば動作するはずだし、必要なことは書かれている。 robots.thoughtbot.com

作業したプルリクは以下

Add config file for CirclrCI 2.0 by kuranari · Pull Request #17 · kuranari/mblog · GitHub

Docker image

imageはcircleci/ruby:2.5.0-node を使用した。

circleci/ruby:2.5.0ではないのは、nodeの実行環境が必要なRubyのGem uglifierに依存しているため。

他コンテナの起動を待つ

テスト用のコンテナよりもDBコンテナの起動に時間がかかり、DBへの接続が出来ずエラーになってしまうことがある。(このようなエラーとなる。)

そのためdbの起動をdockerizeコマンドで待つようにした。

Add config file for CirclrCI 2.0 by kuranari · Pull Request #17 · kuranari/mblog · GitHub

thoughtbotのブログの設定ファイルにもその旨書かれているが自分の携わる他プロジェクトでは記述がなかったため当初dockerizeをしていなかった。 そのプロジェクトではテスト用コンテナでミドルウエアやnpmのインストールのような多少時間がかかる処理が発生するため、MySQLコンテナの起動待ちとなる状況は発生しないようである。

workflow化

現状のCIで行うことはテスト実行のため実質不要だが、興味があったのでworkflow化をしておいた。 workflowを使うと、複数のタスクを並列に実行させたり、直列に定義された各Jobの実行有無を条件によって切り分けられる。

並列実行の例でいうとRuby2.3, 2.4, 2.5の3バージョンを対象に並列でテストができるようになる。 直列実行の例だとbuild, test, deployの3つのJobがある場合、featureブランチではbuild, testまでを行い、masterブランチでのみbuid, test, deployを行うことができる。

またworkflowを定義することでcronのようなスケジュール実行を行うことができる。

この辺は下記の記事が詳しい。 qiita.com

まとめ

RailsプロジェクトのCircleCI2.0設定ファイルの記述についてまとめた。 今回はシンプルにrspecを実行するだけの設定にとどまっているが、今後デプロイ設定なども試していきたい。

Maven + Lombokを使うまでのメモ

Mavenで管理しているプロジェクトでLombokを使うための設定方法のメモです。 この記事では

の2つの手順を踏んでいます。 なおIntelliJなどのIDEでLombokを使うためには別途設定が必要になります。

事前条件

javaとmavenがインストールされていること。

% java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

% mvn --version
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T03:33:14+09:00)
Maven home: /usr/local/Cellar/maven/3.5.4/libexec
Java version: 1.8.0_162, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.4", arch: "x86_64", family: "mac

Mavenプロジェクトの作成

% mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

...

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.743 s
[INFO] Finished at: 2018-08-13T15:53:17+09:00
[INFO] ------------------------------------------------------------------------

*Mavenのインストール直後だと時間がかかる。

生成されたファイルは以下の通り。

% tree
.
└── my-app
    ├── pom.xml
    └── src
        ├── main
        │   └── java
        │       └── com
        │           └── mycompany
        │               └── app
        │                   └── App.java
        └── test
            └── java
                └── com
                    └── mycompany
                        └── app
                            └── AppTest.java

12 directories, 3 files

Mavenのテンプレートをビルドする

% cd my-app
% mvn package
[INFO] Scanning for projects...
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.509 s
[INFO] Finished at: 2018-08-13T15:59:04+09:00
[INFO] ------------------------------------------------------------------------

コンパイルした実行ファイルの起動

% java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
Hello World!

ここまででMavenプロジェクトの作成は終了です。 続いてlombokの設定を行っていきます。

POM.xmlの編集

% vi pom.xml

下記の依存関係を追加

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.2</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

App.javaでlambokのアノテーションを仕様

% cat src/main/java/com/mycompany/app/App.java
package com.mycompany.app;

import lombok.Data;
import lombok.val;

@Data
class User {
    private final int id;
    private final String name;
}

public class App
{
    public static void main( String[] args )
    {
        val user = new User(1, "Alice");
        System.out.println(user);
    }
}

再実行

mvn package
% java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
User(id=1, name=Alice)