Actions上でDeployments APIのリクエストをテンプレート化を試みながらやってみた
はじめに
Deployments APIへのリクエストを行うActionを使ってworkflowを組み立てていましたが、Deploymentsの動作把握を兼ねてActionを使わずにAPIを直接呼び出す形で作り直してみました。
DeploymentsのAPI呼び出し
Deploymentsは特定のブランチを対象にしたデプロイ操作を記録するAPIで、最初に対象とするブランチを記録し、その後デプロイ処理毎に記録していきます。
- Create Deployments
- Create Deployments Status
最初のDeployments APIへリクエストすることでDeploymentsのIDが発行されます。このIDを元にしてStatusを記録していくことになります。
尚、デプロイ処理毎に記録というのは、
- 環境Aにデプロイ
- 環境Bにデプロイ
のように一度のデプロイ操作で複数の環境に反映される場合に、各環境毎にStatusを記録するということです(例:開発環境、検証環境)。デプロイ開始時とデプロイ終了時等の状況変化にも合わせて通知をしておくと把握の負担が大きく下がります。
リクエストの作成
stepの作成順
以下の順で作成してみます。
- Create Deployments
- Create Deployments Status(start)
- Deploy work
- Create Deployments Status(end)
実際のDeploy処理後のStatusは失敗した時と成功した時の双方を用意する必要があります。
共通値の設定
Deployments APIへのリクエストURL共通部分を事前にenv
へ指定しておき、ついでにDeployments
とDeployments Status
それぞれのヘッダも指定します。今回は開発環境のみのデプロイを想定してdevelop
決め打ちにしておきます。
env: DEPLOYMENT_API_BASE: https://api.github.com/repos/${GITHUB_REPOSITORY}/deployments ENVIRONMENT: develop HEAD: "Accept: application/vnd.github.ant-man-preview+json" STATUS_HEAD: "Accept: application/vnd.github.flash-preview+json, application/vnd.github.ant-man-preview+json"
指定が必須のブランチ名は$GITHUB_REF
を加工しての取得としました。また、Deploymentsのログからworkflowをたどりやすくするため、workflowのURLをlog_url
とします。
- name: Extract environment run: | echo "::set-env name=branch::$(echo ${GITHUB_REF#refs/heads/})" echo "::set-env name=log_url::$(echo https://github.com/${GITHUB_REPOSITORY}/commit/${{ github.sha }}/checks)"
APIへのリクエスト
まずDeployments
へのリクエストを作成し、その後Deployments Status
へのリクエストを作成します。
Deployments Status
にはDeployments
のレスポンス内にあるid
が必要になるため、jqを用いて取得しておきます。
- name: Create deployment run: | create_deployment_request_url=${{ env.DEPLOYMENT_API_BASE }} deployment_data=$(curl -X POST -v \ -d '{ "ref": "${{ env.branch }}", "production_environment": false, "environment": "${{ env.ENVIRONMENT }}" }' \ -H "${{ env.HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $create_deployment_request_url)
create_deployment_status_request_url=${{ env.DEPLOYMENT_API_BASE }}/$(echo $deployment_data | jq '.id')/statuses deployment_status_data=$(curl -X POST -v \ -d '{ "log_url": "${{ env.log_url }}", "environment": "${{ env.ENVIRONMENT }}", "state": "in_progress" }' \ -H "${{ env.DEPLOYMENT_STATUS_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $create_deployment_status_request_url) echo "::set-env name=deployment_id::$(echo $deployment_data | jq '.id')"
最後にset-env
をしているのは、Deploy後のStatus記録時に使うためです。
Deployments Status
のstate
には既定値を指定しますが、内容によってはヘッダにメディアタイプの指定が追加で必要になります。
state | extend mediatype |
---|---|
error |
|
failure |
|
pending |
|
success |
|
inactive |
application/vnd.github.ant-man-preview+json |
in_progress |
application/vnd.github.flash-preview+json |
queued |
application/vnd.github.flash-preview+json |
なお、inactive
を指定した場合、GitHub上ではdestroyed
として表示されます。
個人的に一番嵌ったのはToken指定です。Personal Access Tokenを使うとアカウントに依存してしまうためにGITHUB_TOKENを使うべきですが、
'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}'
と指定します。Bearer
がToken
になっていたり、secretsつけではないGITHUB_TOKEN呼び出しは該当する環境変数が存在しないため動作しません。
Deploy判定による分岐
if:
を使って成功時と失敗時それぞれの結果を送信します。
- name: Failed notice if: failure() run: | request_url=${{ env.DEPLOYMENT_API_BASE }}/${{ env.deployment_id }}/statuses data=$(curl -X POST -v \ -d '{ "log_url": "${{ env.log_url }}", "environment": "${{ env.ENVIRONMENT }}", "state": "failure" }' \ -H "${{ env.DEPLOYMENT_STATUS_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $request_url) - name: Update deployment status if: success() run: | request_url=${{ env.DEPLOYMENT_API_BASE }}/${{ env.deployment_id }}/statuses data=$(curl -X POST -v \ -d '{ "log_url": "${{ env.log_url }}", "environment": "${{ env.ENVIRONMENT }}", "state": "success" }' \ -H "${{ env.DEPLOYMENT_STATUS_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $request_url)
workflow全体
最初のon
等は外してありますが、通してのフローは以下のようになります。
env: DEPLOYMENT_API_BASE: https://api.github.com/repos/${GITHUB_REPOSITORY}/deployments ENVIRONMENT: develop HEAD: "Accept: application/vnd.github.ant-man-preview+json" STATUS_HEAD: "Accept: application/vnd.github.flash-preview+json, application/vnd.github.ant-man-preview+json" jobs: deploy: name: Deploy runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Extract environment run: | echo "::set-env name=branch::$(echo ${GITHUB_REF#refs/heads/})" echo "::set-env name=log_url::$(echo https://github.com/${GITHUB_REPOSITORY}/commit/${{ github.sha }}/checks)" - name: Create deployment run: | create_deployment_request_url=${{ env.DEPLOYMENT_API_BASE }} deployment_data=$(curl -X POST -v \ -d '{ "ref": "${{ env.branch }}", "production_environment": false, "environment": "${{ env.ENVIRONMENT }}" }' \ -H "${{ env.DEPLOYMENT_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $create_deployment_request_url) create_deployment_status_request_url=${{ env.DEPLOYMENT_API_BASE }}/$(echo $deployment_data | jq '.id')/statuses deployment_status_data=$(curl -X POST -v \ -d '{ "log_url": "${{ env.log_url }}", "environment": "${{ env.ENVIRONMENT }}", "state": "in_progress" }' \ -H "${{ env.DEPLOYMENT_STATUS_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $create_deployment_status_request_url) echo "::set-env name=deployment_id::$(echo $deployment_data | jq '.id')" - name: Deploy run: ..... - name: Failed notice if: failure() run: | request_url=${{ env.DEPLOYMENT_API_BASE }}/${{ env.deployment_id }}/statuses data=$(curl -X POST -v \ -d '{ "log_url": "${{ env.log_url }}", "environment": "${{ env.ENVIRONMENT }}", "state": "failure" }' \ -H "${{ env.DEPLOYMENT_STATUS_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $request_url) - name: Update deployment status if: success() run: | request_url=${{ env.DEPLOYMENT_API_BASE }}/${{ env.deployment_id }}/statuses data=$(curl -X POST -v \ -d '{ "log_url": "${{ env.log_url }}", "environment": "${{ env.ENVIRONMENT }}", "state": "success" }' \ -H "${{ env.DEPLOYMENT_STATUS_HEAD }}" -H "Content-Type: application/json" -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ $request_url)
あとがき
今回は一つの環境のみへのデプロイという前提でやってみました。
APIへのリクエストが正常に行われていない場合はWorkflowのログを辿って調べる必要がありますが、大体はステータスコードが確認できる程度になると思います。その場合は、まずは以下の4点を確認しましょう。
- 必須パラメータの指定を忘れていないか
- URLに埋め込んだ変数が
null
になっていないか - 既定値を間違えていないか
- パラメータの型を間違えていないか(String? Boolean?)
大体はこれらのどれかに当てはまると思われます。焦っても無駄にコミットが増えるだけなので、落ち着いて対処しましょう。