Skip to Content
リファレンスYAMLフィールド

YAML設定リファレンス

Probeがワークフローファイルから読み取るキー、式が評価されるコンテキスト、バリデーションの規則をまとめます。

ワークフローの構造

以下の雛形は、ワークフローファイルに書けるプロパティと、それぞれの位置を示しています。

name: string # 必須: ワークフロー名 description: string # 任意: ワークフローの説明 vars: # 任意: ワークフロー変数 key: value secrets: # 任意: 出力で伏せる環境変数 - NAME defaults: # 任意: すべてのジョブに効く、アクションごとの with の既定値 http: url: string actions: # 任意: 外部アクションに付ける名前 name: string jobs: # 必須: ジョブのリスト - name: string # 必須: ジョブ名 id: string # 任意: ジョブ ID。needs から参照する needs: [job-id, ...] # 任意: 依存するジョブ always: boolean # 任意: 依存先のジョブが失敗しても実行する skipif: expression # 任意: 真ならジョブをスキップ fail_fast: boolean # 任意: 失敗したステップより後のステップをスキップ defaults: # 任意: アクションごとの with の既定値 http: url: string repeat: # 任意: ジョブを繰り返す count: integer interval: duration async: boolean warmup: integer test: expression # 任意: 全回に対するアサーション baseline_test: expression # 任意: 以前の実行と比べるアサーション steps: # 必須: ステップのリスト - name: string # 任意: ステップ名 id: string # 任意: ステップ ID。outputs をこの ID から読める uses: string # 必須: アクション名、または actions で付けた名前 with: # 任意: アクション引数 key: value test: expression # 任意: アサーション echo: string # 任意: レポートに出力する文字列 vars: # 任意: ステップ変数 key: value outputs: # 任意: 後続へ渡す値 key: expression skipif: expression # 任意: 真ならステップをスキップ wait: duration # 任意: 実行前の待機 timeout: duration # 任意: ステップのタイムアウト iteration: # 任意: 要素ごとにステップを繰り返す。 - key: value # リスト、またはリストになるテンプレート retry: # 任意: 失敗時のリトライ max_attempts: integer interval: duration initial_delay: duration

jobsはリストです。ジョブIDをキーにしたマップで書くと読み込みに失敗します。

トップレベルのenvはありません。環境変数はvarsを通して読みます。

トップレベルのプロパティ

ワークフローファイルのルートには、jobsのほかに6つのプロパティを置きます。名前、説明、開始時点の値、そのうち表示してはいけない値、ステップが共有するwithの値、そして外部アクションに付ける名前です。

name

型: String(必須) 説明: ワークフロー名。レポートの先頭に表示されます。

name: "API Health Check"

description

型: String(任意) 説明: ワークフローの説明。

description: | 本番 API を確認します。 - エンドポイントの死活 - レスポンスタイム

vars

型: Object(任意) 説明: すべてのジョブとステップからvars.<name>で参照できる変数です。

環境変数が見えるのはvarsの中だけで、変数名をそのまま書いて参照します。値は最初のジョブが始まる前に一度だけ評価されます。

vars: # 環境変数を読む api_url: "{{API_URL}}" # デフォルト付き timeout: "{{REQUEST_TIMEOUT ?? '30s'}}" # 読み込み時に計算する run_id: "{{random_str(8)}}" # ネストした値も書ける auth: user: "{{API_USER}}"

varは、probe --var api_url=http://localhost:8080 workflow.ymlのようにワークフローの実行時に与えることもできます。与えた値はここに書いた値の代わりにそのまま使われ、それを読む他のvarもその値を読みます。--varと、環境にない変数をファイルから読む--env-fileを参照してください。

ステップの式から環境変数を直接読むことはできません。式のコンテキストにenvは存在しないため、varsに置いてvars.<name>で参照します。

ある変数から別の変数をvars.<name>で参照できます。参照先がブロックのどこに書かれていても構いません。各変数は参照している変数の後に評価されるため、ランダムなパスワードのように一度だけ計算される値は、それを使って組み立てたどの変数でも同じになります。

