S3アクション
S3アクションは、S3と、MinIO、Cloudflare R2、Versity GatewayのようなS3のプロトコルを話すストレージのオブジェクトを読み書きします。APIが保存したものを、ワークフローから確かめられます。
外部アクションとしてmozership/probe-s3 で公開しています。ワークフローが初めて使うときにProbeがダウンロードし、固定したコミットのaction.ymlが示すSHA-256と一致する実行ファイルだけを実行します。Probe v1.21.0以降が必要です。
基本的な構文
ワークフローでは40文字のコミットSHAでアクションを固定します。各リリース のノートの先頭に、コピーして使うアクションとコミットがあります。このページの例では、actionsで一度だけ名前を付けています。actionsにはProbe v1.24.0以降が必要です。それより前のProbeでは、各usesにアクションを完全な形で書きます。
name: Upload
actions:
s3: github.com/mozership/probe-s3@8d2a120ffe6f2860229f5b6171a3477ed0f07b6d # v0.1.0
jobs:
- name: upload
steps:
- name: Upload an avatar through the API
id: upload
uses: http
with:
url: https://api.example.com
post: /avatars
multipart:
image:
file: ./fixtures/logo.png
test: res.code == 201
outputs:
key: res.body.key
- name: The object is in the bucket, as it was sent
uses: s3
with:
bucket: example-avatars
region: ap-northeast-1
head: "{{outputs.upload.key}}"
test: res.code == 200 && res.content_type == "image/png" && res.metadata.owner == "42"1つのステップは、1つのバケットに対して1つの操作をします。バケットの作成と削除はできません。
操作
ステップは次のキーのどれか1つで操作を指定します。書けるのは1つだけです。
| キー | 値 | 動作 |
|---|---|---|
get | オブジェクトのキー | オブジェクトを読みます。内容、ダイジェスト、ヘッダーが示す情報を返します |
head | オブジェクトのキー | 内容を読まずに、ヘッダーが示すオブジェクトの情報だけを読みます |
list | プレフィックス、または空 | キーがプレフィックスで始まるオブジェクト、またはすべてのオブジェクトを一覧します |
put | オブジェクトのキー | bodyまたはfileからオブジェクトを書きます |
delete | オブジェクトのキー | オブジェクトを削除します |
パラメータ
| パラメータ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
bucket | String | Yes | - | バケット |
region | String | No | AWS_REGION、AWS_DEFAULT_REGION、またはus-east-1 | リクエストの署名に使うリージョン。AWSでは送り先のリージョンでもあります |
endpoint | String | No | AWS | S3互換ストレージの場所。http://localhost:9000やhttps://<account>.r2.cloudflarestorage.comなど |
path_style | Boolean | No | 下記参照 | バケットを、<bucket>.<endpoint>/<key>のようにホストではなく、<endpoint>/<bucket>/<key>のようにパスで指定します |
access_key_id | String | No | AWS_ACCESS_KEY_ID | アクセスキー |
secret_access_key | String | No | AWS_SECRET_ACCESS_KEY | シークレットアクセスキー |
session_token | String | No | AWS_SESSION_TOKEN | 一時的な認証情報のセッショントークン |
body | String、またはほかの値 | putでfileがないとき | - | putが書く内容。文字列はそのまま、それ以外はJSONとして送ります。JSONの場合、content_typeの指定がなければコンテンツタイプはapplication/jsonです |
file | String | putでbodyがないとき | - | putが書くファイルのパス。作業ディレクトリからの相対パスです |
content_type | String | No | - | putがオブジェクトと一緒に保存するメディアタイプ |
metadata | Object | No | - | putがオブジェクトと一緒に保存するメタデータ。x-amz-meta-<name>として送ります。名前は小文字にし、値は表示可能なASCIIである必要があります |
max_keys | Integer | No | ストレージの既定値。S3では1000 | listが返すオブジェクトの最大数 |
timeout | Duration | No | 30s | ステップ全体の制限時間。10sまたは秒数で指定します。0で制限なしになります |
これら以外のキーをwithに書くと、何も送らずにステップが失敗します。action.ymlがこれらをparamsとして宣言しているので、probe checkはそのようなキーを行番号つきで報告します。getにbodyを付けるように、操作が受け付けないパラメータを指定した場合も同じように失敗します。
path_styleのデフォルトは、endpointがあればtrueです。MinIOなどは1つの名前で提供されるためです。AWSではfalseですが、名前にドットを含むバケットは例外です。*.s3.<region>.amazonaws.comの証明書がその名前に対応しないためです。
listが返すのは1ページ分です。最大max_keys個のオブジェクトを返し、ストレージにまだ残りがあるかはres.truncatedで分かります。マルチパートアップロードには対応していません。
認証情報
withにaccess_key_id、secret_access_key、session_tokenのどれもなければ、アクションはProbeを実行している環境からAWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKENを読みます。どちらにも認証情報がなければ、公開バケットが受け付ける形で、リクエストを署名なしで送ります。アクションはプロファイルもインスタンスメタデータも、そのほかの認証情報の取得元も読まないので、ストレージ以外には接続しません。
できるだけ、認証情報は環境変数に任せてください。withに書いたシークレットアクセスキーは、結果にもレポートにも出ません。v1.24.0以降のProbeは、--verboseの出力とアクションのログでもsecret_access_keyとsession_tokenの値を伏せます。それより前のProbeでwithから渡すときは、その変数をsecretsに書いてください。
レスポンスオブジェクト
| プロパティ | 型 | 説明 |
|---|---|---|
res.code | Integer | HTTPステータスコード。200など。deleteでは204です |
res.status | String | HTTPステータス行。"200 OK"など |
res.headers | Object | レスポンスヘッダー。Content-Typeのような正規化した名前がキーです |
res.error_code | String | ストレージが返したエラー。NoSuchKey、NoSuchBucket、AccessDenied、SignatureDoesNotMatchなど。なければ空です。headにはエラーを運ぶ本文がないので、常に空です |
res.error_message | String | ストレージによるエラーの説明。なければ空です |
req | Object | 実行した内容。operation、bucket、region、endpoint、path_style、応答を返したurl、signedと、オブジェクトのkey、または一覧のprefixとmax_keysです。putではさらにbody、file、content_type、metadataと、送った内容のsizeとsha256があります。認証情報は含みません |
rt | Duration | ステップにかかった時間 |
status | Integer | ステータスコードが2xxなら0、そうでなければ1 |
getとheadでは、ヘッダーが示すオブジェクトの情報が加わります。
| プロパティ | 型 | 説明 |
|---|---|---|
res.etag | String | ETag。引用符は除きます |
res.size | Integer | バイト単位のサイズ |
res.content_type | String | オブジェクトと一緒に保存されているメディアタイプ |
res.last_modified | String | 最後に書かれた日時。2026-10-10T01:02:03Zの形式です |
res.metadata | Object | オブジェクトと一緒に保存されているメタデータ。x-amz-meta-を除いた小文字の名前がキーです |
getでは内容が加わります。
| プロパティ | 型 | 説明 |
|---|---|---|
res.body | Any | テキストとしての内容。res.content_typeがJSONを示し、内容がJSONであれば、オブジェクトまたは配列に解析します。バイナリのオブジェクトでは空です |
res.rawbody | String | 解析する前の内容。JSONとして解析したときにだけあります |
res.sha256 | String | オブジェクト全体のSHA-256ダイジェスト。16進数です |
res.truncated | Boolean | オブジェクトが1 MiBより大きいかどうか。大きい場合、res.bodyには先頭の1 MiBが入ります |
res.binary | Boolean | 内容がUTF-8のテキストでなく、res.bodyに入っていないかどうか |
res.sha256とres.sizeは、オブジェクトがどれだけ大きくても全体についての値です。バイナリや大きなオブジェクトは、書き込んだステップのreq.sha256や既知のダイジェストとこれらを比べて確かめます。
putではres.etagが加わります。listでは次のものが加わります。
| プロパティ | 型 | 説明 |
|---|---|---|
res.objects | Array | オブジェクト。キーの順に並び、それぞれkey、size、etag、last_modifiedを持ちます |
res.count | Integer | res.objectsにあるオブジェクトの数 |
res.truncated | Boolean | ストレージに、返した分より多くのオブジェクトがあるかどうか |
ストレージが応答した後は、その応答が結果になります。そのため、消えているはずのキーの404や、閉じているはずのバケットの403をテストで確かめられます。エラーとして失敗するのは、接続の拒否やタイムアウトのように、応答が得られなかったリクエストだけです。
例
AWSに対して、環境の認証情報を使う例です。
steps:
- name: The export is there and not empty
uses: s3
with:
bucket: example-exports
region: ap-northeast-1
list: "daily/{{vars.today}}/"
test: "res.code == 200 && res.count > 0 && all(res.objects, #.size > 0)"MinIOに対して、フィクスチャを書いて読み戻す例です。ジョブのdefaultsを、ワークフローがアクションに付けた名前をキーにして書くと、エンドポイント、バケット、認証情報を各ステップに書かずに済みます。
jobs:
- name: fixtures
defaults:
s3:
endpoint: http://localhost:9000
bucket: fixtures
access_key_id: "{{vars.minio_user}}"
secret_access_key: "{{vars.minio_password}}"
steps:
- name: Put a fixture
id: put
uses: s3
with:
put: config/app.json
body:
enabled: true
test: res.code == 200
outputs:
sha256: req.sha256
- name: Get it
uses: s3
with:
get: config/app.json
test: res.body.enabled == true && res.sha256 == outputs.put.sha256
- name: A key that must not be there
uses: s3
with:
head: config/removed.json
test: res.code == 404リダイレクト
AWSでは、リクエストに署名したリージョンにないバケットを、AWSが応答で示したリージョンから読みます。ストレージが返したLocationも、ストレージの中にとどまる場合は5回まで追います。amazonaws.comの下、またはendpointのホストとその下の名前がこれにあたります。リクエストは行き先ごとに署名し直します。それ以外へのリダイレクトは追わず、そのまま結果になります。
ガードの下での動作
このアクションは実行のガードを守り、action.ymlでguard: [read-only, allow-host]を宣言しています。そのため、どちらの下でも--allow-actionなしで実行されます。アクションが拒否したステップは、種別refusedで失敗します。
--read-onlyの下では、get、head、listだけを実行します。putとdeleteは、何も送らず、fileも読まないうちに拒否します。--allow-hostの下では、リクエストの送り先のホストがすべて、実行で許可されている必要があります。バケットを指定するホスト(AWSでは<bucket>.s3.<region>.amazonaws.com、path_styleではs3.<region>.amazonaws.com)と、各リダイレクト先のホストです。ポートのないURLは、スキームの既定のポート(httpは80、httpsは443)として扱います。--allow-host '*.amazonaws.com'とすれば、どのリージョンのバケットも許可されます。
ガードを参照してください。