[GitHub Actions]repository_dispatchとworkflow_dispatchの使い分けや書き方の違いをまとめてみた

1.この記事で達成したいこと repository_dispatchとworkflow_dispatch の使い分けや書き方の違い、共通点や相違点を整理したい 結局どっちを使うのがいいのか?判断基準を見つけたい そもそもrepository_dispatchとworkflow_dispatchはどういうときに使うのか? アプリケーションリポジトリでイメージをレジストリにpushした後、マニフェストリポジトリでそのイメージタグをマニフェストに反映させたい 使いまわしているWorkflowを呼びたい このようなときに使えるのがGitHub Actionsでは2つ提供されている。それが冒頭に書いた、repository_dispatchとworkflow_dispatchである。 この記事の結論 長くなってしまったので、冒頭で結論を書く。 repository_dispatchとworkflow_dispatchの使い分けの判断基準の一つは、実行時に参照するWorkflowのブランチをデフォルトブランチ以外としたいケースがあるかどうか? デフォルトブランチ以外のWorkflowのファイルを参照してWorkflowを実行したい場合は、workflow_dispatchを選ぶしかない 2.サンプルコードで使っているリポジトリ https://github.com/gkzz/actions-playground 起点となるWorkflow(実行トリガーはpush)のリポジトリ https://github.com/gkzz/actions-dispatch-playground 起点となるWorkflowからkickされるWorkflow(実行トリガーはrepository_dispatch)のリポジトリ 3.環境情報 ローカル始めバージョンを書いておく必要があるものはない 使うActionのバージョンについては後述するWorkflowを参照してほしい 4.repository_dispatchとworkflow_dispatchの共通点や相違点 共通点 どちらも以下の権限を有する Personal Access Token が必要 repo:write 相違点 workflow_dispatchのみ、GUIから実行できる 実行場所はGithubの実行先のリポジトリのActionタブ pushしたWorkflowからdispatchする際のパラメーターの渡し方が違う(詳細は4-1参照) パラメーターの受け取り方が違う(詳細は5-1及び5-2参照) repository_dispatchのみ、event-typeを使ってWorkflowを実行するか制御できる repository_dispatchはevent-typeに応じて実行するかどうか決めることができる workflow_dispatchの場合、Workflowをkickされたら実行されてしまうのでkickしたWorkflowから渡されるパラメータの値によってjobを実行するように制御することはできる repository_dispatchのみ、Workflowはデフォルトブランチを参照して実行する 4-1.pushしたWorkflowからdispatchする際のパラメーターの渡し方 ここでは、curlコマンドでrepository_dispatchとworkflow_dispatchのWorkflowを実行しながらパラメータの渡し方の違いを確認しよう。 とりわけ、POSTする接続先URLと -d (--data)オプションで渡しているPOSTする値の書式はおさえておきたい。 repository_dispatch 接続先URLは https://api.github.com/repos/<REPOSITORY_OWNER>//dispatches $ curl -X POST \ -H "Accespt: application/vnd.github.v3+json" \ -H "Authorization: token <PAT_REPOSITORY_DISPATCH>" \ https://api.github.com/repos/gkzz/actions-dispatch-playground/dispatches \ -d '{"event_type": "sample-event", "client_payload": {"hoge": "hogevalue"}}' https://docs.github.com/en/rest/reference/repos#create-a-repository-dispatch-event ...

January 31, 2022 · 3 min · gkzz

[addnab/docker-run-action]GitHub Actions で yq のコンテナイメージを使ってマニフェストを更新する