vars: http_port: "{{HTTP_PORT ?? '18080'}}" base: "http://localhost:{{vars.http_port}}" password: "{{PASSWORD ?? random_str(24)}}" basic_auth: "Basic {{encode_base64('alice:' + vars.password)}}"

直接または他の変数を経由して自分自身を参照する変数があると、最初のジョブが始まる前にvars: circular reference: a -> b -> aのように経路を示すエラーでワークフローが止まります。変数でない名前は nil として読まれるので、vars.<name> ?? 'default'はデフォルト値になります。vars[KEY]のように実行時に決まるキーでvarsを読む変数は、他のすべての変数の後に評価されます。テンプレートファイルから作る変数のようにtemplateを呼ぶ変数は、テンプレートが何を読むかが実行するまで分からないため、templateを呼ばないすべての変数の後に評価されます。テンプレートが、templateを呼ぶ別の変数のうちまだ評価していないものを読む場合は、その変数を先に評価します。両者の参照が循環していれば、ほかの変数の循環と同じくワークフローを止めます。

リストの中のテンプレートも、マップと同じくどの深さでも評価されます。ports: ["{{vars.http_port}}"]はポート番号を持ちます。

nil のフィールドを読む{{nothing.here}}のように評価できないテンプレートを持つ変数があると、最初のジョブが始まる前に終了ステータス2でワークフローが止まります。エラーにはvars.a: {{nothing.here}}: cannot fetch here from <nil>のように変数とテンプレートが示されます。評価できなかった変数を参照する変数は評価しないため、同じエラーが重ねて出ることはありません。

secrets

型: 文字列の配列(任意) 説明: Probeが表示・書き出すものに、値を出してはいけない環境変数の名前です。

secrets: - API_TOKEN - DB_PASSWORD vars: api_token: "{{API_TOKEN}}" db_password: "{{DB_PASSWORD}}"

列挙した変数の値が現れる箇所には、代わりに<secret:NAME>と書きます。対象は、端末のレポート、ステップ名、echo、失敗したステップについて表示するリクエストとレスポンス、--verboseの出力、アクション自身のログ、--reportで書き出すファイルです。エラーメッセージで引用符に囲まれたときやJSONに埋め込まれたときのエスケープされた形も伏せます。ステップ、テスト、outputsは本来の値をそのまま使い、変わるのは表示だけです。

設定されていない名前や空文字列の名前は、伏せる値が無いので無視します。短い値は現れるたびに置き換えるため、1のような値を指定すると出力中のすべての1が伏せられます。

secretsとは別に、Authorization、Proxy-Authorization、Cookie、Set-Cookieヘッダの値は常に<redacted>と表示します。ログインのステップが返し、後のリクエストで送るトークンのように、実行中に得た値はsecretsに書けませんが、これらのヘッダのどれかで送られます。Probeはアクションがこれらの値を送る直前と受け取った時点で値を記録し、以降はアクション自身のログも含めて伏せます。

アクションに渡す資格情報も同じです。withのどの階層にあってもpassword、key_passphrase、secret_access_key、session_tokenの値は<redacted>と表示します。dsnやurlに書いたredis://user:password@hostのようなURLは、パスワードの部分だけを伏せ、それ以外はそのまま表示します。そのため、ステップに直接書いたパスワードは、secretsに書かなくても--verboseの出力やアクションのログに出ません。こうした値のテンプレートを評価できなかった場合、エラーにはwith.passwordのように値の場所を示しますが、理由は示しません。テンプレートにもエラーの文面にも資格情報が含まれうるためです。urlがこの扱いになるのは、redis://app:{{vars.pw}}@hostのようにテンプレートがユーザー情報の部分にある場合だけです。urlのそれ以外の場所にあるテンプレートのエラーは表示します。

defaults

型: Object(任意)
説明: すべてのジョブのステップに効くwithの既定値です。ジョブのdefaultsと同じく、アクションをキーにして書きます。

ベースURLやDSNのようにどのジョブも使う接続先は、ジョブごとではなくここに一度だけ書きます:

