2021年2月末でRxJava 2.xがEnd-of-Life (EoL)を迎えた

github.com

⚠️ This is the last planned update for the 2.x version line. After February 28, 2021, 2.x becomes End-of-Life (EoL); no further patches, bugfixes, enhancements, documentation or support will be provided by the project.

これまでAndroidアプリ開発での非同期処理の定番として使われていたRxJavaですが、その2系バージョンがEoLを迎えていました。Android JetpackでもKotlin Coroutinesを使ったAPIが増えてきているなど、最近はCoroutinesを使うことが増えてきているので、ひとまず最新の3.xに移行しつつ、Coroutinesに置き換えていきたいところですね。

Reactコンポーネントの定義にFCではなくVFCを使う

簡単に言うと

  • React.FCのpropsの型定義には暗黙的にchildrenが含まれてしまう
  • 今後@types/reactの18以降ではReact.FCにchildrenは含まれなくなる予定(破壊的変更)
    • これを先取りして@types/react16.9.48からReact.VFC/React.VoidFunctionComponentが追加されており、こちらではchildrenが含まれない

ということで

  • @types/react 18の時代を先取りし、基本的には全てをReact.VFCで定義して、childrenが必要なコンポーネントではpropsに明示的にchildrenを定義しましょう
  • React.FCからchildrenが消えた暁にはReact.VFCは非推奨になるはずで、その時はVFCFCに一括置換すれば問題ないはず

ということを会社のチーム内で話した。

React用のカルーセルコンポーネント

ざっと目に着いたものをリストアップしてみる。スターの多さでいうとreact-slickが最強のようだけど、issueの数も200件超と多いのは気になる。そこまでデファクトスタンダードと呼べるものはないのだろうか?


github.com


github.com

  • 「Server side rendering compatible」とREADMEで言及されている

github.com

  • SSRについては特に言及されていない

github.com

  • SSRはサポートしていない(のでNext.jsならdynamicでラップするようにとのこと)
    • we recommend Next.js as @brainhubeu/react-carousel currently doesn't work on the server side so it must be rendered on the client side (maybe we'll provide server-side working in the future).

Amazon RDS/Amazon AuroraのデフォルトタイムゾーンはUTC

備忘録です。

By default, the time zone for an RDS MySQL DB instance is Universal Time Coordinated (UTC). You can set the time zone for your DB instance to the local time zone for your application instead.

By default, the time zone for an Amazon Aurora DB cluster is Universal Time Coordinated (UTC). You can set the time zone for instances in your DB cluster to the local time zone for your application instead.

昔はタイムゾーンは正攻法では変更できなかったようだが、2015年12月に変更できるようになっていた。

dev.classmethod.jp

aws.amazon.com

Amazon ECRのライフサイクルポリシーのタグプレフィックスリストはOR条件ではなくAND条件

突然のAWSの話題です。

Amazon ECR (Elastic Container Registry)はDockerコンテナレジストリのサービスです。コンテナイメージをどんどんプッシュしていくと無限に溜まっていってそれだけストレージコストが掛かってしまうので、不要になったイメージは適度に削除したいものです。ECRではそのためにライフサイクルポリシーという仕組みがあり、

  • タグの有無
  • タグプレフィックスリスト
  • イメージの数、もしくはイメージがプッシュされてからの時間

といった条件を指定してルールのリストを作り、各ルールにマッチしたイメージは保護し、どのルールにもマッチしなくなったイメージは削除する、ということができます。

ここ最近ECRを触っていて見かけた事例に、タグプレフィックスリストの使い方が間違っているものがありました。タグプレフィックスリストはドキュメントに次のように説明があります。

Only used if you specified "tagStatus": "tagged". You must specify a comma-separated list of image tag prefixes on which to take action with your lifecycle policy. For example, if your images are tagged as prod, prod1, prod2, and so on, you would use the tag prefix prod to specify all of them. If you specify multiple tags, only the images with all specified tags are selected.

リストに複数のプレフィックスを指定した場合、全てのプレフィックスを満たしたイメージが選択される、つまりOR条件ではなくAND条件ということです。