1.この記事で達成したいこと GitHub Actionsでyqのコンテナイメージを使ってマニフェストを更新したい yqはPythonのパッケージマネージャのpipでも扱うことが出来るけどコンテナイメージで扱うほうが都合がよさそうなのでコンテナイメージでがんばりたい コンテナイメージで扱うというのは、docker runコマンドでyqのイメージをスポットで使う感じ yqの使い方についてはjqのyaml版と思って大丈夫。詳細は以前書いた記事を参考にしてほしい。 yqコマンド(jq wrapper for YAML)使い方備忘録 $ docker run --rm -v "$PWD:$PWD" -w="$PWD" \ --entrypoint yq linuxserver/yq \ <yqコマンド> GitHub Actions上でDockerコンテナイメージを扱う方法と注意点 やることは addnab/docker-run-action を使うだけ 基本的な使い方はaddnab/docker-run-actionの上記のリンクにサンプルコードを添えて書かれている しかし、docker runコマンドのときのように同アクションを使おうとすると、ホストとコンテナ間でマニフェストが置かれたディレクトリをマウントするところでつまずいた そこで、この記事では特に同アクションを使う際のホストとコンテナ間でディレクトリをマウント方法する方法について、yqのコンテナイメージを使って解説していきたい 2.前提 addnab/docker-run-actionの検証リポジトリはpublic public/private問わず、同Actionsを使う際の注意点は同じはずだけど念のため書いておく yqは以下のとおり2種類あるが、ここでは https://hub.docker.com/r/linuxserver/yq を扱う ↓この記事で使うyq Github https://github.com/kislyuk/yq https://github.com/mikefarah/yq Docker Image https://hub.docker.com/r/linuxserver/yq https://hub.docker.com/r/mikefarah/yq 3.環境情報 ローカル始めバージョンを書いておく必要があるものはない 使うActionやyqのイメージのバージョンについては後述するWorkflowを参照してほしい 4.この記事で扱うサンプルコード(つまずいたところは解決済) yqのコンテナイメージで更新対象のマニフェスト(manifests/deployment.yml.tmpl) 書き換え箇所はマニフェストのごく一部なので抜粋する --- apiVersion: apps/v1 kind: Deployment metadata: # 略 spec: replicas: 3 selector: matchLabels: app: sampleapp template: metadata: labels: app: sampleapp spec: affinity: # 略 containers: - name: sampleapp image: <REGISTRY>/<CONTAINER_IMAGE>:<IMAGE_TAG> ports: - containerPort: 80 yqのコンテナイメージを使うWorkflow(.github/workflows/mod_manifest.yml) jobs: main: runs-on: 'ubuntu-20.04' env: MANIFEST_PATH: 'manifests' steps: - name: Modify image tag uses: addnab/docker-run-action@v3 with: ## yqのイメージを指定 image: linuxserver/yq:2.13.0 ## docker runコマンドで渡していたオプションを書く ## ">"を使い、適宜改行する ## -vオプションの使い方はやや注意なので後述 options: > --rm -v ${{ github.workspace }}/${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }} -w=/opt/${{ env.MANIFEST_PATH }} --entrypoint yq shell: bash run: > yq -ry '.spec.template.spec.containers[0].image |="'${{ secrets.REGISTRY }}'/'${{ secrets.CONTAINER_IMAGE }}':'${{ github.sha }}'"' /opt/${{ env.MANIFEST_PATH }}/deployment.yml.tmpl > /opt/${{ env.MANIFEST_PATH }}/deployment.yml 5.addnab/docker-run-actionでディレクトリをマウントする間違ったやり方 -vオプションで指定するホスト側のパスを「リポジトリのルートディレクトリからマニフェストの 相対パス 」とする - name: Modify image tag uses: addnab/docker-run-action@v3 with: ## yqのイメージを指定 image: linuxserver/yq:2.13.0 ## docker runコマンドで渡していたオプションを書く ## ">"を使い、適宜改行する ## -vオプションで指定するホスト側のパスを「リポジトリのルートディレクトリからマニフェストの相対パス」とする options: > --rm -v ${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }} -w=/opt/${{ env.MANIFEST_PATH }} --entrypoint yq shell: bash run: > yq -ry '.spec.template.spec.containers[0].image |="'${{ env.REGISTRY }}'/'${{ env.CONTAINER_IMAGE }}':'${{ github.sha }}'"' /opt/${{ env.MANIFEST_PATH }}/deployment.yml.tmpl > /opt/${{ env.MANIFEST_PATH }}/deployment.yml 実行するとエラーとなってしまう、、 yq: error: argument files: can’t open ‘/opt/manifests/deployment.yml.tmpl’: [Errno 2] No such file or directory: ‘/opt/manifests/deployment.yml.tmpl’ エラーログ抜粋 Run addnab/docker-run-action@v3 with: image: linuxserver/yq:2.13.0 options: --rm -v manifests:/opt/manifests -w=/opt/manifests --entrypoint yq shell: bash run: yq -ry '.spec.template.spec.containers[0].image |="'your_registry'/'your_container_image':'xxxxxxxxxxxxxx'"' /opt/manifests/deployment.yml.tmpl > /opt/manifests/deployment.yml env: MANIFEST_PATH: manifests REGISTRY: your_registry CONTAINER_IMAGE: your_container_image 略 Unable to find image 'linuxserver/yq:2.13.0' locally 2.13.0: Pulling from linuxserver/yq 略 Digets: 略 Status: Downloaded newer image for linuxserver/yq:2.13.0 usage: yq [-h] [--yaml-output] [--yaml-roundtrip] [--width WIDTH] [--indentless-lists] [--in-place] [--version] [jq_filter] [files [files ...]] yq: error: argument files: can't open '/opt/manifests/deployment.yml.tmpl': [Errno 2] No such file or directory: '/opt/manifests/deployment.yml.tmpl' 6.解決策 -vオプションで指定するホスト側のパスを「GitHub Actionsのホスト側の 絶対パス 」とする Runnerのワーキングディレクトリは、GITHUB_WORKSPACE で取得できる! options: > - --rm -v ${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }} ##ホストの相対パス:コンテナ側の絶対パス + --rm -v ${{ github.workspace }}/${{ env.MANIFEST_PATH }}:/opt/${{ env.MANIFEST_PATH }} ##ホストの絶対パス:コンテナ側の絶対パス -w=/opt/${{ env.MANIFEST_PATH }} --entrypoint yq 7.[備考]GITHUB_WORKSPACEとは GitHubのドキュメントのGITHUB_WORKSPACEの説明文の頼りにすると、Runnerのデフォルトの作業ディレクトリと書かれている GITHUB_WORKSPACE ...

