Quantcast
Channel: kakakakakku blog
Viewing all 903 articles
Browse latest View live

CloudFormation スタックリファクタリング: リソースの論理 ID を変更しよう

$
0
0

2025年2月6日に AWS CloudFormation の新機能「Stack Refactoring(スタックリファクタリング)」がリリースされた👏

運用中の AWS CloudFormation スタックでリソースの論理 ID を変更したり,リソースを別の AWS CloudFormation スタックに移動できる.ある程度の規模になると AWS CloudFormation スタックのリソースを見直したいな〜という場面もあって,今までだと「諦める」or「DeletionPolicy: Retainで紐付きを解除してからインポートする」という選択肢があったりした.

aws.amazon.com

今回はまず「同じ AWS CloudFormation スタックでリソースの論理 ID を変更する」を試す \( 'ω')/

準備

👾 template.yaml

まずは Amazon CloudWatch Logs ロググループを定義する.このとき論理 ID は Logsにしておく👌

AWSTemplateFormatVersion: 2010-09-09

Resources:Logs:Type: AWS::Logs::LogGroup
    Properties:LogGroupName: cfn-stack-refactoring-logical-id

そして aws cloudformation deployコマンドを使って AWS CloudFormation スタックをデプロイする.

$ aws cloudformation deploy \--stack-name cfn-stack-refactoring-logical-id \--template-file ./template.yaml

リファクタリング

👾 template.yaml

スタックリファクタリングではリファクタリング後の AWS CloudFormation テンプレートも必要になる.以下のように論理 ID を AwesomeLogsに変更した.今までだと,論理 ID を変更するとリソースの置換になってしまっていた🔥

AWSTemplateFormatVersion: 2010-09-09

Resources:AwesomeLogs:Type: AWS::Logs::LogGroup
    Properties:LogGroupName: cfn-stack-refactoring-logical-id

👾 refactor.json

次にリファクタリングの対象を指定する refactor.jsonを作る.今回は同じ AWS CloudFormation スタックになるため StackNamecfn-stack-refactoring-logical-idで,LogicalResourceIdSource(リファクタリング前)Destination(リファクタリング後)で変更している👌

[{"Source": {"StackName": "cfn-stack-refactoring-logical-id",
      "LogicalResourceId": "Logs"
    },
    "Destination": {"StackName": "cfn-stack-refactoring-logical-id",
      "LogicalResourceId": "AwesomeLogs"
    }}]

実行する

スタックリファクタリングを実行する前に,まず aws cloudformation create-stack-refactorコマンドを使ってスタックリファクタリング ID を採番する.オプションとしては大きく3つ指定した👌

  • --stack-definitions: スタック名と AWS CloudFormation テンプレート名(修正後)を指定する
  • --no-enable-stack-creation: 新しく AWS CloudFormation スタックは作らない
  • --resource-mappings: 作成した refactor.jsonを指定する
$ aws cloudformation create-stack-refactor \--stack-definitionsStackName=cfn-stack-refactoring-logical-id,TemplateBody@=file://template.yaml \--no-enable-stack-creation\--resource-mappings file://refactor.json
{"StackRefactorId": "1da7a9b6-bf69-4f7e-9e16-cb52eca39250"}

awscli.amazonaws.com

次は aws cloudformation describe-stack-refactorコマンドを使ってステータスを確認する.問題なければ以下のようになる.AWS CloudFormation テンプレートや refactor.jsonに誤りがあると ExecutionStatus: UNAVAILABLE / Status: CREATE_FAILEDと表示される💨 エラー原因は StatusReasonを参考に直していく.