defaults: db: dsn: "postgres://{{vars.user}}@{{vars.host}}/app" http: url: "{{vars.api_url}}" headers: accept: application/json jobs: - name: Rows steps: - name: Count users uses: db with: query: SELECT count(*) AS n FROM users test: res.rows[0].n > 0 - name: API defaults: http: headers: authorization: "Bearer {{vars.token}}" steps: - name: List users # 既定の url に、両方のヘッダーを付けて送る uses: http with: get: /users test: res.code == 200

もっとも近くに書いた値が優先されます。ステップがwithに書いた値、そのジョブのdefaults、ワークフローのdefaultsの順です。オブジェクトはキーごとにマージされるので、上のステップはワークフローのacceptヘッダーとジョブのauthorizationヘッダーの両方を送ります。既定値の中のテンプレートは、ステップの実行時に、そのステップのvarsとoutputsで評価されます。

ワークフローのdefaultsは、embeddedアクションで実行するジョブファイルには適用されません。ジョブファイルは独立したファイルで、自身のdefaultsを持ちます。

actions

型: 文字列のオブジェクト(任意)
説明: ワークフローが使う外部アクションに付ける名前です。ステップのusesと、ジョブやワークフローのdefaultsのキーに、リポジトリとコミットの代わりにこの名前を書けます。

actions: graphql: github.com/mozership/probe-graphql@41e4ffa222db58c63c7169117c919e6d252bdbf9 # v0.2.0 jobs: - name: Countries API defaults: graphql: url: https://countries.trevorblades.com/graphql steps: - name: Look up Japan uses: graphql with: query: '{ country(code: "JP") { capital } }' test: res.data.country.capital == "Tokyo"

アクションを固定するコミットを書く場所が1か所になるので、新しいリリースへの更新は1行の変更で済みます。

  • 名前に使えるのは英数字、_、-で、先頭は英数字です。
  • httpやshellのようなProbeのアクションの名前は付けられません。uses: httpが何を実行するかは、ワークフローによって変わらないようにするためです。そのような名前を付けたワークフローは読み込みに失敗します。
  • 値はusesと同じ形式で外部アクションを指定します。40文字のコミットSHAを付けたgithub.com/<owner>/<repo>[/<dir>]@<commit>か、./、../、/で始まるローカルのパスです。テンプレートは書けず、別の名前を指すこともできません。
  • ステップでアクションを完全な形で書くこともでき、名前で書いたdefaultsはそのステップにも適用されます。1つのdefaultsに、名前とそれが指すアクションの両方を書くことはできません。

Probeはワークフローを読み込む時点で名前をアクションに置き換えるので、それ以降の処理はすべて完全な形のアクションを扱います。特に--allow-actionには、名前ではなくアクションを指定します。名前で許可すると、その名前が指すアクションをワークフローの側で変えられてしまうためです。

embeddedアクションで実行するジョブファイルは、埋め込む側のワークフローの名前で読まれるので、そのステップとdefaultsでも名前を使えます。名前を付けた外部アクションを参照してください。

ジョブ

jobsはジョブ名からジョブ定義へのマップです。ジョブは順に実行するステップをまとめ、依存先を宣言します。

ジョブのプロパティ

ジョブの定義では以下のプロパティを指定します。

プロパティ型必須説明
nameString必須ジョブ名。テンプレート式が使えます
idString任意他ジョブのneedsから参照する識別子。省略時は自動採番されます
needsArray任意先に完了している必要があるジョブのID
alwaysBoolean任意needsのジョブが失敗していても、それらが終わり次第実行する
stepsArray必須実行するステップ
skipifExpression任意真ならジョブ全体をスキップ
fail_fastBoolean任意失敗したステップより後のステップをスキップ
defaultsObject任意アクション名をキーとしたwithの既定値
repeatObject任意ジョブを繰り返す

ジョブにif、continue_on_error、timeoutはありません。失敗の後にも実行したいジョブにはalwaysを付けます。

needs

依存のないジョブは並列に開始します。needsが参照するのはジョブのIDなので、依存される側には明示的なidが必要です。