January 30, 2022 · 3 min · gkzz

asdf で kubectl のバージョンを切り替えながら asdf とそのプラグインの設定方法を理解する

1.この記事で達成したいこと asdfとそのプラグインを設定する方法が頭の中でごちゃごちゃしていた。たとえば、、。 asdf plugin-addとasdf installはどっちからコマンド実行するの? 既にプラグインはをインストールしているか?確認するのはどうやるの? そこで実際に以下のasdfのプラグインを使いながら、その設定方法を理解したい kubectl asdf-community/asdf-kubectl: Kubectl plugin for the asdf version manager 2.はじめに そもそもasdfとはなにか?という説明は公式ドキュメントに譲りたいが、ひとことでいえば バージョン管理ツール である バージョン管理の類似ツールを挙げるとすれば、pythonのvirtualenvはそのひとつであろう。相違点はバージョン管理の対象がひとつだけか複数か。(virtualenvの場合はpythonのみのひとつだけ。) asdfでバージョンを管理するためには、asdf自体のインストールすることに加えて、バージョン管理したいツールに対応したプラグインもインストールする必要 がある 3.環境情報 $ grep VERSION= /etc/os-release VERSION="20.04.3 LTS (Focal Fossa)" $ asdf --version v0.10.0-0f99d0a 4.asdf自体のインストール asdfのドキュメントに従って進めればよいが、そのインストール方法はいくつかある 今回採用した方法はasdfのリポジトリのブランチを指定してクローンするという方法 指定したリリースブランチは、release-v0.10.0 $ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch release-v0.10.0 $ tail ~/.bashrc 略 . $HOME/.asdf/asdf.sh . $HOME/.asdf/completions/asdf.bash これでasdfのインストールは終わった。いよいよプラグインのインストールに移るが、ややこしく感じたので大まかな流れをおさえておきたい。 5.バージョン管理したいプラグインのインストールと設定の大まかな流れ 必要になったプラグインあるいはそのバージョンが既にあるか確認 $ asdf plugin list | grep <プラグイン> プラグインがなければ追加 $ asdf plugin-add <プラグイン> <リポジトリ> 任意のバージョンをインストール $ asdf install <プラグイン> <バージョン> asdf global/localで導入 $ asdf local <プラグイン> <バージョン> 導入したプラグインとそのバージョンが書かれていることを確認 $ asdf current $ cat .tool-versions (不要なバージョンはuninstall) $ asdf uninstall <プラグイン> <バージョン> 参考:https://asdf-vm.com/guide/getting-started.html#install-the-plugin ...

