Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
モノレポのGitHub(Enterprise)からCodePipelineを呼び出す小ネタ
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
hmatsu47
PRO
February 23, 2022
Technology
290
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
モノレポのGitHub(Enterprise)からCodePipelineを呼び出す小ネタ
JAWS-UG 浜松 AWS 勉強会 2022#2 2022/2/25
hmatsu47
PRO
February 23, 2022
More Decks by hmatsu47
See All by hmatsu47
中小企業に就職して転職せず30年。結果どうなった?
hmatsu47
PRO
0
84
JAWS ミート 2026 の「出し物」のゲームを Kiro と AI-DLC v2 で作った話
hmatsu47
PRO
0
15
ゲームで挑戦!VPC の気持ちになって IPv4/v6 パケットをルーティングしよう!
hmatsu47
PRO
0
29
続・名古屋城とデータセンター
hmatsu47
PRO
0
28
【再演】IPv6 VPC の実装パターンをいくつか
hmatsu47
PRO
0
33
名古屋城とデータセンター
hmatsu47
PRO
0
40
IPv6 に関する話
hmatsu47
PRO
0
29
さいきんの光ファイバーの話
hmatsu47
PRO
0
76
低いほうのレイヤを見てみる話
hmatsu47
PRO
0
35
Other Decks in Technology
See All in Technology
目の前の楽しいが人生を変える - コミュニティの螺旋の歩き方と楽しむコツ / change your life
soudai
PRO
4
590
Deploying a Full-Stack Bun-Native Framework on Cloudflare Workers
7nohe
0
160
10分で知る最近のOmarchy
komagata
0
310
AIエージェントの自己改善をどう設計するか / How to Design Self-Improvement for AI Agents
22mi
23
15k
range over func 2年間の軌跡 Issue #56413 はGoのエコシステムをどう変えたか
ryujicre8ive
0
190
絵ではじめるKubernetesセキュリティ
aoi1
3
530
生成AIエージェントを用いた、 手動テスト手順書から自動テストへの 変換手法の検討
magicpod
0
150
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
780
AI 時代のスタートアップエコシステ厶から考究する技術的負債との向き合い方
m3m0r7
PRO
2
1.9k
顧客に向き合う開発組織へ。リアーキテクチャとフィーチャーチーム化で挑む組織改革
safie
0
1.7k
幾何アルゴリズムで なめらかなピン操作を / iOSDC Japan 2026 / smoothpin
kazumanagano
0
350
銀行勘定系システムにおける開発プロセス刷新×AIによる環境モダナイゼーション / Development Process Transformation and AI-Driven Environment Modernization
muit
0
2k
Featured
See All Featured
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Paper Plane
katiecoart
PRO
4
53k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
520
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
280
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.8k
Odyssey Design
rkendrick25
PRO
2
810
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
450
Embracing the Ebb and Flow
colly
88
5.2k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
3
4.3k
How to build a perfect <img>
jonoalderson
1
6k
Six Lessons from altMBA
skipperchong
29
4.5k
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