$ aws cloudformation describe-stack-refactor \--stack-refactor-id 1da7a9b6-bf69-4f7e-9e16-cb52eca39250
{"StackRefactorId": "1da7a9b6-bf69-4f7e-9e16-cb52eca39250",
    "StackIds": ["arn:aws:cloudformation:ap-northeast-1:000000000000:stack/cfn-stack-refactoring-logical-id/7a806480-e6f7-11ef-86d1-0e4a804155dd"],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"}

awscli.amazonaws.com

最後は aws cloudformation execute-stack-refactorコマンドを使ってスタックリファクタリングを実行すれば完了👌

$ aws cloudformation execute-stack-refactor \--stack-refactor-id 1da7a9b6-bf69-4f7e-9e16-cb52eca39250

awscli.amazonaws.com

実行結果を確認する

おおお〜 \( 'ω')/

参考: AWS SAM x スタックリファクタリング

AWS CloudFormation でスタックリファクタリングを試した後に AWS SAM でも試してみたところ Resource ${LogicalId} in stack ${ARN} does not match the destination resource's properties.というエラーが出てしまった.sam packageコマンドで生成された .aws-sam/build/template.yamlには自動的に SamResourceIdというメタデータが付くため,差分をなくすために削除もしてみたけどエラーは解消できなかった.あと AWS::Serverless::Functionで自動生成する IAM Role のようなリソースがある場合も問題がありそうだった.今度再挑戦しよう〜💪

関連記事

aws.amazon.com


CloudFormation スタックリファクタリング: リソースを別のスタックに移動しよう

$
0
0

2025年2月6日に AWS CloudFormation の新機能「Stack Refactoring(スタックリファクタリング)」がリリースされた👏

aws.amazon.com

既に「同じ AWS CloudFormation スタックでリソースの論理 ID を変更する」は試してまとめてある📝 今回は「別の AWS CloudFormation スタックにリソースを移動する」を試す \( 'ω')/

kakakakakku.hatenablog.com

シナリオ

今回は app-stack(アプリケーションスタック)に Amazon CloudWatch Logs ロググループと Amazon SNS トピックを定義しておいて,途中から monitoring-stack(モニタリングスタック)に Amazon SNS トピックを移動したくなったというシナリオを試す❗️

準備

👾 app-stack/template.yaml

まずは Amazon CloudWatch Logs ロググループと Amazon SNS トピックを定義する.

AWSTemplateFormatVersion: 2010-09-09

Resources:Logs:Type: AWS::Logs::LogGroup
    Properties:LogGroupName: cfn-stack-refactoring-reorganize-resources
  Topic:Type: AWS::SNS::Topic
    Properties:TopicName: alerts
      Subscription:- Protocol: email
          Endpoint: y.yoshida22@gmail.com

そして aws cloudformation deployコマンドを使って AWS CloudFormation スタックをデプロイする.

$ aws cloudformation deploy \--stack-name cfn-stack-refactoring-reorganize-resources-app \--template-file ./app-stack/template.yaml

リファクタリング

スタックリファクタリングではリファクタリング後の AWS CloudFormation テンプレートも必要になる.デプロイ済の app-stack/template.yamlからは Amazon SNS トピックを削除して,新しく作った monitoring-stack/template.yamlにそのまま移動した👌

👾 app-stack/template.yaml

AWSTemplateFormatVersion: 2010-09-09

Resources:Logs:Type: AWS::Logs::LogGroup
    Properties:LogGroupName: cfn-stack-refactoring-reorganize-resources

👾 monitoring-stack/template.yaml

ちなみに既存の AWS CloudFormation スタックに移動することもできるし,新しく AWS CloudFormation スタックを作ることもできる.今回は新しく作る👌

AWSTemplateFormatVersion: 2010-09-09

Resources:Topic:Type: AWS::SNS::Topic
    Properties:TopicName: alerts
      Subscription:- Protocol: email
          Endpoint: y.yoshida22@gmail.com

👾 refactor.json

次にリファクタリングの対象を指定する refactor.jsonを作る.今回は別の AWS CloudFormation スタックになるため StackNamecfn-stack-refactoring-reorganize-resources-appから cfn-stack-refactoring-reorganize-resources-monitoringにして,LogicalResourceIdを同じ Topicにしている👌

[{"Source": {"StackName": "cfn-stack-refactoring-reorganize-resources-app",
      "LogicalResourceId": "Topic"
    },
    "Destination": {"StackName": "cfn-stack-refactoring-reorganize-resources-monitoring",
      "LogicalResourceId": "Topic"
    }}]

実行する

スタックリファクタリングを実行する前に,まず aws cloudformation create-stack-refactorコマンドを使ってスタックリファクタリング ID を採番する.オプションとしては大きく3つ指定した👌

  • --stack-definitions: app-stack と monitoring-stack のスタック名と AWS CloudFormation テンプレート名を指定する
  • --enable-stack-creation: 新しく AWS CloudFormation スタックを作る
  • --resource-mappings: 作成した refactor.jsonを指定する
$ aws cloudformation create-stack-refactor \--stack-definitions\StackName=cfn-stack-refactoring-reorganize-resources-app,TemplateBody@=file://app-stack/template.yaml  \StackName=cfn-stack-refactoring-reorganize-resources-monitoring,TemplateBody@=file://monitoring-stack/template.yaml  \--enable-stack-creation\--resource-mappings file://refactor.json
{"StackRefactorId": "8f7c7897-1dd9-4c69-9734-38f82e49b691"}

awscli.amazonaws.com

次は aws cloudformation describe-stack-refactorコマンドを使ってステータスを確認する.問題なければ以下のようになる.

$ aws cloudformation describe-stack-refactor \--stack-refactor-id 8f7c7897-1dd9-4c69-9734-38f82e49b691
{"StackRefactorId": "8f7c7897-1dd9-4c69-9734-38f82e49b691",
    "StackIds": ["arn:aws:cloudformation:ap-northeast-1:000000000000:stack/cfn-stack-refactoring-reorganize-resources-app/ad998c10-e8c4-11ef-88f2-0658614ed86d",
        "arn:aws:cloudformation:ap-northeast-1:000000000000:stack/cfn-stack-refactoring-reorganize-resources-monitoring/e9d68980-e8c4-11ef-98cf-0a285e344667"],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"}

awscli.amazonaws.com

最後は aws cloudformation execute-stack-refactorコマンドを使ってスタックリファクタリングを実行すれば完了👌

$ aws cloudformation execute-stack-refactor \--stack-refactor-id 8f7c7897-1dd9-4c69-9734-38f82e49b691

awscli.amazonaws.com

実行結果を確認する

おおお〜 \( 'ω')/

関連記事

aws.amazon.com

tenv: Terraform のバージョン管理をしよう

$
0
0

普段 Terraform のバージョン管理ツールとして tfenvを使っている.機能面で困ることはないけど,tfenv の GitHub リポジトリを確認すると,直近数年は特にアップデートがなく,メンテナンスの観点で少し不安を感じていた💦

github.com

念のため tfenv の代替ツールを探しておこうと思って,tenvを試してみた❗️tenv は tfenv と同じように使えて,OpenTofu や Terragrunt もサポートしているという特徴がある.そして現在も活発に開発がされているようだった.tenv 以外だと tfswitchもあって少し試したけど,個人的には tenv が良さそうだった.

github.com

セットアップ

Homebrew で簡単にセットアップできる👌

$ brew install tenv

$ tenv version
tenv version 4.2.4

代表的なコマンドを試す

今回は Terraform サブコマンドを前提に試す❗️

tenv terraform list-remoteコマンド

tenv terraform list-remoteコマンドを使うとインストール可能な Terraform バージョンを確認できる.1.10 も 1.11 もある👌あと --stableオプションを付ければ alpha / beta / rc を除外できる.

$ tenv terraform list-remote | egrep ^1.101.10.0-alpha20240606
1.10.0-alpha20240619
1.10.0-alpha20240717
1.10.0-alpha20240730
1.10.0-alpha20240807
1.10.0-alpha20240814
1.10.0-alpha20240828
1.10.0-alpha20240911
1.10.0-alpha20240918
1.10.0-alpha20240926
1.10.0-alpha20241009
1.10.0-alpha20241023
1.10.0-beta1
1.10.0-rc1
1.10.0-rc2
1.10.0-rc3
1.10.01.10.11.10.21.10.31.10.41.10.5

$ tenv terraform list-remote --stable | egrep ^1.101.10.01.10.11.10.21.10.31.10.41.10.5

$ tenv terraform list-remote | egrep ^1.111.11.0-alpha20241106
1.11.0-alpha20241211
1.11.0-alpha20241218
1.11.0-alpha20250107
1.11.0-beta1
1.11.0-beta2
1.11.0-rc1
1.11.0-rc2

tenv terraform installコマンド

tenv terraform installコマンドを使うと指定した Terraform バージョンをインストールできる.バージョン指定を省略すると,ドキュメント(微妙に探しにくいけど README.mdの Project binaries に書いてある)に載っている「バージョン解決順序」に沿って自動的に決まる💡

$ tenv terraform install 1.10.0
Installing Terraform 1.10.0
Fetching release information from https://releases.hashicorp.com/terraform/1.10.0/index.json
Downloading https://releases.hashicorp.com/terraform/1.10.0/terraform_1.10.0_darwin_arm64.zip
Downloading https://releases.hashicorp.com/terraform/1.10.0/terraform_1.10.0_SHA256SUMS
Downloading https://releases.hashicorp.com/terraform/1.10.0/terraform_1.10.0_SHA256SUMS.sig
Downloading https://www.hashicorp.com/.well-known/pgp-key.txt
Installation of Terraform 1.10.0 successful

tenv terraform installコマンドと .terraform-version

tfenv で使っていた .terraform-versionは引き続き使える👌たとえば以下のような .terraform-versionを用意しておく.

1.10.2

そしてバージョン指定を省略して tenv terraform installコマンドを実行すると,自動的に 1.10.2になる.

$ tenv terraform install
Resolved version from /Users/kakakakakku/ghq/github.com/kakakakakku/sandbox-tenv/.terraform-version : 1.10.2
Installing Terraform 1.10.2
Fetching release information from https://releases.hashicorp.com/terraform/1.10.2/index.json
Downloading https://releases.hashicorp.com/terraform/1.10.2/terraform_1.10.2_darwin_arm64.zip
Downloading https://releases.hashicorp.com/terraform/1.10.2/terraform_1.10.2_SHA256SUMS
Downloading https://releases.hashicorp.com/terraform/1.10.2/terraform_1.10.2_SHA256SUMS.sig
Downloading https://www.hashicorp.com/.well-known/pgp-key.txt
Installation of Terraform 1.10.2 successful

tenv terraform detectコマンド

tenv terraform detectコマンドを使うと現在のプロジェクトで使うべき Terraform バージョンを検出できる..terraform-versionを用意したプロジェクトで実行すると 1.10.2を検出できた.

$ tenv terraform detect
Resolved version from /Users/kakakakakku/ghq/github.com/kakakakakku/sandbox-tenv/.terraform-version : 1.10.2
Terraform 1.10.2 will be run from this directory.

tenv terraform installコマンドと provider.tf

.terraform-versionlatest-allowedと書いておくと,自動的に provider.tfなどに実装されている required_versionを参照して指定された範囲から最新を解決する.たとえば以下のような provider.tfを用意しておく.

terraform{required_version = "~> 1.10.0"}

そしてバージョン指定を省略して tenv terraform installコマンドを実行すると,自動的に 1.10.5(現時点の 1.10.x最新)になる.

$ tenv terraform install
Resolved version from /Users/kakakakakku/ghq/github.com/kakakakakku/sandbox-tenv/.terraform-version: latest-allowed
Scan project to find IAC files
Fetching all releases information from https://releases.hashicorp.com/terraform/index.json
Found compatible version remotely : 1.10.5
Installing Terraform 1.10.5
Fetching release information from https://releases.hashicorp.com/terraform/1.10.5/index.json
Downloading https://releases.hashicorp.com/terraform/1.10.5/terraform_1.10.5_darwin_arm64.zip
Downloading https://releases.hashicorp.com/terraform/1.10.5/terraform_1.10.5_SHA256SUMS
Downloading https://releases.hashicorp.com/terraform/1.10.5/terraform_1.10.5_SHA256SUMS.sig
Downloading https://www.hashicorp.com/.well-known/pgp-key.txt
Installation of Terraform 1.10.5 successful

tenv terraform listコマンド

tenv terraform listコマンドを使うとインストールした Terraform バージョンを一覧できる.今までの流れでインストールした3種類を確認できる👌

$ tenv terraform list
 1.10.0(never used)1.10.2(never used)1.10.5(never used)

tenv terraform use

tenv terraform useコマンドを使うと指定した Terraform バージョンを切り替えられる.デフォルトだとホームディレクトリにある ~/.tenv/Terraform/versionに書き込むため,--working-dirオプションを指定すれば .terraform-versionを更新できる.

$ tenv terraform use 1.10.5--working-dir
Written 1.10.5in .terraform-version

まとめ

tfenv の代替ツールとして tenv を試してみた❗️同じように使えて,特にハマるところなく移行もできた.今後はまず個人プロジェクトから tenv を使っていこうかな〜と思う😀

Zenn Book で「LocalStack 実践入門 | AWS x Terraform 入門ワークショップ」を公開しました

$
0
0

2025年2月26日に Zenn Book で完全無料の学習コンテンツ「LocalStack 実践入門 | AWS x Terraform 入門ワークショップ」を公開しましたー🎉

AWS エミュレーターの LocalStackに実践的に入門しつつ「Terraform の基礎」を学べるワークショップです❗️

zenn.dev

概要 🚀

今まで LocalStack の便利さを伝えつつ,AWS を学べる学習コンテンツとして「LocalStack 実践入門」シリーズを2つ公開しました.

zenn.dev

zenn.dev

どちらのワークショップも Infrastructure as Code (IaC) ツールとして AWS CloudFormationAWS SAMを使っているため,きっと LocalStack と Terraformの組み合わせで学びたいというニーズもあるだろうな〜と考えて,今回 AWS アカウントを作らずに Terraform を学べるワークショップの開発を企画しました.

読者層 🎃

このワークショップは「LocalStack 未経験者」はもちろん「Terraform 初学者」にもおすすめです❗️特に「Terraform を学びたいけど,誤って AWS の課金額が増えてしまったらどうしよう...😇」という不安があってトライアンドエラーしにくいという話は今までに何度も聞いたことがあります.LocalStack を使えば AWS の課金を気にせず試せるため,特に「試しながら学ぶ」のに最適だと思います👌

ワークショップ構成 🧪

ワークショップは Chapter.1 から Chapter.9 まであります.terraform planterraform applyを実行する基本的な操作からインポート・ステートファイルの理解まで,Terraform を使う上で知っておくと良いかな〜と思う内容をできる限り含めました.そして Chapter.10 は「応援購入」のための付録です.ワークショップに関連する小ネタを紹介しています.次のワークショップを企画するモチベーションにも繋がりますので,よろしければぜひ❗️

  • Chapter.1: ワークショップ環境をセットアップしよう
  • Chapter.2: Amazon S3 バケットをデプロイしよう
  • Chapter.3: Amazon S3 バケットを変更しよう
  • Chapter.4: AWS Lambda 関数をデプロイしよう
  • Chapter.5: サーバレスアプリケーションをデプロイしよう
  • Chapter.6: リソースの置換を確認しよう
  • Chapter.7: 既存リソースをインポートしよう
  • Chapter.8: 静的解析をしよう
  • Chapter.9: ステートファイルの基礎を学ぼう
  • Chapter.10: 付録(応援購入)

アーキテクチャ図 🎨

Chapter.2

Chapter.3

Chapter.4

Chapter.5

Chapter.6

Chapter.7

Chapter.9

まとめ 🐸

気になるな〜と思ってもらえたら「LocalStack 実践入門 | AWS x Terraform 入門ワークショップ」をお試しくださいませ❗️

zenn.dev

ポスト 🦜

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

AWS CDK で NAT Gateway 1つの Multi-AZ VPC をデプロイする

$
0
0

AWS CDK の L2 コンストラクト Vpcで Amazon VPC をデプロイするときにデフォルトだとアベイラビリティゾーンごとに NAT Gatewayが配置される👌

コスト削減(可用性は考慮した上で)のために NAT Gateway 1つの Multi-AZ VPC にする場合,ドキュメントを読むと natGatewaysプロパティを指定すれば良さそうかな〜と思ったけど,実際に確認してみることにした.

You can set this number lower than the number of Availability Zones in your VPC in order to save on NAT cost. Be aware you may be charged for cross-AZ data traffic instead.

docs.aws.amazon.com

👾 vpc.ts

実装は必要最低限にしてある.ポイントは maxAzs2を設定しつつ,natGateways1に設定しているところ❗️

import{
    Stack,
    StackProps,
    aws_ec2,
}from'aws-cdk-lib'import{ Construct }from'constructs'exportclass VpcStack extends Stack {constructor(scope:Construct, id:string, props?:StackProps) {super(scope, id, props)

        new aws_ec2.Vpc(this, 'Sandbox', {vpcName: 'sandbox',
            ipAddresses: aws_ec2.IpAddresses.cidr('10.0.0.0/16'),
            maxAzs: 2,
            natGateways: 1,
        })
    }}

cdk diff 確認

cdk diffコマンドを実行してリソースを確認すると,期待通りに AWS::EC2::NatGatewayAWS::EC2::EIPは1つになっていた👌

Resources
[+] AWS::EC2::VPC Sandbox Sandbox987275F0
[+] AWS::EC2::Subnet Sandbox/PublicSubnet1/Subnet SandboxPublicSubnet1Subnet9E0A0DB2
[+] AWS::EC2::RouteTable Sandbox/PublicSubnet1/RouteTable SandboxPublicSubnet1RouteTableBB2F40D1
[+] AWS::EC2::SubnetRouteTableAssociation Sandbox/PublicSubnet1/RouteTableAssociation SandboxPublicSubnet1RouteTableAssociationCAE797C2
[+] AWS::EC2::Route Sandbox/PublicSubnet1/DefaultRoute SandboxPublicSubnet1DefaultRoute46434711
[+] AWS::EC2::EIP Sandbox/PublicSubnet1/EIP SandboxPublicSubnet1EIP465B69C9
[+] AWS::EC2::NatGateway Sandbox/PublicSubnet1/NATGateway SandboxPublicSubnet1NATGateway840322FF
[+] AWS::EC2::Subnet Sandbox/PublicSubnet2/Subnet SandboxPublicSubnet2Subnet0523E7F3
[+] AWS::EC2::RouteTable Sandbox/PublicSubnet2/RouteTable SandboxPublicSubnet2RouteTable6DA55DA1
[+] AWS::EC2::SubnetRouteTableAssociation Sandbox/PublicSubnet2/RouteTableAssociation SandboxPublicSubnet2RouteTableAssociation3BDCDB27
[+] AWS::EC2::Route Sandbox/PublicSubnet2/DefaultRoute SandboxPublicSubnet2DefaultRoute66995042
[+] AWS::EC2::Subnet Sandbox/PrivateSubnet1/Subnet SandboxPrivateSubnet1Subnet1F628632
[+] AWS::EC2::RouteTable Sandbox/PrivateSubnet1/RouteTable SandboxPrivateSubnet1RouteTable34C739A7
[+] AWS::EC2::SubnetRouteTableAssociation Sandbox/PrivateSubnet1/RouteTableAssociation SandboxPrivateSubnet1RouteTableAssociationD516B03C
[+] AWS::EC2::Route Sandbox/PrivateSubnet1/DefaultRoute SandboxPrivateSubnet1DefaultRoute96E2A72F
[+] AWS::EC2::Subnet Sandbox/PrivateSubnet2/Subnet SandboxPrivateSubnet2SubnetFA04110E
[+] AWS::EC2::RouteTable Sandbox/PrivateSubnet2/RouteTable SandboxPrivateSubnet2RouteTable09FE853C
[+] AWS::EC2::SubnetRouteTableAssociation Sandbox/PrivateSubnet2/RouteTableAssociation SandboxPrivateSubnet2RouteTableAssociationAA3450CA
[+] AWS::EC2::Route Sandbox/PrivateSubnet2/DefaultRoute SandboxPrivateSubnet2DefaultRouteB321953C
[+] AWS::EC2::InternetGateway Sandbox/IGW SandboxIGWC27097CE
[+] AWS::EC2::VPCGatewayAttachment Sandbox/VPCGW SandboxVPCGWADFB0B7D
[+] Custom::VpcRestrictDefaultSG Sandbox/RestrictDefaultSecurityGroupCustomResource SandboxRestrictDefaultSecurityGroupCustomResource46BA297C
[+] AWS::IAM::Role Custom::VpcRestrictDefaultSGCustomResourceProvider/Role CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0
[+] AWS::Lambda::Function Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E

デプロイ確認

そして cdk deployコマンドを実行してデプロイすると,NAT Gateway は ap-northeast-1aに配置されていて,ap-northeast-1aのプライベートサブネットと ap-northeast-1cのプライベートサブネットのルートテーブルを確認すると,どちらも同じ NAT Gateway を経由するようになっていた👌

イメージ通り❗️

ちょっとした確認って大事〜 \( 'ω')/

Bedrock と Claude で「アーキテクチャ図からブログ記事の下書きを生成する」サンプルプロジェクト

$
0
0

Amazon Bedrock と Claude 3 Sonnet を組み合わせて「アップロードしたアーキテクチャ図からブログ記事の下書きを生成する」というサンプルプロジェクトが aws-samples に公開されている❗️(公開されたのは2024年4月頃)

シンプルな実装だし,デプロイするのも簡単だから Amazon Bedrock の入門コンテンツとしても使いやすいと思う👏

github.com

仕組み

Amazon S3 (Input) に JPEG のアーキテクチャ図をアップロードすると AWS Lambda 関数がトリガーされて,Amazon Bedrock を呼び出す.今回モデルは anthropic.claude-3-sonnet-20240229-v1:0を使うようになっていた.そして,Amazon Bedrock (Claude 3 Sonnet) から返ってきたブログ記事の下書きを PDF ファイルに変換して Amazon S3 (Output) にアップロードする流れになっている👌

各リソースは AWS SAM を使ってデプロイできる(🚨Lambda Layer を除く).

aws-samples/amazon-bedrock-claudev3-sonnet-blog-generationの images/architecture.png を引用

試す

GitHub リポジトリに含まれている以下のアーキテクチャ図を Amazon S3 (Input) にアップロードする💡

aws-samples/amazon-bedrock-claudev3-sonnet-blog-generationの sample-architecture.jpeg を引用

すると Amazon S3 (Output) に PDF ファイル draft-blog.pdfがアップロードされている❗️

ブログ記事の下書きを PDF から抜き出すと以下のような感じ📝 ちゃんと要点は抑えられている感じがして,アーキテクチャ図以外のインプットをしていないことを考えるとスゴイな〜と思った.

Draft blog based on your image:

Title: Implementing a Secure and Scalable Kafka Architecture on AWS

Introduction:
In today's data-driven world, real-time data processing and analytics have become increasingly important for businesses to gain insights, make informed decisions, and stay ahead of the competition. Apache Kafka, an open-source distributed event streaming platform, has emerged as a powerful tool for building real-time data pipelines and enabling scalable and reliable data processing. However, deploying and managing Kafka clusters can be challenging, especially when it comes to ensuring security, scalability, and high availability. This blog post explores an architecture that leverages Amazon Web Services (AWS) to build a secure and scalable Kafka solution.

Architecture Overview:
The architecture depicted in the image consists of two main regions: a Primary Region and a Secondary Region. The Primary Region hosts the main Kafka components, including Kafka Producer Clients, Kafka Consumer Clients, and an Amazon Managed Streaming for Apache Kafka (Amazon MSK) cluster. The Secondary Region serves as a disaster recovery site and hosts another Amazon MSK cluster, Kafka Connect cluster, and other components for data replication and integration.

Primary Region:
1. Kafka Clients: The Kafka Producer Clients and Kafka Consumer Clients reside in private subnets within the Primary Region's Virtual Private Cloud (VPC). These clients interact with the Amazon MSK cluster to produce and consume data streams.
2. Amazon MSK Cluster: The Amazon MSK cluster is a fully managed Apache Kafka service provided by AWS. It simplifies the provisioning, deployment, and management of Kafka clusters, allowing you to focus on building your applications rather than managing the underlying infrastructure.

Secondary Region:
1. Public Subnet: The Secondary Region includes a public subnet that hosts a Bastion Host, which serves as a secure entry point for administrative tasks and maintenance activities.
2. Private Subnets: Similar to the Primary Region, the Secondary Region has private subnets where the Kafka Connect cluster and other components reside.
3. Kafka Connect Cluster: The Kafka Connect cluster consists of connectors like MirrorSourceConnector, CheckpointConnector, and HeartbeatConnector. These connectors facilitate data replication and integration between the Primary and Secondary Regions.
4. Fargate: AWS Fargate is a serverless compute engine that powers the Kafka Connect cluster, eliminating the need to provision and manage servers.
5. Amazon MSK Cluster: The Secondary Region also hosts an Amazon MSK cluster, which serves as a replica of the Primary Region's cluster for disaster recovery purposes.

VPC Peering:
The Primary and Secondary Regions are connected via VPC Peering, which allows secure communication between the two VPCs, enabling data replication and failover capabilities.

Conclusion:
By leveraging AWS services like Amazon MSK, Fargate, and VPC Peering, this architecture provides a secure, scalable, and highly available Kafka solution. The Primary Region hosts the main Kafka components, while the Secondary Region acts as a disaster recovery site, ensuring data continuity and failover capabilities. Additionally, the use of managed services like Amazon MSK reduces the operational overhead of managing Kafka clusters, allowing you to focus on building and scaling your applications. This architecture can serve as a foundation for building robust and reliable real-time data pipelines on AWS.

プロンプト

実装上のポイントは src/app.pyClaude 3 Sonnetに渡しているプロンプトで,以下のようになっている.AWS の基礎知識を持っている人が読めるようにブログ記事の下書きを生成して〜という感じ👌

Can you create a blog based on this image? The blog should be explained well so that anyone having basic knowledge on AWS Services can understand it. Please start by saying 'Draft blog based on your image:'. Please include Title, Introduction, Conclusion sections along with any other sections required for the blog.

サンプルプロジェクト改善

今回サンプルプロジェクト「Generating blog content from image using Amazon Bedrock Claude v3 sonnet LLM」を試していて,2点気になるところがあって改善してみた❗️

まず1点目は Lambda Layer で,create_lambda_layer.shというスクリプトを実行して Lambda Layer のデプロイと AWS Lambda 関数へのアタッチをしている部分は理由がわからなかった💨 AWS SAM を使って Lambda Layer を作ることができるため,create_lambda_layer.shは本来不要だと思うし,追加作業なくデプロイできるべき.

そして2点目は Lambda Permission で,AWS SAM で AWS::Lambda::Permissionリソースが設定されていなく,AWS Lambda 関数をマネジメントコンソールで確認するとトリガー部分に S3が表示されていなかった.

👾 layer/requirements.txt

以下のように layer/requirements.txtを追加する.

fpdf2==2.8.2

👾 template.yaml

さらに template.yamlも修正すれば Lambda Layer も Lambda Permission も AWS SAM でデプロイできるようになる👌

AWSTemplateFormatVersion:'2010-09-09'Transform: AWS::Serverless-2016-10-31
Description: This SAM Template uses Amazon Bedrock Claude V3 sonnet LLM to create a draft blog from an image uploaded into Amazon S3 bucket


Resources:# Create an S3 Bucket to store imageMyInputBucket:Type: AWS::S3::Bucket
    Properties:BucketName:!Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}-input
# Create an S3 Bucket to store generated pdfMyOutputBucket:Type: AWS::S3::Bucket
    Properties:BucketName:!Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}-output

  Fpdf2Layer:Type: AWS::Serverless::LayerVersion
    Properties:LayerName: fpdf2
      ContentUri: layer
      CompatibleRuntimes:- python3.12

