こんにちは、エンジニアの尾宇江です。
goでプルリク作ってリリース作業を改善してみた。のエントリーに引き続き、Goを使ったちょっとした改善をした話です。
最初に
書いたコードをcommitした後、「あープリントデバッグで仕込んでたvar_dump消し忘れた」ってことありますよね?
あと、「設定ファイルのURLをexample.comのままにしてcommitしちゃった」ということも良くありますよね?
私は日常的にやらかしていました…
対策
気をつけても抜ける時は抜けるので、自動化しよう!!
ということで、CIでチェックするようにしました。
対象となるリポジトリはPHP(Laravel)なのですが、今回はYappliのメイン言語のGoをつかってチェックすることにしました!
実装したコード
プリントデバッグが残ってないかチェックするスクリプト
package main import ( "bufio" "errors" "flag" "fmt" "os" "path/filepath" "strings" ) var directories = flag.String("directories", "", "directories to search. if you specify more than one, separate them with commas. eg. app,vendor") func main() { flag.Parse() if err := Main(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func Main() error { find := false for _, v := range strings.Split(*directories, ",") { b, err := walk(v) if err != nil { return err } if b && !find { find = true } } if find { return errors.New("found a print debug, check the output above") } return nil } func walk(root string) (bool, error) { fmt.Printf("# root: %s\n", root) find := false err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { if err != nil { return err } switch filepath.Ext(path) { case ".php": fmt.Printf("## path: %s\n", path) b, err := search(path) if err != nil { return err } if b && !find { find = true } } return nil }) return find, err } func search(path string) (bool, error) { file, err := os.Open(path) if err != nil { return false, err } fs := bufio.NewScanner(file) i := 0 find := false for fs.Scan() { i++ if isPrintDebug(fs.Text()) { fmt.Printf("- [ ] find print debug@%s:%d, %s\n", path, i, strings.TrimSpace(fs.Text())) find = true } } return find, fs.Err() } func isPrintDebug(s string) bool { for _, v := range []string{"print", "print_r", "var_dump", "var_export", "echo"} { if strings.Contains(s, v) { i := strings.Index(s, v) + len(v) // コメント行は無視する if strings.TrimSpace(s)[:2] == "//" { continue } // ユーザ定義関数は無視する if s[i:i+1] != "(" && s[i:i+1] != " " { continue } switch v { case "print_r", "var_export": // trueがないとNG return strings.Index(s[i:], ", true)") == -1 default: return true } } } return false }
envファイルにexample.comが含まれていないかをチェックするスクリプト
package main import ( "bufio" "fmt" "os" "strings" ) func main() { if err := Main(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func Main() error { if err := checkNGWords(".env.local"); err != nil { return err } if err := checkNGWords(".env.prod"); err != nil { return err } return nil } func checkNGWords(name string) error { file, err := os.Open(name) if err != nil { return err } fs := bufio.NewScanner(file) i := 0 for fs.Scan() { i++ for _, v := range ngWords() { if strings.Contains(fs.Text(), v) { return fmt.Errorf("%s found on line:%d@%s", v, i, name) } } } return fs.Err() } func ngWords() []string { return []string{ "example.com", } }
GitHub Actionsの設定
name: Search Print Debug on: push: jobs: setup: runs-on: ubuntu-latest steps: - uses: actions/setup-go@v2 with: go-version: ^1.17 - uses: actions/checkout@v2 search: needs: setup runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - run: go run tools/search_print_debug/main.go -directories=app,tests
今回はビルドせずに直接ファイルを実行しています。
config-checkerもrunの部分が、- run: go run tools/config-checker/main.go
となるだけなので、詳細は割愛します。
ディレクトリ構成
$ tree -a -P 'search_print_debug.yml|check_config.yml|main.go' --prune . ├── .github │ └── workflows │ └── search_print_debug.yml └── tools ├── config-checker │ └── main.go └── search_print_debug └── main.go
まとめ
という感じで、簡易的ではありますがvar_dumpの消し忘れや、残しておきたくない設定値のチェックの自動化ができるようになりました!
ちょっとした改善ですが、誰でもやりかねないミスをチェックしてくれるということで、 導入後は結構な安心感を生み出してくれています!