GAEのapp.yamlのenv_variablsをローカル環境で使い回したかった

1 min read読了の目安(約1400字

背景

本番とステージングをGAEで運用してるnodeのアプリケーションで、環境ごとにコード変更したくないので、アプリケーションコードでは環境変数を参照するようにして、app.yamlを環境毎に用意、env_variablesを定義してデプロイ時に設定されるようにしてた。

ステージング用

runtime: nodejs12
instance_class: F2
env_variables:
  BUCKET_NAME: "staging-gcs-bucket"

本番用

runtime: nodejs12
instance_class: F4
env_variables:
  BUCKET_NAME: "production-gcs-bucket"

みたいな。

それは良いけど困ったゾイ

GAEにデプロイする分には何も考えなくていいのでパラメータ指定を間違えることはないものの、同じコードをローカルやDockerコンテナ内で動かそうとしたときに、いちいちexport BUCKET_NAME=xxxとかしたりしてめんどくさいなぁって思ってた。JSONみたいなエスケープしないといけないパラメータだとかなり辛い。

app.yamlやstaging.yamlをそのまま使えるようにする

辛かったので素直にアプリケーションコードの先頭でyamlを読んで環境変数を上書きするようにした。

app.js

async function setEnvVariablesFromYaml(filename){
    const jsYaml = require("js-yaml");
    const fs = require("fs").promises;
    const yamlData = await fs.readFile(`${process.cwd()}/${filename}`, 'utf-8');
    const config = jsYaml.safeLoad(yamlData);

    // yamlから環境変数を設定する
    Object.entries(config.env_variables).map((e)=>{
        process.env[e[0]] = e[1];
    });
}

if(process.env["NODE_ENV"] === "local"){
    const filename = process.env["NODE_YAML_FILE"];
    setEnvVariablesFromYaml(filename);
}

実行時

ローカル実行フラグと読み込みたいファイル名を環境変数で渡してやる

export NODE_ENV="local" && NODE_YAML_FILE="staging.yaml"; node app.js

これでenv_variablesがそのまま使えるし、同じようにテストコードの前処理とかにも対応できる。素直に良き。

所感

bashにexport書き散らかして脳筋運用してたので、もっと早く気が付けばよかった。
yamlに合わせてbashをメンテしなくていいのがタイポに神経すり減らさなくてとてもよい。

ちくしょう。みんな知ってるならもっと早く教えといてよ…!!!