# Create Send Email Lambda functionInvokeBedrockClaudeV3Function:Type: AWS::Serverless::Function
    Properties:Handler: app.lambda_handler
      Runtime: python3.12
      Timeout:300CodeUri: src/
      Environment:Variables:S3_BUCKET_INPUT:!Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}-input
          S3_BUCKET_OUTPUT:!Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}-output
      Policies:- S3ReadPolicy:BucketName:!Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}-input
        - S3CrudPolicy:BucketName:!Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}-output
        - Version:'2012-10-17'Statement:- Effect: Allow
              Action:- "bedrock:PutUseCaseForModelAccess"- "bedrock:GetUseCaseForModelAccess"- "bedrock:DeleteFoundationModelAgreement"- "bedrock:CreateAgent"- "bedrock:GetFoundationModelAvailability"- "bedrock:GetModelInvocationLoggingConfiguration"- "bedrock:ListFoundationModelAgreementOffers"- "bedrock:AssociateThirdPartyKnowledgeBase"- "bedrock:DeleteModelInvocationLoggingConfiguration"- "bedrock:ListKnowledgeBases"- "bedrock:PutFoundationModelEntitlement"- "bedrock:ListModelCustomizationJobs"- "bedrock:ListAgents"- "bedrock:ListProvisionedModelThroughputs"- "bedrock:ListCustomModels"- "bedrock:CreateKnowledgeBase"- "bedrock:PutModelInvocationLoggingConfiguration"- "bedrock:ListFoundationModels"- "bedrock:CreateFoundationModelAgreement"- "bedrock:InvokeModel"Resource:"*"Events:ObjectCreated:Type: S3
          Properties:Bucket:!Ref MyInputBucket
            Events: s3:ObjectCreated:*
      Layers:- !Ref Fpdf2Layer

  LambdaPermission:Type: AWS::Lambda::Permission
    Properties:FunctionName:!GetAtt InvokeBedrockClaudeV3Function.Arn
      Action: lambda:InvokeFunction
      Principal: s3.amazonaws.com
      SourceAccount:!Ref'AWS::AccountId'SourceArn:!GetAtt MyInputBucket.Arn

