Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
モノレポのGitHub(Enterprise)からCodePipelineを呼び出す小ネタ
Search
hmatsu47
PRO
February 23, 2022
Technology
0
240
モノレポのGitHub(Enterprise)からCodePipelineを呼び出す小ネタ
JAWS-UG 浜松 AWS 勉強会 2022#2 2022/2/25
hmatsu47
PRO
February 23, 2022
Tweet
Share
More Decks by hmatsu47
See All by hmatsu47
PostgreSQL+pgvector で GraphRAG に挑戦 & pgvectorscale 0.7.x アップデート
hmatsu47
PRO
0
8
LlamaIndex の Property Graph Index を PostgreSQL 上に構築してデータ構造を見てみる
hmatsu47
PRO
0
10
PostgreSQL+pgvector で LlamaIndex の Property Graph Index を試す(序章)
hmatsu47
PRO
0
11
HeatWave on AWS という選択肢を検討してみる
hmatsu47
PRO
0
6
HeatWave on AWS のインバウンドレプリケーションで HeatWave エンジン有効時のレプリケーションラグを確認してみた!
hmatsu47
PRO
0
16
CloudWatch Database Insights 関連アップデート
hmatsu47
PRO
0
28
さいきんの MySQL との付き合い方 〜 MySQL 8.0 より後の世界へようこそ 〜
hmatsu47
PRO
0
29
ベクトルストア入門
hmatsu47
PRO
0
25
Aurora DSQL について
hmatsu47
PRO
0
27
Other Decks in Technology
See All in Technology
Windows 11 で AWS Documentation MCP Server 接続実践/practical-aws-documentation-mcp-server-connection-on-windows-11
emiki
0
970
Snowflake Summit 2025全体振り返り / Snowflake Summit 2025 Overall Review
mtpooh
2
400
生成AI活用の組織格差を解消する 〜ビジネス職のCursor導入が開発効率に与えた好循環〜 / Closing the Organizational Gap in AI Adoption
upamune
4
2.6k
Observability infrastructure behind the trillion-messages scale Kafka platform
lycorptech_jp
PRO
0
140
SalesforceArchitectGroupOsaka#20_CNX'25_Report
atomica7sei
0
170
25分で解説する「最小権限の原則」を実現するための AWS「ポリシー」大全 / 20250625-aws-summit-aws-policy
opelab
9
1.1k
Node-RED × MCP 勉強会 vol.1
1ftseabass
PRO
0
140
あなたの声を届けよう! 女性エンジニア登壇の意義とアウトプット実践ガイド #wttjp / Call for Your Voice
kondoyuko
4
450
PHP開発者のためのSOLID原則再入門 #phpcon / PHP Conference Japan 2025
shogogg
4
750
Prox Industries株式会社 会社紹介資料
proxindustries
0
290
Amazon S3標準/ S3 Tables/S3 Express One Zoneを使ったログ分析
shigeruoda
4
520
AIの最新技術&テーマをつまんで紹介&フリートークするシリーズ #1 量子機械学習の入門
tkhresk
0
140
Featured
See All Featured
Building a Modern Day E-commerce SEO Strategy
aleyda
42
7.3k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
107
19k
Fireside Chat
paigeccino
37
3.5k
GitHub's CSS Performance
jonrohan
1031
460k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
29
9.5k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
It's Worth the Effort
3n
185
28k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
Code Reviewing Like a Champion
maltzj
524
40k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
GraphQLとの向き合い方2022年版
quramy
48
14k
A better future with KSS
kneath
239
17k
Transcript
モノレポの GitHub (Enterprise) から CodePipeline を呼び出す小ネタ JAWS-UG 浜松 AWS 勉強会 2022#2 2022/2/25
まつひさ(hmatsu47)
自己紹介 松久裕保(@hmatsu47) • https://qiita.com/hmatsu47 • 現在のステータス: ◦ 名古屋で Web インフラのお守り係をしています
◦ Aurora MySQL v1(5.6)の EoL が発表されたのでアップ開始 ▪ https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aur ora.MySQL56.EOL.html • v1 → v3 移行を画策中 2
本日の小ネタ • こちら↓の Lambda 関数を正しく動くよう実装 ◦ GitHub モノレポを AWS CodePipeline
と統合して、プロジェクト固有の CI/CD パイプラインを実行する(Amazon Web Services ブログ) • Zenn で記事化済み ◦ https://zenn.dev/hmatsu47/articles/73c624fb5730dd • 参考にした記事 ◦ Backlogの課題にGitHubのコミットを連携する方法(ponsuke_tarou’s blog) 3
モノレポの課題 • 開発プロジェクト(プロダクト・サービス)別にビルド →デプロイするのに手間が掛かる ◦ 必要がなくても全プロジェクトをビルドパイプラインが走る • そこで提示されたのが前掲の記事 ◦ GitHub
モノレポを AWS CodePipeline と統合して、プロジェクト固有の CI/CD パイプラインを実行する(Amazon Web Services ブログ) ◦ ただし動作に問題がある 4
何が問題? • 対象ブランチの指定がない ◦ どこのブランチに push してもパイプラインが実行されてしまう • コードの変更以外の操作まで拾う ◦
誤動作の可能性がある • 複数フォルダにまたがる push でも、1 本のパイプライン しか実行されない 5
修正後は • 対象ブランチの指定が可能 • パイプライン実行対象のフォルダを指定可能 • 複数フォルダにまたがる push で複数のパイプラインを並 列呼び出し可能
• 例外的に全パイプラインを並列呼び出しするフォルダの 指定が可能 6
設定の流れ(詳細は前掲の Zenn 記事を参照) 1. Secrets Manager にシークレットを保存 2. Lambda 関数を作成
3. API Gateway を作成し、Lambda 関数を統合 4. IAM Role(Lambda 実行用)にポリシーを追加 5. GitHub (Enterprise) で Webhook を設定 6. CodePipeline を設定(変更) 7
1. Secrets Manager にシークレットを保存 • GitHub → (API Gateway →)Lambda
認証時に使用 ◦ パスワードジェネレータなどで生成 ◦ Secrets Manager で「その他のシークレットのタイプ」を選択 ▪ キー : GHE_SECRETS ▪ 値 : 生成したシークレットの値 ▪ 任意の名前を付けて保存 8
2. Lambda 関数を作成 • GitHub Webhook からのリクエストを受けて、対象の CodePipeline を呼び出す ◦
コードと↓の環境変数を登録 ▪ 呼び出すパイプライン名のサフィックス : job_name_suffix • 「【フォルダ名】+【サフィックス】」の CodePipeline を呼び出します ▪ シークレット名(先ほど保存したもの) : secrets_name ▪ パイプライン実行対象のブランチ名 :trigger_branch • 「refs/heads/【ブランチ名】」の形で指定 9
2. Lambda 関数を作成 import json import hmac, hashlib import boto3
import base64 import ast, re import os from botocore.exceptions import ClientError def lambda_handler(event, context): body = event['body'] if is_correct_signature(event['headers']['x-hub-signature'], body): print('認証成功') project_names = [] job_name_suffix = os.environ['job_name_suffix'] body_json = json.loads(body) ref = body_json['ref'] if ref == os.environ['trigger_branch'] and len(body_json['commits']) > 0: # 指定ブランチへのコミットの場合だけ処理 added_files = body_json['commits'][0]['added'] removed_files = body_json['commits'][0]['removed'] modified_files = body_json['commits'][0]['modified'] + added_files + removed_files print('added / removed / modified : {}'.format(modified_files)) # どのプロジェクトのビルドを行うかファイルパスから判断 includes = ['project1', 'project2', 'project3'] pipelines_count_max = len(includes) common = ['common'] 10
2. Lambda 関数を作成 for file_path in modified_files: pos = file_path.find('/')
if pos > 0: # パスにフォルダを含む→プロジェクト名を確認 project_name = file_path[:pos] if common.count(project_name) > 0: # 共有プロジェクト名であれば全て呼び出しパイプラインに含める project_names = includes break if project_names.count(project_name) == 0: # 対象プロジェクト初検出→呼び出しパイプラインに含める project_names.append(project_name) if len(project_names) == pipelines_count_max: # すべてのプロジェクトを検出→ループを抜ける break # 対象プロジェクトをビルドするパイプラインを呼び出す print('projects : {}'.format(project_names)) if len(project_names) > 0: for project_name in project_names: return_code = start_code_pipeline('{}{}'.format(project_name, job_name_suffix)) print(return_code) return { 'statusCode': 200, 'body': json.dumps('Modified project in repo: {}'.format(project_names)) } 11
2. Lambda 関数を作成 def get_secrets_manager_dict(secret_name: str) -> dict: """Secrets Managerからシークレットのセットを辞書型で取得する"""
secrets_dict = {} if not secret_name: print('シークレットの名前未設定') else: session = boto3.session.Session() client = session.client( service_name='secretsmanager', region_name='ap-northeast-1' ) try: get_secret_value_response = client.get_secret_value( SecretId=secret_name ) except ClientError as e: print('シークレット取得失敗:シークレットの名前={}'.format(secret_name)) print(e.response['Error']) else: if 'SecretString' in get_secret_value_response: secret = get_secret_value_response['SecretString'] else: secret = base64.b64decode(get_secret_value_response['SecretBinary']) secrets_dict = ast.literal_eval(secret) return secrets_dict 12
2. Lambda 関数を作成 def get_secrets_manager_key_value(secret_name: str, secret_key: str) -> str:
"""AWS Secrets Managerからシークレットキーの値を取得する.""" value = '' secrets_dict = get_secrets_manager_dict(secret_name) if secrets_dict: if secret_key in secrets_dict: # secrets_dictが設定されていてsecret_keyがキーとして存在する場合 value = secrets_dict[secret_key] else: print('シークレットキーの値取得失敗:シークレットの名前={}、シークレットキー={}'.format(secret_name, secret_key)) return value def is_correct_signature(signature: str, body: dict) -> bool: """GitHubから送られてきた情報をHMAC認証する.""" if signature and body: # GitHubのWebhookに設定したSecretをSecrets Managerから取得する secret = get_secrets_manager_key_value(os.environ['secrets_name'], 'GHE_SECRETS') if secret: secret_bytes = bytes(secret, 'utf-8') body_bytes = bytes(body, 'utf-8') # Secretから16進数ダイジェストを作成する signedBody = "sha1=" + hmac.new(secret_bytes, body_bytes, hashlib.sha1).hexdigest() return signature == signedBody else: return False 13
2. Lambda 関数を作成 def start_code_pipeline(pipelineName): client = codepipeline_client() response =
client.start_pipeline_execution(name=pipelineName) return True cpclient = None def codepipeline_client(): global cpclient if not cpclient: cpclient = boto3.client('codepipeline') return cpclient 14 • こちらで公開中 ◦ https://github.com/hmatsu47/github-monorepo-codepipeline
3. API Gateway を作成し、Lambda 関数を統合 • HTTP の API Gateway
を作成 ◦ 先ほど作成した Lambda 関数を統合 ◦ 任意の API 名を指定 ◦ ルートのメソッドは POST に限定 ◦ ステージ名「$default」のまま自動デプロイ指定で作成 15
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow",
"Action": [ "secretsmanager:GetResourcePolicy", "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ], "Resource": "【シークレットのARN】" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "secretsmanager:GetRandomPassword", "secretsmanager:ListSecrets" ], "Resource": "*" } ] } 4. IAM Role(Lambda 実行用)にポリシーを追加 16
5. GitHub (Enterprise) で Webhook を設定 • ↓を指定して作成 ◦ Payload
URL :API Gateway の URL ▪ https://XXX.execute-api.ap-northeast-1.amazonaws.com/【リソースパス】 ◦ Content type :application/json ◦ Secret :生成したシークレット 17
6. CodePipeline を設定(変更) • Source ステージで↓のチェックを外す ◦ 検出オプションを変更する ▪ ソースコードの変更時にパイプラインを開始する
18
やってみた感想など • 意外と面倒 ◦ 情報があまり出回っていない ◦ 本当に大変なのは GitHub Webhooks 〜
Lambda よりも CodePipeline 側 ◦ GitHub Actions でやったほうが… • 事情で GitHub Actions が使えない場合の代替策 19