do_su_0805's blog

dairyquestions は typo です。

ファイル名が意図しないものがあったら異常終了させるワンライナー、およびそれを GitHubActions で動かすまで

TL;DR

  • find は対象が見つかろうが見つからなかろうが exit 0 する
  • find を異常終了させるには -exec false {} + が楽そう
  • せっかくなので GithubActions で動かしてみたよ

ことのあらまし

  • 特定の拡張子のファイルを見て処理を行う仕組みがあった。
  • ある時、ファイルをアップロードして処理されないと言う事件が起きた。
    • 原因が拡張子の誤りだったんだけど、一文字間違いくらいでなかなか気づけなかった。
  • これは人間が確認すべきじゃないので CI に載せたくて、とりあえず「特定の拡張子でないファイルが現れたら異常終了する」術がないかなぁと調べ始めた

「特定の拡張子でないファイルが現れたら異常終了する」術

例として、 .json 以外出て来れられたらおかしい世界を考える

  • ぱっと思いついたのは find . | grep -v "\.json$" みたいな話
    • だけど grep は「条件に引っ掛かったら exit 0」という世界なので、日頃問題ない世界では exit 1 される
    • いろいろパイプなり、いっそスクリプトにするなどしたら使えるけど今回はもうちょっと気楽にやりたかった
  • 次に思いついたのは 「 find 自体でどうにかできないか? 」だった
    • 試してみたところ、どうやら「コマンドオプション自体がエラーじゃないととにかく正常終了する」世界
      • そりゃそうだ、一覧を出すだけだからね
  • 試しに 「find returncode」 とかで調べたところ、こんな記事が引っ掛かった
  • ちょうど同じニーズっぽい。中段くらいにある false を使う例がスッキリしていたので試したみたところ、ちゃんと「 json しかない時は正常終了し、json 以外がある時は異常終了する」世界ができた。
    • find -not -name "*.json" -exec "false {} +"
  • とはいえ、CI で実行時に失敗だけ言われても辛いので、見つけたファイルも出すようにした。
    • find -not -name "*.json" -exec "false {} +" -print

術が生まれたので GithubActions で自動検知させてみた

do-su-0805/Unintentional_filename_detection_example に例をおいてみました。

やっていることはこんな感じ。先ほど生み出した術を走らせる最小構成です。jsondir というディレクトリに *.json 以外が紛れ込んだら落ちる CI が完成です。

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
jobs:
  detector:
    name: Detect unintentional file ( not "*.json" )
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: exec detection
      working-directory: jsondir
      run: find . -type f -not -name "*.json" -exec false {} + -print

実際に動いている例としては unintentional file exemple by do-su-0805 · Pull Request #1 · do-su-0805/Unintentional_filename_detection_example に用意しました。json フォルダに yaml をおいてしまったという世界です。

f:id:do_su_0805:20200703204150p:plain
検知例。ちゃんと test.yaml を検知してエラー落ちしていますね。

こういう細かいところを機械がみてくれるのは心地よいですね。