jobs: - id: setup name: Setup steps: - name: Prepare uses: hello echo: "ready" - name: Test needs: [setup] steps: - name: Run uses: hello echo: "testing"

always

ジョブは、needsに書いたジョブが失敗したとき、または同じ理由でスキップされたときにスキップされます。always: trueを付けたジョブは、needsのジョブがどう終わったかにかかわらず、すべてが終わり次第実行されます。他のジョブが作ったものを片付けるジョブに必要な動作です。これがないと、失敗した実行はテスト用のデータベースやファイルを残し、次の実行はそれらが残っているために失敗します。

jobs: - id: setup name: Setup steps: - name: Create the test database uses: db with: dsn: "{{vars.admin_dsn}}" query: CREATE DATABASE probe_test test: res.code == 0 - id: tests name: Tests needs: [setup] steps: - name: Count users uses: db with: dsn: "{{vars.test_dsn}}" query: SELECT count(*) AS n FROM users test: res.rows[0].n > 0 - name: Cleanup needs: [setup, tests] always: true steps: - name: Drop the test database uses: db with: dsn: "{{vars.admin_dsn}}" query: DROP DATABASE IF EXISTS probe_test test: res.code == 0
  • このジョブもneedsのすべてのジョブを待ちます。繰り返すジョブは全回の実行を待ちます。片付ける対象を作るジョブはすべてneedsに書き、それらと並行して走らないようにします。
  • 実行全体の成否は変わりません。alwaysが変えるのはどのジョブが走るかであり、終了ステータスではありません。
  • 失敗またはスキップされたジョブが公開しなかったoutputはnilとして読まれます。DROP DATABASE IF EXISTSのように、それがなくても動くステップを書きます。
  • alwaysを付けたジョブをneedsに書いたジョブは、他のジョブに対してと同じく、そのジョブの結果に従います。
  • skipifは引き続き有効です。両方を書いたジョブは、式が真ならスキップされます。

skipif

ブール式です。真と評価されるとジョブをスキップします。

jobs: - name: Production only skipif: vars.environment != "production" steps: - name: Check uses: http with: url: "{{vars.api_url}}/health" method: GET

fail_fast

ジョブのステップは順番に実行され、前のステップが失敗していても次のステップは実行されます。これは、それぞれが別のことを確かめていて、レポートに1行ずつ残す価値があるステップに向いています。一方、後のステップが前のステップの作ったものを使う場合、後のステップは前の失敗が原因で失敗し、本当に見るべき1つの失敗が、そこから派生した失敗に紛れて見分けにくくなります。fail_fast: trueを付けると、失敗したステップより後のステップは実行されず、スキップとして報告されます:

jobs: - name: Orders fail_fast: true steps: - name: Create the table uses: db with: query: CREATE TABLE orders (id INTEGER PRIMARY KEY, total INTEGER) test: res.code == 0 - name: Insert an order # テーブルを作れなかったときはスキップ uses: db with: query: INSERT INTO orders (total) VALUES (?) params: [100] test: res.rows_affected == 1
  • ステップが失敗するのは、testが偽のとき、アクションがエラーを返したとき、レスポンスが契約に違反したときです。testがなく何にも検査されないステップは失敗しないので、何も止めません。
  • スキップされたステップはwaitを待たず、outputsも公開しません。
  • iterationの残りのエントリも、どれかが失敗した時点でスキップされます。
  • repeatを付けたジョブは、実行のたびにやり直します。失敗によってスキップされるのは、その回の残りのステップだけです。ステップが実行されなかった回は、そのステップの成功にも失敗にも数えず、1/3 success (33.3%), 2 skippedのように別に示します。
  • 他のジョブには影響しません。失敗したジョブ一般と同じく、needsを通した影響だけがあります。後片付けのように失敗の後にも実行したいステップは、alwaysを付けたジョブに書きます。

defaults

ジョブ内の該当アクションを使うステップのwithにマージされる既定値です。ステップ側の指定が優先され、ここでの指定は、すべてのジョブが共有するワークフローのdefaultsより優先されます。キーはステップがusesに書くものです。組み込みアクションの名前、完全な形の外部アクション、actionsで付けた名前のどれかです。