January 13, 2022 · 2 min · gkzz

direnvでAWSの名前付きプロファイル($HOME/.aws/config)をディレクトリに沿って自動的に指定する

1.この記事で達成したいこと $HOME/.aws/configに書かれた名前付きプロファイルをイイ感じに使いたい ディレクトリごとに指定できるようにしたい AWS_DEFAULT_PROFILEを都度exportするのは面倒なので避けたい $ export AWS_DEFAULT_PROFILE=user1 2.前提/環境情報 $ grep VERSION= /etc/os-release VERSION="20.04.3 LTS (Focal Fossa)" $ direnv --version 2.21.2 3. どうやるか? direnvを使う direnvとは、ディレクトリに移動した際、自動で記載されている環境変数を読み込んでくれるもの direnvを使うことでできること ディレクトリ/環境に適したAWS_PROFILEを指定すること 前提として、$HOME/.aws/configに以下のように書かれていること [default] region=us-west-2 output=json [profile user1] region=us-east-1 output=text 出所:名前付きプロファイル - AWS Command Line Interface 4.使い方 aptでdirenvをインストール ※Installation | direnv では紹介されていなかった。。 Setup | direnv に従って ~/.bashrc を編集 $ apt search direnv | tail WARNING: apt does not have a stable CLI interface. Use with caution in scripts. Full Text Search... direnv/focal,now 2.21.2-1 amd64 [installed] ## <-- direnvがあった Utility to set directory specific environment variables extrace/focal 0.7-1 amd64 trace exec() calls system-wide ondir/focal 0.2.3+git0.55279f03-1 amd64 Automate tasks specific to certain directories in the shell $ sudo apt install direnv $ tail -n 1 ~/.bashrc eval "$(direnv hook bash) direnvを使いたいディレクトリ直下で、direnv edit . を実行し、使いたいプロファイルを書く $EDITORの値がないとエラーを引いたら、export $EDITOR=vimなどと$EDITORの値をセットすればok $ direnv edit . $ cat .envrc export AWS_PROFILE=user1 $ direnv edit . direnv: $EDITOR not found. direnv: error exit status 1 $ echo "export $EDITOR=vim" >> ~/.bashrc && source ~/.bashrc direnv allow で読み込みができるようにする $ direnv allow direnv: loading /path/to/.envrc direnv: export +AWS_PROFILE 動作確認 $ cd /path/to direnv: loading /path/to/.envrc direnv: export +AWS_PROFILE ## ディレクトリを離れると $ cd .. direnv: unloading 5.参考 名前付きプロファイル - AWS Command Line Interface Installation | direnv Setup | direnv

January 12, 2022 · 1 min · gkzz

sensitve=true な値を terraform output で確認する方法