例えばproduction環境とstaging環境へのデプロイ用のイメージは保護しよう、という時になんとなく使うとこのリストを["production-", "staging-"]と指定してしまうかもしれませんが、これだと両方を満たしたイメージがなくどちらも保護されない・もしくは古いイメージを削除できない、ということになってしまいます。この場合は["production-"]を指定するルールと、["staging-"]を指定するルールを別々に作るのが正解です。

例として「Filtering on multiple tags in a single rule」というのも挙げられていますが、意外とこういうのは見落としがちかもしれません。ドキュメントが用意されているものはすっ飛ばさずにちゃんと読んで、余計な回り道をしないようにしていきたい今日この頃です。

GitHub Actionsのpathsによる条件付き実行にまつわる落とし穴と困りごと

paths と言っているのはこれです。

https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestpaths

When using the push and pull_request events, you can configure a workflow to run when at least one file does not match paths-ignore or at least one modified file matches the configured paths. Path filters are not evaluated for pushes to tags.

GitHub ActionsでファイルAが更新されているがファイルBが更新されていない時だけ実行する、を実現する

GitHub Actionsの on: pushon: pull_rerequest のトリガーには paths/paths_ignore という機能があり、特定のファイルパスが変更された時だけワークフローを実行できます。

# 例えばiOSとAndroidのmonorepoで、ios以下が変更された時だけiOSのテストを実行したい
on:
  push:
    paths:
      - 'ios/**'

paths/paths_ignoreには配列で複数のパス指定・globパターン指定ができ、そのうちのどれか1つにでもマッチするとワークフローが実行されます。しかしこの機能には1つ弱点があり、pathspaths_ignore を同時に使うことができません。つまり、ファイルAが変更され・かつ・ファイルBが変更されていない、という条件が記述できません(と認識しています)。

You can exclude paths using two types of filters. You cannot use both of these filters for the same event in a workflow.

今回はこれを乗り越える方法の紹介です。trilom/file-changes-actionというアクションを使用して、ジョブ内で自分でファイル差分をチェックしてみましょう。ここではiOSアプリのリポジトリで、Podfileが更新されているがPodfile.lockが更新されていない時、ということにしてみます。

name: Update Podfile.lock

on:
  pull_request:
    paths:
      - Podfile

jobs:
  precheck:
    runs-on: ubuntu-latest
    outputs:
      files_changed: ${{ steps.file_changes.outputs.files }}
    steps:
      - uses: actions/checkout@v2
      - id: file_changes
        uses: trilom/file-changes-action@v1.2.3

  update:
    runs-on: macos-latest
    needs: precheck
    if: contains(fromJson(needs.precheck.outputs.files_changed), 'Podfile.lock') == false
    steps:
      - uses: actions/checkout@v2
      - run: pod install
      - uses: stefanzweifel/git-auto-commit-action@v4.2.0
        with:
          commit_message: Update Podfile.lock
          file_pattern: Podfile.lock

まずは前提条件としてpathsPodfileを指定して、「Podfileが更新されている」ことをワークフローレベルでフィルタリングします。

ここからが本題です。precheckジョブで、trilom/file-changes-actionを使ってファイル差分を取得します。そしてそのステップのoutputジョブのoutputに保存して、後続のジョブからアクセスできるようにします。ここでジョブを分割しているのは

  • 後続の処理が複数ステップに渡る場合、それぞれのステップにifを書くのが面倒・メンテナンスしにくい
  • 今回の例では後続の処理にmacOSが必要だが、macOSは課金が高額(Ubuntuの10倍!)なので、ファイル差分のチェックはUbuntuで行う

ためです。

updateジョブはneedsを使ってprecheckジョブの終了後に直列で実行されるようにします(デフォルトでは複数のジョブは並列で実行されます)。次にジョブレベルのifで、Podfile.lockが変更されていない、という条件を書きます。needs contextを使うと、前段のジョブの実行結果やoutputsにアクセスできます。ここではprecheckジョブでoutputsに保存したtrilom/file-changes-actionの出力結果を使用し、contains関数で変更されたファイル名の配列にPodfile.lockが含まれるかを確認します。

後は実処理として pod installしてPodfile.lockを更新してから、stefanzweifel/git-auto-commit-actionを使ってプルリクエストを作成しています。

こうして「Podfileが更新されているがPodfile.lockが更新されていない時」という条件を実現できました。めでたしめでたし。色んなアクションを組み合わせて柔軟なジョブ制御を実現していきましょう。