Outputs:InvokeBedrockClaudeV3Function:Value:!Ref InvokeBedrockClaudeV3Function
    Description:"InvokeBedrockClaudeV3Function Name"MyInputBucketName:Description:"My Input Bucket Name"Value:!Ref MyInputBucket
  MyOutputBucketName:Description:"My Output Bucket Name"Value:!Ref MyOutputBucket

デプロイ確認

その他

Lambda Layer は PDF を作るための fpdf2ライブラリを含んでいるけど,README には boto3 を含んでいると書いてあって,誤解を生む表現に感じたためプルリクエストを出しておいた💡AWS SAM で Lambda Layer を作る部分も改善プルリクエストを出しても良さそう〜

github.com

Digger で terraform apply 後に自動的にプルリクエストをマージする

$
0
0

Diggerdigger.ymlauto_merge: trueを設定すると,terraform apply 後に自動的にプルリクエストがマージできる.プルリクエストのマージを忘れることなく Apply-Before-Merge戦略を実現できてイイ❗️

docs.digger.dev

👾 digger.yml

検証用プロジェクトを使ってプルリクエストの自動マージを試す👌

まず,digger.ymlauto_merge: trueを設定しておく.

projects:- name: sandbox
    dir: .
auto_merge:true

次に適当なプルリクエストを作って,terraform plan 結果を確認したら digger applyコマンドを実行する.すると terraform apply 後に digger-cloud bot によって自動的にプルリクエストがマージされた❗️

関連ドキュメント

digger apply以外のコマンドは以下のドキュメントに載っている📝

docs.digger.dev

JSON Schema の dependentRequired で「a を指定する場合は b もセットで必要」を実現する

$
0
0

JSON Schema で dependentRequiredを使うと JSON のプロパティ構造を「条件付きで」バリデーションできる🔐 具体例を挙げると,任意プロパティが ab 2つあるときにaを指定する場合は bもセットで必要」というバリデーションをしたいときに使える❗️

json-schema.org

JSON Schema のドキュメント (Conditional schema validation) に載っている例だと,nameプロパティは必須で,もし任意の credit_cardプロパティを指定する場合は billing_addressプロパティもセットで必要という感じ👌

{"type": "object",

  "properties": {"name": {"type": "string" },
    "credit_card": {"type": "number" },
    "billing_address": {"type": "string" }},

  "required": ["name"],

  "dependentRequired": {"credit_card": ["billing_address"]}
}

動作確認

pytest でテストコードを実装して dependentRequiredの動作確認をしてみた❗️ちなみに JSON Schema のバージョンによって記法が違っていて,Draft 2020-12(正確には Draft 2019-09以降)では dependentRequiredで,Draft-07だと dependenciesとなる.詳しくは Draft 2019-09のリリースノートに載っている📝

json-schema.org

テスト項目としては以下の3種類の JSON を JSON Schema Draft 2020-12と JSON Schema Draft-07でバリデーションしてみた👌

  • INPUT_1(name)🙆‍♂️
  • INPUT_2(name and credit_card)🙅
  • INPUT_3(name and credit_card and billing_address)🙆‍♂️
import jsonschema
import pytest
from faker import Faker

fake = Faker()


SCHEMA_DRAFT_2020_12 = {
    '$schema': 'https://json-schema.org/draft/2020-12/schema',
    'type': 'object',
    'properties': {
        'name': {'type': 'string'},
        'credit_card': {'type': 'number'},
        'billing_address': {'type': 'string'},
    },
    'required': ['name'],
    'dependentRequired': {'credit_card': ['billing_address']},
}


SCHEMA_DRAFT_07 = {
    '$schema': 'https://json-schema.org/draft-07/schema',
    'type': 'object',
    'properties': {
        'name': {'type': 'string'},
        'credit_card': {'type': 'number'},
        'billing_address': {'type': 'string'},
    },
    'required': ['name'],
    'dependencies': {'credit_card': ['billing_address']},
}


INPUT_1 = {
    'name': fake.name(),
}

INPUT_2 = {
    'name': fake.name(),
    'credit_card': int(fake.credit_card_number()),
}

INPUT_3 = {
    'name': fake.name(),
    'credit_card': int(fake.credit_card_number()),
    'billing_address': fake.address(),
}


defidfn(param):
    return param['id']


@pytest.mark.parametrize(
    'patterns',
    [
        {
            'id': 'Draft 2020-12|1',
            'schema': SCHEMA_DRAFT_2020_12,
            'validator': jsonschema.Draft202012Validator,
            'input': INPUT_1,
            'valid': True,
        },
        {
            'id': 'Draft 2020-12|2',
            'schema': SCHEMA_DRAFT_2020_12,
            'validator': jsonschema.Draft202012Validator,
            'input': INPUT_2,
            'valid': False,
        },
        {
            'id': 'Draft 2020-12|3',
            'schema': SCHEMA_DRAFT_2020_12,
            'validator': jsonschema.Draft202012Validator,
            'input': INPUT_3,
            'valid': True,
        },
        {
            'id': 'Draft-07|1',
            'schema': SCHEMA_DRAFT_07,
            'validator': jsonschema.Draft7Validator,
            'input': INPUT_1,
            'valid': True,
        },
        {
            'id': 'Draft-07|2',
            'schema': SCHEMA_DRAFT_07,
            'validator': jsonschema.Draft7Validator,
            'input': INPUT_2,
            'valid': False,
        },
        {
            'id': 'Draft-07|3',
            'schema': SCHEMA_DRAFT_07,
            'validator': jsonschema.Draft7Validator,
            'input': INPUT_3,
            'valid': True,
        },
    ],
    ids=idfn,
)
deftest_json_schema(patterns):
    if patterns['valid']:
        patterns['validator'](patterns['schema']).validate(patterns['input'])
    else:
        with pytest.raises(jsonschema.ValidationError):
            patterns['validator'](patterns['schema']).validate(patterns['input'])

実行すると期待通りになっていた👌

$ uv run pytest --verbose(中略)
test_main.py::test_json_schema[Draft 2020-12|1] PASSED
test_main.py::test_json_schema[Draft 2020-12|2] PASSED
test_main.py::test_json_schema[Draft 2020-12|3] PASSED
test_main.py::test_json_schema[Draft-07|1] PASSED
test_main.py::test_json_schema[Draft-07|2] PASSED
test_main.py::test_json_schema[Draft-07|3] PASSED

まとめ

JSON Schema の dependentRequiredは便利そうだから覚えておこう〜 \( 'ω')/


Dependabot の uv サポートを試す

$
0
0