1.この記事で達成したいこと sensitve=trueな値をterraform outputで確認したい 1-1.お悩みポイント そもそもsensitve=trueとしている理由は、terraform applyやterraform outputする際にはCLI(ターミナル)上では出力させたくないから なので、terraform applyやterraform outputする際には表示されないのが正しい! とはいえ、確認したいときはある。さて、どうするか、、??? $ terraform output aws_iam_smtp_password_v4 = <sensitive> sensitive=trueの技術的仕様はterraform.tfstateに記載されている値のうち、出力させないそれらを指定するというもの なので以下のように確認することはできるが、チョット煩わしい。シュッとやりたい。 $ cat terraform.tfstate | jq -r .outputs { "aws_iam_smtp_password_v4": { "value": "xxxxxxxxxxxxxxxxxxxxxx", "type": "string", "sensitive": true } } このような都合のいい、「ワガママ」な事情をよしなに汲み取ってterraform outputで確認するというのが本記事の目的 2.前提 Terraformのインストール方法を始めとする初期設定は終えているものとして話を進める 今回出力したくないセキュアな値は ses_smtp_password_v4 とする サンプルコードは以下のとおり $ cat main.tf resource "aws_iam_user" "dummy" { name = "dummy" path = "/dummy/" } resource "aws_iam_access_key" "dummy" { user = aws_iam_user.dummy.name } output "aws_iam_smtp_password_v4" { value = aws_iam_access_key.dummy.ses_smtp_password_v4 sensitive = true } 3.環境情報 Terraform実行環境 $ grep VERSION= /etc/os-release VERSION="20.04.3 LTS (Focal Fossa)" $ terraform version Terraform v1.1.0 on linux_amd64 + provider registry.terraform.io/hashicorp/aws v3.70.0 4.sensitive=trueとしてterraform applyするとマスクされることを確認 $ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_iam_access_key.dummy will be created + resource "aws_iam_access_key" "dummy" { + create_date = (known after apply) + encrypted_secret = (known after apply) + encrypted_ses_smtp_password_v4 = (known after apply) + id = (known after apply) + key_fingerprint = (known after apply) + secret = (sensitive value) + ses_smtp_password_v4 = (sensitive value) + status = "Active" + user = "dummy" } # aws_iam_user.dummy will be created + resource "aws_iam_user" "dummy" { + arn = (known after apply) + force_destroy = false + id = (known after apply) + name = "dummy" + path = "/dummy/" + tags_all = (known after apply) + unique_id = (known after apply) } Plan: 2 to add, 0 to change, 0 to destroy. Changes to Outputs: + aws_iam_smtp_password_v4 = (sensitive value) Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes 略 Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: aws_iam_smtp_password_v4 = <sensitive> # <-- マスクされている!(これでいいんだけど実際ちゃんと入っているか確認したい!!) 4-1.terraform outputコマンドを実行すると・・・(再掲) sensitve=trueと指定しているのでマスクされている $ terraform output aws_iam_smtp_password_v4 = <sensitive> 5.sensitve=trueな値をシュッと確認する(cat terraform.tfstateしない) terraform outputコマンドに -json オプションを付与すればok $ terraform output -json { "aws_iam_smtp_password_v4": { "sensitive": true, "type": "string", "value": "xxxxxxxxxxxxxxxxxxxxxx" } } もちろんjqで加工することもできる $ terraform output -json | \ > jq -r '.aws_iam_smtp_password_v4 | { aws_iam_smtp_password_v4: .value }' { "aws_iam_smtp_password_v4": "xxxxxxxxxxxxxxxxxxxxxx" } もっとシンプルにterraform output -jsonの結果を絞る方法として、terraform output -json ${KEY} もある ${KEY}はoutputで指定しているもの $ terraform output -json aws_iam_smtp_password_v4 "xxxxxxxxxxxxxxxxxxxxxx $ grep output main.tf output "aws_iam_smtp_password_v4" { 6.参考 sensitive=trueな値を出力させる方法について Note: When using the -json or -raw command-line flag, any sensitive values in Terraform state will be displayed in plain text. ...

January 7, 2022 · 2 min · gkzz