GitHub Actionsには、ワークフローの実行時に渡すパラメータを定義するinputs
があります。このinputs
を使うことで外部から変数を受け取ることができます。
今回はinputs
で渡した変数を環境変数として受け取れる時と受け取れない時の違いについてです。
inputsを環境変数として取得する
inputsのドキュメントに詳細がありますが、カスタムアクションを呼び出す時に指定されたinputsはカスタムアクション内で環境変数INPUT_<VARIABLE_NAME>
として取得できます。例えばカスタムアクションが次のinputsを定義している場合、INPUT_NUM-OCTOCATS
やINPUT_OCTOCAT-EYE-COLOR
として環境変数に自動登録されます。
inputs: num-octocats: description: 'Number of Octocats' required: false default: '1' octocat-eye-color: description: 'Eye color of the Octocats' required: true
GitHub ActionsのTypeScript SDKであるactions/toolkitはこの仕組みを利用して、core.getInput
でinputsを取得できます。
When you specify an input, GitHub creates an environment variable for the input with the name INPUT_<VARIABLE_NAME>. The environment variable created converts input names to uppercase letters and replaces spaces with _ characters.
// これでinputsに対して渡された値を取得できる core.getInputs('num-octocats')
同SDKのcore.getInputs
の実装はドキュメントの環境変数変換に沿った実装です。
export function getInput(name: string, options?: InputOptions): string { const val: string = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '' if (options && options.required && !val) { throw new Error(`Input required and not supplied: ${name}`) } if (options && options.trimWhitespace === false) { return val } return val.trim() }
inputsが環境変数に自動登録される仕組みは便利です。たとえSDKがなくても、アクションで自前処理を書いたときにinputsをパラメーターとして受けらずに環境変数から取ればよくなります、ラクチン。
// C#なら Environment.GetEnvironmentVariable("INPUT_NUM-OCTOCATS")
# Bashなら echo ${INPUT_NUM-OCTOCATS}
inputsを環境変数からとれる場合ととれない場合
inputsコンテキストはGitHub Actions的にはいろいろなトリガーで使われます。
- カスタムアクション (JavaScript, TypeScript)
- カスタムアクション (Docker)
- カスタムアクション (Composite)
- Workflow Dispatch
- Workflow Call
- 他
この中で、inputsを環境変数が自動登録されるのはカスタムアクション (JavaScript, TypeScript) とカスタムアクション (Docker) だけで、他のトリガーでは環境変数に変換されません。
トリガー | inputsをINPUT_ 環境変数取得 |
---|---|
カスタムアクション (JavaScript, TypeScript) | 〇 |
カスタムアクション (Docker) | 〇 |
カスタムアクション (Composite) | × |
Workflow Dispatch | × |
Workflow Call | × |
CompositeアクションでINPUT_
環境変数に登録されないことはドキュメントに記載されていますが、Workflow DispatchやWorkflow Callで取得できないことはドキュメントがないので注意しましょう。Composite ActionsでINPUT_
環境変数がないIssueはあるのですが、Workflow CallやWorkflow Dispatchに来る日はなさそう。
If the action is written using a composite, then it will not automatically get INPUT_<VARIABLE_NAME>. With composite actions you can use inputs Accessing contextual information about workflow runs to access action inputs.
WorkfloCallやWorkflowDispatchでinputsを環境変数で取得したかった
WorkflowCallで共通化している処理をC#で書いていて、「inputsを引数ではなくSDKからならとれるの!?」と思って試して取れなかったので調べてました。core/toolkitをC#に移植したIEvangelist/dotnet-github-actions-sdkがあるのですが、ICoreService.GetInput("num-octocats")
でとれない、悲しい、しょうがない。
カスタムアクション(TS/TS/Docker)に限定しているのは仕様を考えるとしょうがなさそうです。例えば、WorkflowCallからCompositeActionsを呼び出すとき、両方で同じinputstag
を定義しているとしましょう。この場合、Composite ActionsのINPUTS_TAG
にどの値を入れればいいか決定できないかな、と。後勝ちというルールを設けてもよさそうですが、Issueで何とかしてとかいわれるのが目に見えています。
WorkflowCallやWorkflowDispatchでinputsを使う場合は、引数で渡すか、環境変数に自前で渡すしかないです。
# 引数で渡す run: dotnet run -- "${{ inputs.tag }}" # 環境変数で渡す run: dotnet run env: INPUT_TAG: ${{ inputs.tag }} # 環境変数で自分で渡すならいっそINPUTなしでもいいのでは run: dotnet run env: TAG: ${{ inputs.tag }}
それか、カスタムアクション(docker)にするか... というのはやりすぎ感じあるんですよねー。
まとめ
WorkflowCallでinputsが使われたらINPUT_
で取りたかった。値の受け渡しが楽になるのになー、と思っていたらだめなのでした。無念。