jobs: - name: API checks defaults: http: url: "{{vars.api_url}}" headers: authorization: "Bearer {{vars.token}}" accept: application/json steps: - name: Health uses: http with: get: /health # 既定の url からの相対パス test: res.code == 200

httpアクションはメソッドの指定が必須です。methodを明示するか、get / post / put / delete / patchといった省略記法を使います。省略記法の値は完全なURLか、urlからの相対パスです。

- name: Explicit method uses: http with: url: "{{vars.api_url}}/health" method: GET

repeat

repeatはジョブ全体を一定の間隔で繰り返します。この指定でテストを繰り返し実行すると、監視として使えます。

プロパティ型必須説明
countInteger必須実行回数。上限はPROBE_MAX_REPEAT_COUNT(既定10000)
intervalDuration任意1回の実行が終わってから次を始めるまでの待ち時間。asyncのときは、1回の実行を始めてから次を始めるまでの間隔で、必須
asyncBoolean任意前の実行の終わりを待たずに次の実行を始める
warmupInteger任意countの前に行う実行の回数。どの集計にも含めない。countとの合計がPROBE_MAX_REPEAT_COUNTの上限を受ける
testExpression任意すべての回が終わった後に、各ステップの回の集計に対して評価する。指定した場合は、これだけでジョブの成否が決まる。全回に対するテストを参照
baseline_testExpression任意すべての回が終わった後に、各ステップの回の集計と、--baselineで指定した実行の集計に対して評価する。指定がなければスキップする。以前の実行と比べるテストを参照
jobs: - name: Poll until ready repeat: count: 10 interval: 5s steps: - name: Check uses: http with: url: "{{vars.api_url}}/status" method: GET test: res.code == 200

warmupの回は最初に行います。intervalとasyncも含めてほかの回と同じように実行しますが、結果には含めません。ステップが失敗してもジョブは失敗しません。ただし、名前を評価できないなどジョブを開始できない場合は、ほかの回と同じくwarmupの回でも失敗します。成否の回数と応答時間は、その後のcount回について数えます。計測する回の前に、サービスがキャッシュやコネクションプールを満たす時間を取るためのものです。

各回のステップは、同じ回の前のステップが公開した出力を読みます。asyncで複数の回が同時に動く場合も同じです。後続のジョブは、それぞれの出力について、最後にそれを公開した回の値を読みます。そのため、最後の回が飛ばしたステップの出力は、その前の回の値になります。

全回に対するテスト

repeat.testがなければ、ステップが失敗した回が1回でもあるとジョブは失敗します。repeat.testは、すべての回が終わった後に各ステップの回の集計に対して評価され、これだけでジョブの成否が決まります。

jobs: - name: Search repeat: count: 100 interval: 100ms warmup: 5 test: steps.search.success_rate >= 0.99 && steps.search.rt.p95 < 0.3 steps: - name: Search by keyword id: search uses: http with: url: "{{vars.api_url}}" get: /search?q=probe test: res.code == 200

式からは、ワークフローの変数varsと、ジョブの各ステップの回の集計stepsを読めます。stepsのキーはステップのidで、idのないステップはstep_0のように番号で指定します。

フィールド型説明
runsInteger数えた回数。success、failure、skippedの合計
successIntegerステップが成功した回数。ステップ自身のskipifでスキップされた回を含む
failureIntegerテストが失敗した回数と、アクションがエラーを返した回数の合計
skippedIntegerステップが実行されなかった回数。fail_fastのジョブで前のステップが失敗した回と、iterationに要素がなかった回
success_rateFloatsuccessをrunsで割った値。0から1
rtObjectアクションが時間を返した回の所要時間。rt.secと同じく秒単位で、min、mean、p50、p90、p95、p99、maxを持つ。時間を返した回がなければnil

パーセンタイルは、レポートの応答時間と同じく最近接順位法によるものです。warmupの回はどれにも数えません。iterationのあるステップは、すべての要素の回をまとめて数えます。