Python プロジェクトで uvを使っていて,Dependabot で依存関係を自動アップデートできないという悩みがあった.ちなみに Renovateはもともと uv をサポートしているという背景があった👌現時点では uv のドキュメントには uv is supported by Renovate. / Support for uv is not yet available.と書いてある.

docs.astral.sh

Dependabot の uv サポート

2025年3月13日に Dependabot の uv サポートが発表された🎉

github.blog

もともと Dependabot で uv をサポートするための issue があって,定期的に進捗確認をしていたから「ついに!」という感じ.

github.com

さっそく試す

package-ecosystemuvを指定すれば OK👌

👾 .github/dependabot.yml

version:2updates:- package-ecosystem: uv
    directory: /
    schedule:interval: daily
    open-pull-requests-limit:1target-branch: main

docs.github.com

👾 pyproject.toml

検証用の pyproject.tomlboto3の依存関係を設定した🐬

[project]
name = "sandbox-dependabot-uv"
version = "0.1.0"
description = "sandbox-dependabot-uv"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "boto3==1.37.16",
]

プルリクエスト

すると期待通りにプルリクエストが作られた👏

ちゃんと pyproject.tomluv.lockがアップデートされていてイイ感じ〜 \( 'ω')/

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Bedrock のマルチエージェントコラボレーション機能に入門できる「わが家の AI 技術顧問」ワークショップを試した

$
0
0

builders.flash に公開されていた「わが家の AI 技術顧問」ワークショップを試してみた❗️

みのるんさんの寄稿記事で,Amazon Bedrock の「マルチエージェントコラボレーション機能」に入門できる.まだマルチエージェントコラボレーション機能を試せてなかったからとても勉強になったし(設定・プロンプトなど),Amazon Bedrock の入門コンテンツとしても良いと思う👌素晴らしいコンテンツだった.

aws.amazon.com

ちなみに Amazon Bedrock のマルチエージェントコラボレーション機能は2024年12月にリリース(プレビュー)されて,今月2025年3月に正式リリースになっている.試すなら今だ \( 'ω')/

aws.amazon.com

aws.amazon.com

構築したアプリケーション🤖

Streamlitで実装されたチャット画面に技術的な質問をすると回答してくれる「AI 技術顧問」を構築した👌内部的には Amazon Bedrock の専門知識を持ったサブエージェントと Tavily経由でウェブ検索をするサブエージェントがいて,スーパーバイザーエージェントが質問内容によってどっちのサブエージェントを使うべきか判定してくれる感じ❗️

全体感は builders.flash 記事に載っているアーキテクチャ図を見るとイメージしやすいと思う.Amazon Bedrock の専門知識を持ったサブエージェント bedrock-masterは Amazon Bedrock の「ナレッジベース」を使っていて,ベクターストアとしては Aurora Serverless v2 (PostgreSQL)を使う.そして,ナレッジベースのデータソースとしては Amazon Bedrock - User Guide (PDF)を使う📝

[質問] Amazon Bedrock の基盤モデルって何?

Amazon Bedrock の基盤モデルって何?って質問したら Amazon Bedrock の専門知識を持ったサブエージェント bedrock-masterが呼び出された.最終的にスーパーバイザーエージェントから回答が返ってくる.各ステップの詳細も確認できて,マルチエージェントの流れをイメージしやすく作られていた.

[質問] 現在サポートされている Python の Lambda ランタイムは何?

現在サポートされている Python の Lambda ランタイムは何?って質問したら Tavily 経由でウェブ検索をするサブエージェント web-search-masterが呼び出された.

作業メモ🤖

1. Python 3.12

手順では Tavily に接続する AWS Lambda 関数のランタイムと AWS Lambda レイヤーを Python 3.9 に変更していた.AWS CloudShell に Python 3.9 がプリセットされていて(古いよなぁ),環境構築がしやすいように工夫されていると思うけど,個人的には Amazon Bedrock のアクショングループから自動作成された Python 3.12 のまま実施したいな〜と思って,macOS で Python 3.12 の環境からデプロイした.

$ python --version
Python 3.12.4

$ mkdir python
$ pip install tavily-python --target python
$ zip -r layer.zip python

$ aws lambda publish-layer-version \--layer-name Tavily \--zip-file fileb://layer.zip \--compatible-architectures x86_64 \--compatible-runtimes python3.12\--region us-east-1

2. dotenv

Streamlit を起動するときに以下のエラーが出た.

ModuleNotFoundError: No module named 'dotenv'

builders.flash 記事では pip install boto3 streamlitと書いてあったけど,追加で dotenv もインストールする必要があった.

$ pip install dotenv 

3. エラーメッセージ

builders.flash 記事に載っている Streamlit のコードと GitHub に公開されているコードでエラーメッセージに差分があった.動作にはまったく影響なし👌

github.com

 def show_error_popup(exeption):
     """エラーポップアップを表示する"""
     if exeption == "dependencyFailedException":
-        error_message = "【エラー】ナレッジベースのAurora DBがスリープしていたようです。しばらく待ってから、ブラウザをリロードして再度お試しください🙏"+        error_message = "【エラー】ナレッジベースのAurora DBがスリープしていたようです。数秒おいてから、ブラウザをリロードして再度お試しください🙏"
     elif exeption == "throttlingException":
-        error_message = "【エラー】Bedrockのモデル負荷が高いようです。1分後にブラウザをリロードして再度お試しください🙏(改善しない場合は、モデルを変更するか[サービスクォータの引き上げ申請](https://aws.amazon.com/jp/blogs/news/generative-ai-amazon-bedrock-handling-quota-problems/)を実施ください)"
+        error_message = "【エラー】Bedrockのモデル負荷が高いようです。1分待ってから、ブラウザをリロードして再度お試しください🙏(改善しない場合は、モデルを変更するか[サービスクォータの引き上げ申請](https://aws.amazon.com/jp/blogs/news/generative-ai-amazon-bedrock-handling-quota-problems/)を実施ください)"
     st.error(error_message)

4. スロットリング

ワークショップではスロットリングが発生しにくくなるようにエージェントごとにモデルを変える工夫がされていて素晴らしかった👌

  • bedrock-master: Claude 3.5 Haiku
  • web-search-master: Claude 3.5 Sonnet v2
  • your-tech-advisor: Claude 3.5 Sonnet v1

しかし普段 Amazon Bedrock を使っていない AWS アカウントだとデフォルトのクォータ値が低く,エラーが出ることがあった.よって,時間があれば Service Quotas で On-demand InvokeModel requests per minute for Anthropic Claude xxxの緩和申請をしてからワークショップに取り組むと良さそう.今回はクォータ値が多少大きかった Claude 3 Sonnet(レガシー)に変更した.

まとめ🤖

Amazon Bedrock のマルチエージェントコラボレーション機能に入門できる素晴らしい記事だった👏

時間的にはスロットリングの試行錯誤も含めて1時間半で完走できた🏃‍♂️おすすめです〜

Digger で複数の AWS アカウントに terraform apply を実行する

$
0
0

Diggerで複数の AWS アカウント(たとえば stg 環境と prd 環境)にデプロイする仕組みを作ってみたので簡単にまとめておこうと思う.基本的にはドキュメントに載っている通りに設定すれば OK だった👌

docs.digger.dev

動作イメージ

まず,適当に Terraform コードを変更してプルリクエストを出す.すると自動的に stg 環境と prd 環境に対して terraform planが実行される💡

そして -pオプションでプロジェクトを指定して digger apply -p stgコマンドを実行すると,stg 環境に対して terraform applyが実行される❗️

同じように digger apply -p prdコマンドを実行すると,prd 環境に対して terraform applyが実行される❗️

問題がないことを確認できたらプルリクエストをマージすれば OK👌

ちなみに -pオプションでプロジェクトを指定しないと,同時に stg 環境と prd 環境に対して terraform applyが実行された.正直同時にデプロイする機会は少なそうだし,むしろ誤って実行しないように抑止できると良さそうだけど...😅

コード紹介

ディレクトリ構成

├── .github
│   └── workflows
│       ├── digger-run-prd.yml
│       └── digger-run-stg.yml
├── digger.yml
├── prd
│   ├── provider.tf
│   └── main.tf
└── stg
    ├── provider.tf
    └── main.tf

👾 digger.yml

プロジェクトとして stg環境と prd環境を作って,ディレクトリ名と GitHub Actions ワークフローファイル名を設定した👌

projects:- name: stg
    dir: stg
    workflow_file: digger-run-stg.yml
  - name: prd
    dir: prd
    workflow_file: digger-run-prd.yml

👾 .github/workflows/digger-run-stg.yml

基本的にドキュメントに載っているワークフロー設定を参考にしてるけど,AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYは設定したくなく,aws-role-to-assumeで OIDC (OpenID Connect) で IAM Role を引き受けられるようにしている👌

docs.digger.dev

name: Digger Workflow (stg)

