最近のプロジェクトでは、.envファイルを各自用意し、それを読み込んだり、docker-composeに読み込ませたりすることで、設定を行うことはよくある。便利ではある反面、各種環境の設定の差によって問題を引き起すこともある。例えばテストなどはそうだろう。ローカルで実行したテストは成功するのにGithub Actionsで実行したテストは失敗する。またはその逆の状況にしばしば陥いる。それらの理由はいくつかあるが、環境変数が原因であることも多い。ただ、環境変数の管理は本当に面倒で、開発者が複数いる場合、知らない間に環境変数が増えたりする。しかし、ローカル環境の設定として生成した.envファイルはそれらに追従しない。結果としてローカルの環境変数の設定が漏れ、ローカルで実行したテストは失敗するが、Github Actions上ではテストが成功しているという状況になる。.envファイルに何が記載されているのかということについて、把握できればそれにこしたことはないが、この認知能力が下がった状態では当然把握できる訳がない。そこでGithub Actionsの設定を解析し、環境変数の設定を読み込んだり.envファイルを出力するようなEmacs Lispを実装することにした。
(defvar github-actions-config-yaml "")
(defvar github-actions-config-object-path '(jobs test env))
(defun github-actions-parse-env ()
(let ((ga-env-list nil))
(maphash (lambda (sym val)
(push (format "%s=%s"
(symbol-name sym)
(cond ((stringp val) val)
((eq nil val) "None")
((eq t val) "True")
(t (json-encode-string (json-parse-string val)))))
ga-env-list))
(seq-reduce (lambda (val sym) (gethash sym val))
github-actions-config-object-path
(yaml-parse-string
(with-current-buffer
(find-file--read-only
#'find-file-noselect
github-actions-config-yaml
nil)
(buffer-substring-no-properties (point-min) (point-max))))))
ga-env-list))
(defun github-actions-export-env ()
(interactive)
(let ((envlist (github-actions-parse-env)))
(with-current-buffer (get-buffer-create "*github actions environment variables*")
(mapc (lambda (line) (insert (format "%s\n" line)))
envlist))))
github-actions-config-yaml
に Github Actions
の設定へのパスを指定し、 github-actions-config-object-path
に Github Actions
の設定内のオブジェクト名を指定する。例えば次のような設定となっている場合、 '(jobs test env)
と指定する。
jobs: test: env: foo: bar
設定が完了したら M-x github-actions-export-env
を実行すると、 *github actions environment variables*
バッファを作成し、そこに設定をdotenv形式で記述する。それ以降は必要に応じて、ファイルに保存するなどを各自の要求に応じて行う。