repeat.testを指定すると、各回の結果は数えるだけになり、それ自体では何も失敗させません。

  • ステップが失敗した回があってもジョブは失敗しません。ステップは成功として報告し、失敗した回はrepeatの回数に数えます。
  • テストが真ならジョブは成功し、偽のとき、評価できないとき、真偽値でないときは失敗します。偽のときは、ステップのテストと同じく、どの条件が偽だったかと、比べた値を示します。
  • 終了ステータスはテストの結果で決まります。テストが失敗すれば、各回が何で失敗したかに関係なく1です。
  • 数える回をすべてskipifがスキップしたジョブはスキップとなり、テストは評価しません。一部の回だけをスキップした場合は、実行した回に対してテストを評価します。
以前の実行と比べるテスト

repeat.baseline_testは、各回を以前の実行(--baselineで指定したレポート)と比べます。すべての回が終わった後、repeat.testの次に評価します。repeat.testが読めるものに加えて、baseline.stepsの下で、以前の実行における同じジョブのステップをidで読めます。

jobs: - name: Search repeat: count: 100 warmup: 5 test: steps.search.success_rate >= 0.99 baseline_test: steps.search.rt.p95 < baseline.steps.search.rt.p95 * 1.2 steps: - name: Search by keyword id: search uses: http with: url: "{{vars.api_url}}" get: /search?q=probe test: res.code == 200

レポートに記録される項目が少ないので、baseline.stepsの下のステップはstepsの下より少ないフィールドを持ちます。

フィールド型説明
runsInteger数えた回数
successIntegerステップが成功した回数
success_rateFloatsuccessをrunsで割った値。0から1
rtObjectステップの所要時間。レポートの応答時間から取り、秒単位でstepsの下と同じフィールドを持つ。時間がなければnil

ジョブはidが同じジョブと、ステップはidが同じステップと対応させます。iterationのあるステップは、レポートでは同じidの複数のステップになります。runsとsuccessはそれらの合計ですが、時間はパーセンタイルからまとめられないので、rtはnilになります。

--baselineを指定しなかったとき、テストがbaseline.stepsの下で読むステップが以前の実行にないとき、rtの下で読む時間がないときは、テストをスキップし、ジョブはこのテストでは失敗しません。そのため、同じワークフローを--baselineの有無にかかわらずそのまま実行できます。スキップしたときは、skipped: the baseline has no step searchのように理由を示します。以前の実行にテストが読むものがあるかを実行前に判断できるのは、ステップとフィールドが式に直接書かれているときだけです。そのため、baseline.steps[vars.id]のように実行時に決まるキーでステップやフィールドを読むテストは、ワークフローを読み込む時点で拒否し、終了ステータス2で終わります。

評価した場合は、テストが成り立つときだけジョブは成功し、終了ステータスはrepeat.testと同じくテストの結果で決まります。各回の失敗の扱いは変えません。repeat.testがなければ、ステップが失敗した回があるとジョブは失敗します。baselineを読めるのはこのテストだけです。baseline.stepsにないステップやフィールドを読むbaseline_testは、probe checkが報告します。

ステップ

ステップは1回のアクション呼び出しと、その周辺の指定から成ります。実行するかを決める条件、成功したかを決めるテスト、後続のステップに残す出力です。

ステップのプロパティ

ステップの定義では以下のプロパティを指定します。

プロパティ型必須説明
usesString必須実行するアクション。http、shellなどの組み込みアクションか、外部アクション
nameString任意ステップ名
idString任意このステップのoutputsの名前空間になる識別子
withObject任意アクション引数
testExpression任意アサーション。偽ならステップは失敗します
echoString任意レポートに出力する文字列
varsObject任意ステップ内だけの変数
outputsObject任意後続のステップやジョブへ渡す値
skipifExpression任意真ならステップをスキップ
waitDuration任意実行前の待機時間
timeoutDuration任意ステップのタイムアウト(既定5m)。その時点で実行中のアクションは停止され、ステップは失敗する
iterationArray またはテンプレート任意要素ごとにステップを繰り返す。値はvarsから参照します
retryObject任意失敗時のリトライ