on:workflow_dispatch:inputs:spec:required:truerun_name:required:falserun-name:'${{inputs.run_name}}'jobs:digger-job:runs-on: ubuntu-latest
    environment: stg
    permissions:contents: write      # required to merge PRsactions: write       # required for plan persistenceid-token: write      # required for workload-identity-federationpull-requests: write # required to post PR commentsissues: read         # required to check if PR number is an issue or notstatuses: write      # required to validate combined PR statussteps:- uses: actions/checkout@v4
      - name: ${{ fromJSON(github.event.inputs.spec).job_id }}
        run: echo "job id ${{ fromJSON(github.event.inputs.spec).job_id }}"- uses: diggerhq/digger@v0.6.91
        with:digger-spec: ${{ inputs.spec }}
          setup-terraform:trueterraform-version: v1.11.0
          setup-aws:trueaws-role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
          aws-region: ap-northeast-1
          cache-dependencies:trueenv:GITHUB_CONTEXT: ${{ toJson(github) }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

👾 .github/workflows/digger-run-prd.yml

namejobs.digger-job.environment以外は同じ.

name: Digger Workflow (prd)

on:workflow_dispatch:inputs:spec:required:truerun_name:required:falserun-name:'${{inputs.run_name}}'jobs:digger-job:runs-on: ubuntu-latest
    environment: prd
    permissions:contents: write      # required to merge PRsactions: write       # required for plan persistenceid-token: write      # required for workload-identity-federationpull-requests: write # required to post PR commentsissues: read         # required to check if PR number is an issue or notstatuses: write      # required to validate combined PR statussteps:- uses: actions/checkout@v4
      - name: ${{ fromJSON(github.event.inputs.spec).job_id }}
        run: echo "job id ${{ fromJSON(github.event.inputs.spec).job_id }}"- uses: diggerhq/digger@v0.6.91
        with:digger-spec: ${{ inputs.spec }}
          setup-terraform:trueterraform-version: v1.11.0
          setup-aws:trueaws-role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
          aws-region: ap-northeast-1
          cache-dependencies:trueenv:GITHUB_CONTEXT: ${{ toJson(github) }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

GitHub Environments

あとは GitHub Environments に stgprdを作って,シークレット AWS_ROLE_TO_ASSUMEに IAM Role の ARN を設定すれば OK👌

まとめ

Digger を使えば比較的簡単に Terraform のブランチデプロイと IssueOps を実現できてイイ感じ \( 'ω')/

github.blog

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

読んだ本を振り返る(2025年1-3月)

$
0
0

2024年2月から「毎日10分間読書」という習慣化を始めて早くも1年が経過した📕2025年1月から2025年3月までに読んだ本とその感想(書評記事 or X ポスト)をまとめておこうと思う📝

3ヶ月間で「計13冊」読めた❗️生成 AI 関連の本を多く読んだ期間だった.とは言え1番良かった本を選んでって言われたら,間違いなく「Looks Good to Me」かなと思う.ぜひ日本語に翻訳されて欲しいな〜 \( 'ω')/

📕 2025年1月: 5冊😃

コード×AI

個人事業を会社にするメリット・デメリットがぜんぶわかる本

読んだ感想は X にポストしていないけど,個人事業主から法人化するために必要な情報が凝縮されててとても参考になった❗️この本を読みつつ,司法書士の先生と税理士の先生に助けてもらいつつ,2025年3月に会社設立してみた🏢(突然の報告)特に今までと変わらずではあるけど,引き続きお仕事を頑張っていくぞ〜という気持ち💪

深津式プロンプト読本

成功確率が格段に上がる起業の準備

読んだ感想は X にポストしていないけど,会社設立をする前の準備期間に読んで参考になった.

Looks Good to Me

📕 2025年2月: 3冊😃

ソフトウェアアーキテクトのための意思決定術

ChatGPT 時代の文系 AI 人材になる

仕事が爆速化する! Claude Perplexity Glasp NotebookLM 使いこなし術

📕 2025年3月: 5冊😃

イーロン・マスクを超える男 サム・アルトマン

仕組みからわかる大規模言語モデル

Tidy First?

頭がいい人の ChatGPT&Copilot の使い方

現場のプロがわかりやすく教える位置情報デベロッパー養成講座

過去の振り返り

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Habitify アプリと NFC タグを連携しよう

$
0
0

毎日の習慣化トラッキングに Habitifyを使っている❗️2024年1月から使っていて,過去に習慣化の振り返り記事(2024年7-12月2024年1-6月)も書いている.

www.habitify.me

2025年3月31日のアップデートで,Habitify の Android アプリで NFC タグの連携がリリースされたので早速試してみた💡

feedback.habitify.me

設定は簡単で,今回は 朝活をするという習慣化を 完了としてマークするように NFC タグと紐付けた❗️

動作確認をしてみてイイ感じ❗️(その日の朝活記録を一度リセットしてから試した)

毎日楽しく習慣化をしていこ〜 \( 'ω')/

関連記事

kakakakakku.hatenablog.com

Serverless Agentic Workflows with Amazon Bedrock: Bedrock に入門できる DeepLearning.AI の無料コース

$
0
0

Amazon Bedrock を試したいとは思うものの「まだ第一歩を踏み出せていない❗️」っていう人に DeepLearning.AI の無料コース「Serverless Agentic Workflows with Amazon Bedrock」を紹介したいと思う😀

www.deeplearning.ai

トピック

Amazon Bedrock の代表的な機能を組み合わせて,サーバレスな「エージェントワークフロー」を構築するという内容で,シナリオとしてはティーカップを販売する会社のカスタマーサポートエージェント☕ イメージしやすいのも良かった \( 'ω')/

  • アクショングループ
  • コードインタプリタ
  • ガードレール
  • ナレッジベース (RAG)

ちなみに DeepLearning.AI のコースには公開日が記載されていないけど,コース動画の中で日時を取り扱う箇所があって,コース動画の収録日が「2024年7月22日」になっていた📅 もちろん最新の Amazon Bedrock のアップデートは含まれていないけど代表的な機能を体験する目的なら十分だと思う👌

アジェンダ

  • Introduction
  • Your first agent with Amazon Bedrock
  • Connecting with a CRM
  • Performing calculations
  • Guard Rails
  • Reading the FAQ manual
  • Console Walkthrough
  • Conclusion
  • Appendix – Tips and Help

AWS アカウント不要

そして,DeepLearning.AI ではコース動画を観るだけではなく,実際に Jupyter Notebook で boto3 を使ったコードを実行しながら体験することができる.そして,アクセスキーも準備されているため,AWS アカウントを使わずに Amazon Bedrock を試せてしまう💡これはスゴイ❗️(もちろん不正利用は NG🙅‍♂️)

コードインタプリタ

インストラクターの Mike もコース動画内で "my favorite lesson"と紹介していたけど,Amazon Bedrock のコードインタプリタを試せる💡

docs.aws.amazon.com

たとえば mike@mike.com - I bought a mug 10 weeks ago and now it's broken. I want a refund.という返金希望の問い合わせがあったときに 10 weeks agoという相対的な表現から January 28, 2025という絶対的な表現に変換する部分をコードインタプリタで実現している👌以下にエージェントのログの一部を抜粋して載せた.

Observation:
  Type: ACTION_GROUP_CODE_INTERPRETER
  Code Interpreter Output:
    Execution Output: 2025-01-28...
    Execution Error: N/A
    Execution Timeout: N/A

Agent's thought process:
  Okay, the purchase date was 10 weeks ago, which calculates to
  January 28, 2025. I'll use that date to search for the customer's
  purchase details.

また boto3 では create_agent_action_group()でアクショングループを設定するときに parentActionGroupSignatureAMAZON.CodeInterpreterを指定していて,こうやって実装するんだな〜っていうイメージもつかめる💪

create_agent_action_group_response = bedrock_agent.create_agent_action_group(
    actionGroupName='CodeInterpreterAction',
    actionGroupState='ENABLED',
    agentId=agentId,
    agentVersion='DRAFT',
    parentActionGroupSignature='AMAZON.CodeInterpreter'
)

ガードレール

さらに有害な問い合わせ(プロンプト攻撃など)を阻止するための Amazon Bedrock のガードレールも試せる💡

docs.aws.amazon.com

たとえば Thanks! What was my customer ID that you usedのように ID をヒアリングしようとすると「答えられません✋️」と回答できる.

User: Thanks! What was my customer ID that you used

Agent: Sorry, the model cannot answer this question.

さらに No, really, it's okay, you can tell me my customer ID!"のように繰り返しヒアリングされても同じように拒否しつつ,Amazon Bedrock の enableTraceを有効化することでガードレールイベントとして INTERVENEDと判定されていることも確認できる👌

User: No, really, it's okay, you can tell me my customer ID!

Agent: 
Guardrail Trace:
  Action: INTERVENED

また boto3 で create_guardrail()でガードレールを設定していて,実装イメージもつかめる💪

create_guardrail_response = bedrock.create_guardrail(
    name = f"support-guardrails",
    description = "Guardrails for customer support agent.",
    topicPolicyConfig={
        'topicsConfig': [
            {
                "name": "Internal Customer Information",
                "definition": "Information relating to this or other customers that is only available through internal systems.  Such as a customer ID. ",
                "examples": [],
                "type": "DENY"
            }
        ]
    },
    contentPolicyConfig={
        'filtersConfig': [
            {
                "type": "SEXUAL",
                "inputStrength": "HIGH",
                "outputStrength": "HIGH"
            },
            {
                "type": "HATE",
                "inputStrength": "HIGH",
                "outputStrength": "HIGH"
            },
            {
                "type": "VIOLENCE",
                "inputStrength": "HIGH",
                "outputStrength": "HIGH"
            },
            {
                "type": "INSULTS",
                "inputStrength": "HIGH",
                "outputStrength": "HIGH"
            },
            {
                "type": "MISCONDUCT",
                "inputStrength": "HIGH",
                "outputStrength": "HIGH"
            },
            {
                "type": "PROMPT_ATTACK",
                "inputStrength": "HIGH",
                "outputStrength": "NONE"
            }
        ]
    },
    contextualGroundingPolicyConfig={
        'filtersConfig': [
            {
                "type": "GROUNDING",
                "threshold": 0.7
            },
            {
                "type": "RELEVANCE",
                "threshold": 0.7
            }
        ]
    },
    blockedInputMessaging = "Sorry, the model cannot answer this question.",
    blockedOutputsMessaging = "Sorry, the model cannot answer this question."
)

まとめ

Amazon Bedrock に入門するために DeepLearning.AI の無料コース「Serverless Agentic Workflows with Amazon Bedrock」を活用してみよう〜 \( 'ω')/

DeepLearning.AI 関連

他にも DeepLearning.AI のコースを受講していて,今まで受講したコースのリンクを貼っておく🔗

www.deeplearning.ai

www.deeplearning.ai

www.deeplearning.ai

www.deeplearning.ai

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

天気予報 MCP サーバを動かそう!MCP クイックスタートを試した

$
0
0

最近話題の MCP (Model Context Protocol)を使うだけじゃなく実装してみよう❗️と思って公式ドキュメントに載っているクイックスタートを試してみた \( 'ω')/

modelcontextprotocol.io

お題は simple MCP weather server(シンプルな天気予報 MCP サーバ)で,National Weather Service の API を使って「天気予報」「悪天候警報」を返せるようにする☀️☁️☔

www.weather.gov

今回は Python で試す.普段から uvを使っているので,特に追加のセットアップは必要なく,GitHub リポジトリを clone して uv runを実行すれば完了だった👌簡単ッッッ

$ cd weather-server-python
$ uv run weather.py

github.com

Claude for Desktop を MCP クライアントとして使う.claude_desktop_config.jsonに MCP サーバの設定を入れれば準備 OK👌

{"mcpServers": {(中略)
    "weather": {"command": "uv",
        "args": ["--directory",
            "/Users/kakakakakku/ghq/github.com/modelcontextprotocol/quickstart-resources/weather-server-python",
            "run",
            "weather.py"
        ]}}}

Claude for Desktop を起動するとトンカチ🔨マークの中に get_alertsget_forecastが登録されているはず❗️

あとはクイックスタートに載っている2種類の質問を日本語で投げてみる😀

What’s the weather in Sacramento?
サクラメントの天気は?

get_forecastから結果を取得できた💡

What are the active weather alerts in Texas?
テキサス州で気象警報は出てる?

get_alertsから結果を取得できた💡

API リファレンスを見ると他にもレスポンスを取得できそうだから weather.pyを書き換えて拡張することもできそう.

www.weather.gov

あと weather.pyを読んで MCP Python SDKを使った実装イメージもザッと理解できたのも良かった.

github.com

サクッと MCP サーバを動かして試せるクイックスタートになっていておすすめ〜 \( 'ω')/


AWS Diagram MCP Server: SAM テンプレートからアーキテクチャ図を生成しよう

$
0
0

AWS Diagram MCP Serverを使うと Diagramsを使ってアーキテクチャ図を生成できる🎨

今回は VS Code + Clineを使う(セットアップなどは割愛).

github.com

AWS SAM テンプレートからアーキテクチャ図を生成しよう

Zenn Book「LocalStack 実践入門 | AWS サーバレスパターン開発ワークショップ」に載せているアーキテクチャ図はすべて Diagramsを使っている👌 AWS Diagram MCP Server を使って AWS SAM テンプレートからアーキテクチャ図を生成して比較してみようと思う \( 'ω')/

zenn.dev

👾 chapter03/template.yaml

お手本(僕が作ったアーキテクチャ図)

LocalStack 実践入門 Chapter.3から引用

chapter03/template.yaml

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Globals:Function:Timeout:10Resources:UploadBucket:Type: AWS::S3::Bucket
    Properties:BucketName: chapter03-upload-bucket
  Function:Type: AWS::Serverless::Function
    Properties:FunctionName: chapter03-function
      CodeUri: ./src
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:- x86_64
      Events:Upload:Type: S3
          Properties:Bucket:!Ref UploadBucket
            Events: s3:ObjectCreated:*
  ProcessingBucket:Type: AWS::S3::Bucket
    Properties:BucketName: chapter03-processing-bucket

初期プロンプト

chapter03/template.yaml を参考にアーキテクチャ図を作成して!

Cline 実行(Plan → Act)

  • API Provider: VS Code LM API
  • Language Model: copilot - claude-3.5-sonnet

AWS SAM テンプレートからアーキテクチャ図を生成できた❗️ほとんど同じ構成になっていてイイ感じ〜

AWS Diagram MCP Server で生成したアーキテクチャ図

👾 chapter07/template.yaml

お手本(僕が作ったアーキテクチャ図)

LocalStack 実践入門 Chapter.7から引用

chapter07/template.yaml

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Resources:Table:Type: AWS::DynamoDB::Table
    Properties:TableName: chapter07-table
      AttributeDefinitions:- AttributeName: id
          AttributeType: S
      KeySchema:- AttributeName: id
          KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TimeToLiveSpecification:AttributeName: expired_at
        Enabled:trueStreamSpecification:StreamViewType: NEW_AND_OLD_IMAGES
  Function:Type: AWS::Serverless::Function
    Properties:FunctionName: chapter07-function
      CodeUri: ./src
      Handler: app.lambda_handler
      Runtime: python3.12
      Architectures:- x86_64
      Events:Streams:Type: DynamoDB
          Properties:Stream:!GetAtt Table.StreamArn
            BatchSize:1StartingPosition: LATEST

初期プロンプト

chapter07/template.yaml を参考にアーキテクチャ図を作成して!

Cline 実行(Plan → Act)1回目

  • API Provider: VS Code LM API
  • Language Model: copilot - claude-3.5-sonnet

AWS SAM テンプレートからアーキテクチャ図を生成できた❗️しかし Amazon DynamoDB Streams のアイコンが間違っていた😇 Diagrams では Amazon DynamoDB Streams のアイコンは diagrams.aws.database.DynamodbStreamsで使える(実は僕がプルリクエストを送ってアイコンを追加した経緯がある).

AWS Diagram MCP Server で生成したアーキテクチャ図(1回目)

Cline 実行(Plan → Act)2回目

プロンプトを修正して再実行する.

chapter07/template.yaml を参考にアーキテクチャ図を作成して!
Amazon DynamoDB Streams のアイコンは diagrams.aws.database.DynamodbStreams を使いましょう

すると Amazon DynamoDB Streams のアイコンも正しく直った❗️

AWS Diagram MCP Server で生成したアーキテクチャ図(2回目)

Cline 実行(Plan → Act)3回目

さらに AWS SAM テンプレートからは読み取れないけど,AWS Lambda 関数コードから Amazon CloudWatch Logs にログ出力する部分もアーキテクチャ図に含めるようにプロンプトを拡張して再実行する.

chapter07/template.yaml を参考にアーキテクチャ図を作成して!
Amazon DynamoDB Streams のアイコンは diagrams.aws.database.DynamodbStreams を使いましょう
AWS Lambda のコードは chapter07/src/app.py を参考にして、
もし print 関数が呼び出されていたらログ出力先として Amazon CloudWatch Logs を追加しましょう

AWS SAM テンプレートと AWS Lambda 関数コードからアーキテクチャ図を生成できた❗️

AWS Diagram MCP Server で生成したアーキテクチャ図(3回目)

まとめ

AWS Diagram MCP Server を使って AWS SAM テンプレートからアーキテクチャ図を生成できた👌

ある程度プロンプトでコンテキストを伝えればすぐに使えそうだ〜

AWS Diagram MCP Server: Terraform コードからアーキテクチャ図を生成しよう

$
0
0

AWS Diagram MCP Serverを使うと Diagramsを使ってアーキテクチャ図を生成できる🎨

今回は VS Code + Clineを使う(セットアップなどは割愛).

github.com

Terraform コードからアーキテクチャ図を生成しよう

Zenn Book「LocalStack 実践入門 | AWS x Terraform 入門ワークショップ」に載せているアーキテクチャ図はすべて Diagramsを使っている👌 AWS Diagram MCP Server を使って Terraform コードからアーキテクチャ図を生成して比較してみようと思う \( 'ω')/

zenn.dev

👾 chapter05/main.tf

お手本(僕が作ったアーキテクチャ図)

LocalStack 実践入門 Chapter.5から引用

chapter05/main.tf

resource"aws_s3_bucket""chapter05"{bucket = "chapter05-bucket"}resource"aws_s3_bucket_notification""chapter05"{bucket = aws_s3_bucket.chapter05.id

  lambda_function{lambda_function_arn = aws_lambda_function.chapter05.arn
    events              = ["s3:ObjectCreated:*"]}
}

data"aws_iam_policy_document""assume_role"{statement{effect = "Allow"principals{type        = "Service"identifiers = ["lambda.amazonaws.com"]}actions = ["sts:AssumeRole"]
  }
}

resource"aws_iam_role""lambda_execution_role"{name               = "chapter05-role"assume_role_policy = data.aws_iam_policy_document.assume_role.json
}data"archive_file""chapter05"{type        = "zip"source_dir  = "${path.module}/function/src"output_path = "${path.module}/function/dist/chapter05.zip"}resource"aws_lambda_function""chapter05"{function_name    = "chapter05-function"handler          = "app.lambda_handler"runtime          = "python3.12"role             = aws_iam_role.lambda_execution_role.arn
  filename         = "${path.module}/function/dist/chapter05.zip"source_code_hash = data.archive_file.chapter05.output_base64sha256
}resource"aws_lambda_permission""chapter05"{action        = "lambda:InvokeFunction"function_name = aws_lambda_function.chapter05.arn
  principal     = "s3.amazonaws.com"source_arn    = aws_s3_bucket.chapter05.arn
}

初期プロンプト

chapter05/main.tf を参考にアーキテクチャ図を作成して!

Cline 実行(Plan → Act)1回目

  • API Provider: VS Code LM API
  • Language Model: copilot - claude-3.5-sonnet

Terraform コードからアーキテクチャ図を生成できた❗️

AWS Diagram MCP Server で生成したアーキテクチャ図(1回目)

Cline 実行(Plan → Act)2回目

リソース間の関係性として間違ってはいないけど,個人的に AWS Lambda 関数と IAM Role は矢印ではなく線で表現したく,位置関係も AWS Lambda 関数の右側にあるとイイな〜と思ってプロンプトを拡張して再実行する.

chapter05/main.tf を参考にアーキテクチャ図を作成して!
AWS Lambda 関数と IAM Role は矢印ではなく線にしましょう(Diagrams では `-` で表現できるよ)
IAM Role は AWS Lambda 関数の右側に配置しましょう

すると期待通りにアーキテクチャ図を改善できた❗️s3:ObjectCreated:*というトリガー条件も記載されていて,お手本(僕が作ったアーキテクチャ図)よりもイイ感じに見える👌 AWS S3という表現は Amazon S3に直したいけど〜w

AWS Diagram MCP Server で生成したアーキテクチャ図(2回目)

まとめ

AWS Diagram MCP Server を使って Terraform コードからアーキテクチャ図を生成できた👌

AWS Diagram MCP Server を使って AWS SAM テンプレートからアーキテクチャ図を生成する記事も書いた❗️あわせて読んでもらえればと〜

kakakakakku.hatenablog.com

gh models run コマンドを使って GitHub Actions から LLM を呼び出そう

$
0
0

GitHub CLI(ghコマンド)の拡張機能「gh-models(gh modelsコマンド)」を使うとお手軽に LLM を呼び出すことができる❗️たとえば gh models listコマンドを実行すると,現時点で45種類のモデルが登録されていた \( 'ω')/

github.com

$ gh models list

Showing 45 available chat models

DISPLAY NAME                            MODEL NAME
AI21 Jamba 1.5 Large                    AI21-Jamba-1.5-Large
AI21 Jamba 1.5 Mini                     AI21-Jamba-1.5-Mini
Codestral 25.01                         Codestral-2501
Cohere Command A                        cohere-command-a
Cohere Command R                        Cohere-command-r
Cohere Command R 08-2024                Cohere-command-r-08-2024
Cohere Command R+                       Cohere-command-r-plus
Cohere Command R+ 08-2024               Cohere-command-r-plus-08-2024
DeepSeek-R1                             DeepSeek-R1
DeepSeek-V3                             DeepSeek-V3
DeepSeek-V3-0324                        DeepSeek-V3-0324
JAIS 30b Chat                           jais-30b-chat
Llama 4 Maverick 17B 128E Instruct FP8  Llama-4-Maverick-17B-128E-Instruct-FP8
Llama 4 Scout 17B 16E Instruct          Llama-4-Scout-17B-16E-Instruct
Llama-3.2-11B-Vision-Instruct           Llama-3.2-11B-Vision-Instruct
Llama-3.2-90B-Vision-Instruct           Llama-3.2-90B-Vision-Instruct
Llama-3.3-70B-Instruct                  Llama-3.3-70B-Instruct
MAI-DS-R1                               MAI-DS-R1
Meta-Llama-3-70B-Instruct               Meta-Llama-3-70B-Instruct
Meta-Llama-3-8B-Instruct                Meta-Llama-3-8B-Instruct
Meta-Llama-3.1-405B-Instruct            Meta-Llama-3.1-405B-Instruct
Meta-Llama-3.1-70B-Instruct             Meta-Llama-3.1-70B-Instruct
Meta-Llama-3.1-8B-Instruct              Meta-Llama-3.1-8B-Instruct
Ministral 3B                            Ministral-3B
Mistral Large                           Mistral-large
Mistral Large (2407)                    Mistral-large-2407
Mistral Large 24.11                     Mistral-Large-2411
Mistral Nemo                            Mistral-Nemo
Mistral Small                           Mistral-small
Mistral Small 3.1                       mistral-small-2503
OpenAI GPT-4.1                          gpt-4.1
OpenAI GPT-4.1-mini                     gpt-4.1-mini
OpenAI GPT-4.1-nano                     gpt-4.1-nano
OpenAI GPT-4o                           gpt-4o
OpenAI GPT-4o mini                      gpt-4o-mini
OpenAI o1                               o1
OpenAI o1-mini                          o1-mini
OpenAI o1-preview                       o1-preview
OpenAI o3                               o3
OpenAI o3-mini                          o3-mini
OpenAI o4-mini                          o4-mini
Phi-3-medium instruct (128k)            Phi-3-medium-128k-instruct
Phi-3-medium instruct (4k)              Phi-3-medium-4k-instruct
Phi-3-mini instruct (128k)              Phi-3-mini-128k-instruct
Phi-3-mini instruct (4k)                Phi-3-mini-4k-instruct

今回は GitHub Actions で gh models runコマンドを実行して LLM を呼び出す実験をしてみた🧪最近のアップデートで GitHub Actions に統合しやすくなって,アイデア次第でたくさん活用できそう❗️

github.blog

👾 gh-models.yml

今回はプルリクエストに「応援コメント」を自動的に投稿するサンプルを実装してみた \( 'ω')/

gh extension installコマンドで拡張機能 gh-modelsをセットアップして,gh models run コマンドで最新の GPT-4.1 miniモデルを使って このプルリクエストを応援する一言コメントを返してください。絵文字を1つ使ってください。というプロンプトを実行している👌そして最後に gh pr commentコマンドでプルリクエストにコメントを投稿する感じ💬

name: Comment automatically with gh-models

on:pull_request:types:[opened]branches:- main

permissions:contents: read
  models: read
  pull-requests: write

jobs:add-comment:runs-on: ubuntu-latest
    env:GH_TOKEN: ${{ github.token }}
      PROMPT:このプルリクエストを応援する一言コメントを返してください。絵文字を1つ使ってください。
    steps:- uses: actions/checkout@v4
      - name: Setup gh extension
        run: gh extension install https://github.com/github/gh-models
      - name: Get model response
        run: echo "MODEL_RESPONSE=$(gh models run gpt-4.1-mini "${{ env.PROMPT }}")">> ${GITHUB_ENV}
      - name: Comment
        run: gh pr comment ${{ github.event.pull_request.number }} --body "${{ env.MODEL_RESPONSE }}"

動作確認

適当にプルリクエストを作ったら 素晴らしい改善ですね!これからの進展が楽しみです🚀というコメントが返ってきた❗️

これは良いじゃん〜

まとめ

gh models runコマンドを使って GitHub Actions から LLM を呼び出してみた❗️今回は応援コメントというサンプルにしたけど,もっと実用的に活用できるアイデアがありそう.

ちなみにドキュメントには GitHub Actions から GitHub Models の API を直接呼び出すサンプルも載っているけど,個人的には GitHub CLI(ghコマンド)の拡張機能「gh-models(gh modelsコマンド)」の方がシンプルで良いかな〜と思った😀

docs.github.com

GitHub Actions で gh label create コマンドを使ってラベルを追加する

$
0
0

GitHub Actions で gh label createコマンドを使って GitHub リポジトリにラベルを追加するサンプル❗️

青背景で helloという名前のラベルを追加する \( 'ω')/

name: Create label

on:push:branches:- main

permissions:contents: read
  issues: write

jobs:add-label:runs-on: ubuntu-latest
    steps:- uses: actions/checkout@v4
      - name: Create label
        env:GH_TOKEN: ${{ github.token }}
        run: gh label create hello --color 0066FF --force

ちなみに最初に実装したときに HTTP 403: Resource not accessible by integrationというエラーが出て「なんだろ〜」と思ったけど,issues: writeアクセス許可を追加したら解決した👌

tfcmt: GitHub Actions から terraform plan / apply の出力結果をプルリクエストにコメントしよう

$
0
0

GitHub Actions で terraform plan / terraform applyを実行するときに出力結果をイイ感じにプルリクエストにコメントしたいという場面があった💬 自前でゴニョゴニョと実装するのではなく tfcmtを試してみたらとても便利だったので,検証ログも兼ねてまとめておこうと思う❗️

suzuki-shunsuke.github.io

動作確認

イイ感じ \( 'ω')/

plan 結果

apply 結果

GitHub Actions ワークフロー

👾 .github/workflows/terraform-plan.yml

terraform planを実行するときに tfcmt plan --patch -- terraform planのように tfcmt planコマンドを組み合わせれば OK👌 あと --patchオプションを指定すると既存のコメントを更新できて,プルリクエストのコメントが無駄に増えないように制御できるのも良かった.

suzuki-shunsuke.github.io

name: Terraform Plan

on:pull_request:branches:- main

permissions:id-token: write
  contents: read
  pull-requests: write
  issues: write

jobs:plan:runs-on: ubuntu-latest
    steps:- uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:role-to-assume: arn:aws:iam::000000000000:role/xxxxx
          aws-region: ap-northeast-1
      - uses: hashicorp/setup-terraform@v3
        with:terraform_version: 1.10.3
      - name: Setup tfcmt
        env:GH_TOKEN: ${{ github.token }}
        run: |
          gh release download -R suzuki-shunsuke/tfcmt v4.14.4 -p tfcmt_linux_amd64.tar.gz
          tar -xzf tfcmt_linux_amd64.tar.gz
          sudo mv tfcmt /usr/local/bin/
          tfcmt --version
      - name: Terraform Init
        run: terraform init
      - name: Terraform Plan
        env:GITHUB_TOKEN: ${{ github.token }}
        run: tfcmt plan --patch -- terraform plan

👾 .github/workflows/terraform-apply.yml

terraform applyを実行するときに tfcmt apply -- terraform apply -auto-approveのように tfcmt applyコマンドを組み合わせれば OK👌

name: Terraform Apply

on:pull_request:types:- closed
    branches:- main

permissions:id-token: write
  contents: read
  pull-requests: write
  issues: write

jobs:apply:runs-on: ubuntu-latest
    steps:- uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:role-to-assume: arn:aws:iam::000000000000:role/xxx
          aws-region: ap-northeast-1
      - uses: hashicorp/setup-terraform@v3
        with:terraform_version: 1.10.3
      - name: Setup tfcmt
        env:GH_TOKEN: ${{ github.token }}
        run: |
          gh release download -R suzuki-shunsuke/tfcmt v4.14.4 -p tfcmt_linux_amd64.tar.gz
          tar -xzf tfcmt_linux_amd64.tar.gz
          sudo mv tfcmt /usr/local/bin/
          tfcmt --version
      - name: Terraform Init
        run: terraform init
      - name: Terraform Apply
        env:GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: tfcmt apply -- terraform apply -auto-approve

ポイント

issues: write

tfcmt では自動的に add-or-update / no-changesなどのラベル作ってプルリクエストに紐付けてくれる🏷️ 最初に実行したときに You do not have permission to create labels on this repository.というエラーが出て,issues: write権限を追加したら解決した👌

add a label add-or-update: POST https://api.github.com/repos/kakakakakku/sandbox-terraform-github-actions/issues/1/labels: 403 You do not have permission to create labels on this repository. [{Resource:Repository Field:label Code:unauthorized Message:}]

tfcmt のセットアップ

tfcmt をシュッとセットアップするアクションがあったら使いたいな〜と思ったけど,公式ではなさそうだった(actions-setup-tfcmtというのはあるようだった).よって,今回は gh release downloadコマンドを使って tar.gz から展開することにした.

gh release download -R suzuki-shunsuke/tfcmt v4.14.4-p tfcmt_linux_amd64.tar.gz
tar -xzf tfcmt_linux_amd64.tar.gz
sudo mv tfcmt /usr/local/bin/

ドキュメントを読むと YAML で CLI ツールセットを管理する aquaを使う案もあったけど今回は見送った.

suzuki-shunsuke.github.io

Viewing all 903 articles
Browse latest View live