キーはactionではなくuses、条件はifではなくskipifです。

outputs

後続のステップやジョブへ渡す値です。outputs.tokenのように名前で読めます。ステップにidがあれば、outputs.auth.tokenのようにidからも読めます。ほかのステップが同じ名前を公開する場合は、それぞれの値を読めるようにステップにidを付けてください。

値はテンプレートではなく式なので、波カッコは書きません。

steps: - name: Log in id: auth uses: http with: url: "{{vars.api_url}}/login" method: POST test: res.code == 200 outputs: token: res.body.access_token user_id: res.body.user.id

後続からはステップIDで名前空間を指定するか、出力名だけで参照します。

headers: Authorization: "Bearer {{outputs.auth.token}}" X-User: "{{outputs.user_id}}"

ハイフンを含むIDは式の識別子として解釈できないため、ブラケットで参照します。

echo: "{{outputs['create-user'].user_id}}"

retry

retryは、テストが通るか試行回数を使い切るまで、そのステップだけを繰り返します。

プロパティ型必須説明
max_attemptsInteger必須試行回数。1以上で、上限はPROBE_MAX_ATTEMPTS(既定10000)
intervalDuration任意試行間隔
initial_delayDuration任意最初の試行前の待機
steps: - name: Flaky endpoint uses: http with: url: "{{vars.api_url}}/slow" method: GET test: res.code == 200 retry: max_attempts: 3 interval: 2s

iteration

要素ごとにステップを繰り返します。各要素のキーはvarsから参照できます。

steps: - name: Check {{vars.path}} uses: http iteration: - path: /health - path: /metrics - path: /version with: url: "{{vars.api_url}}{{vars.path}}" method: GET test: res.code == 200

iterationには、ワークフローに書いたリストの代わりに、オブジェクトのリストになるテンプレートを1つ書けます。テンプレートはステップに到達した時点で、ワークフローとステップのvars、それまでに公開されたoutputsを使って評価されます。そのため、ファイルに置いたケースや、前のステップで取得した値を要素にできます:

steps: # ファイルのケースごとに1回実行。ケースはワークフローを変えずに増やせる - name: "{{vars.name}} can sign in" uses: http iteration: "{{ parse_json(file('testdata/users.json')) }}" with: post: /login body: user: "{{vars.name}}" password: "{{vars.password}}" test: res.code == 200 - name: List orders id: orders uses: db with: query: SELECT id, total FROM orders WHERE status = 'open' test: res.code == 0 outputs: rows: res.rows # 上のステップが読んだ行ごとに1回実行 - name: "Order {{vars.id}} has a total" uses: http iteration: "{{ outputs.orders.rows }}" with: get: "/orders/{{vars.id}}" test: res.body.total == vars.total
  • 値は{{ }}のテンプレート1つだけです。前後に文字があるもの、テンプレートが2つあるものは文字列になってしまうため、ワークフローの読み込みに失敗します。
  • 各要素はオブジェクトで、そのキーをステップがvarsとして読みます。文字列のリストなど、それ以外のリストはステップを失敗させます。"{{ map(vars.paths, ({path: #})) }}"のようにmapでオブジェクトに変換してください。
  • 評価できないテンプレート、リストにならないテンプレートは、ステップを実行せずに失敗させます。
  • 要素のないリストはステップをスキップし、スキップとして報告します。実行に使う値がないためです。空のリスト[]として書いたiterationは、iterationのないステップと同じく1回実行します。
  • 要素はそのまま使われます。要素の値に書いた{{ }}は評価されません。ステップ自身のvarsは、テンプレートのために評価され、さらに要素ごとにも評価されます。ワークフローに書いたリストの要素ごとに評価されるのと同じです。random_strを呼ぶvarは、そのたびに別の値になります。
  • iterationが受け取れる要素は1,048,576個までです。それより長いリストはステップを失敗させます。
  • repeatを付けたジョブでは、テンプレートは回ごとに評価され、回によって要素数が変わることがあります。各要素はリスト内の位置ごとに集計され、後続のステップはそれぞれ自身として集計されます。リストに要素がなかった回は、fail_fastのジョブで実行されなかった回と同じく、そのステップの成功にも失敗にも数えません。

式のコンテキスト

ステップの式から見えるのは次の名前だけです。

名前型説明
varsObjectワークフローの変数にステップのvarsをマージしたもの
resObjectアクションのレスポンス
reqObject送信したリクエスト
rtObjectレスポンスタイム。rt.duration(文字列)とrt.sec(秒、浮動小数点数)
statusIntegerアクションの終了ステータス。成功は0
outputsObject先行ステップが公開した値
repeat_indexIntegerジョブ繰り返し時の現在のインデックス。0から始まり、warmupの回も数える

このコンテキストにenv、jobs、stepsはありません。

httpのres

resの内容はアクションごとに異なります。httpでは以下が入ります。

フィールド型説明
res.codeIntegerステータスコード(例: 200)
res.statusStringステータス行(例: "200 OK")
res.headersObjectレスポンスヘッダー。キーはContent-Typeのような正規形
res.bodyAnyレスポンスボディ。JSONならオブジェクトや配列に解析され、それ以外は文字列
res.rawbodyString解析前のボディ。JSONとして解析したときに入ります
test: | res.code == 200 && res.headers["Content-Type"] contains "application/json" && res.body.status == "ok" && rt.sec < 1

他のアクションのresはアクションリファレンスを参照してください。

データ型

ワークフローファイルの値のうち、独自の書き方を持つものが2つあります。時間の長さと、コンテキストを参照する式やテンプレートです。

Duration

Goのduration文字列か、秒数の数値で指定します。

timeout: "30s" timeout: "5m" interval: 10 # 10 秒

式とテンプレート

テンプレート式は文字列の中に書き、評価結果で置き換わります。

url: "{{vars.api_url}}/users/{{outputs.auth.user_id}}"

ブール式は波カッコなしでそのまま書きます。

test: res.code == 200 && rt.sec < 2 skipif: vars.environment == "local"

outputsの値も式なので、波カッコは書きません。

評価できないテンプレートはエラーになり、エラーの文面が値に入ることはありません。定義されていない名前は nil として読まれエラーになりませんが、nil のフィールドを読むことや、構文として解釈できない式はエラーです。

テンプレートの場所起きること
ステップのwith、vars、nameステップは種類templateで失敗し、アクションは実行されません。エラーにはwith.headers.authorizationのように値の場所が示されます
ワークフローのvars最初のジョブの前に終了ステータス2でワークフローが止まります
ジョブのnameジョブが失敗し、終了ステータスは2です
ステップのecho本文の代わりにエラーを表示し、ステップの結果は変わりません
# 先行するステップが outputs.login を出力していなければ、ステップは失敗する headers: authorization: "Bearer {{outputs.login.token}}" # 代わりの値を使う headers: authorization: "Bearer {{outputs.login?.token ?? 'none'}}"

式の中で使える関数は組み込み関数を参照してください。

バリデーション規則

  • ワークフローにはnameが必要で、jobsは空でないリストである必要があります
  • 各ジョブにはnameと1つ以上のステップが必要です
  • 各ステップにはusesが必要で、アクションを指している必要があります。Probeのアクション、外部アクション、actionsで付けた名前のいずれかです。どれでもない場合は、スキップされるステップであっても、最初のジョブの前に終了ステータス2で実行が止まります
  • actionsの名前はProbeのアクションの名前であってはならず、コミットで固定した外部アクションかローカルのパスを指す必要があります
  • needsは存在するジョブIDを指し、依存関係は循環していない必要があります
  • repeat.countとrepeat.warmupは0以上、retry.max_attemptsは1以上である必要があります

probe checkは、受け付けないキー、解析できない式、公開される前に読む出力とあわせて、これらをワークフローを実行せずに報告します。CLIリファレンスを参照してください。

ファイルのマージ

複数のファイルをカンマ区切りで渡すと順に連結されます。複数回定義されたトップレベルのキーは、最後のファイルの値になります。

probe base.yml,production.yml

マージの規則はファイルマージを参照してください。

関連項目

更新日時