yasudacloudの日記

札幌に住むソフトウェアエンジニア

BacklogのGitリポジトリをCodeCommitに同期するHow To

長くコードを書く仕事をしていると、たまに不思議な構成に出会うものです。

例えば特定のGitホスティングでソース管理をしていて、他のGitホスティングと同期させるような手順を要求されることがあります。私は今このケースに直面しており、複雑なデプロイ手順に時間を費やして負担になっています。

そこで今回は掲題の通りBacklogのGitをCodeCommitに自動同期させる検証を行いたいと思います。

サンプルコードはこちらにアップ済み

Gitの同期のあれこれ

本件とは関係ありませんが、GitHubやGitLabだと下記のように簡単に同期する方法が色々ヒットします。

dev.classmethod.jp

zenn.dev

しかし、Backlogから他のGit(特にCodeCommit)への同期は情報が少なく、一番近かったのがフェンリルさんのこちらの記事でした。

engineers.fenrir-inc.com

上記の方法ではBacklog -> API Gateway -> CodeBuildと動いてGitの同期処理を行なっているようです。

このままでも充分なんですが、せっかくなので別のアプローチで実現してみたいと思います😎

構成

気になる構成は、

 

こんな感じでいきます。非常にシンプルです。これで実現できるのかと疑問を持たれるかもしれませんが、いけます。

CodePipelineやAPI Gateway、Chatbot、CloudWatchなどを組み合わせたいところですが、この手の仕組みはサクッと動くものが欲しいという人も多いと想像して極力シンプルにしました。個人ブログなのでニッチな路線を突き進みます。

環境の準備

まずLamdbaはPythonで書きますが、ローカルでコードを書いて気軽にデプロイしたいのでServerless Frameworkを使います。ServerlessFWを使ったサンプルはこちらに公開してますが、本記事ではServerlessFWを使わなくても(知らなくても)分かるように説明していきます。

次に、コードでGitを操作するためにライブラリが必要になります。libgit2のWebサイトにいくとpygit2がPythonのライブラリになるのでこちらを取り込みます(pip install)

具体的な手順

手順は大きく3つに分けます。

1. BacklogからLambdaへのwebhook疎通

2. Lambda上でGitの操作(fetchやmerge)

3. LambdaからCodeCommitへpush

Lambdaが実行されるマシン(コンテナ)上にcloneするのでストレージサイズやタイムアウト時間、メモリを充分な値に設定する必要があります。

では実際に進めていきます。

1. BacklogからLambdaへのwebhook疎通

まずはLambdaを関数URLにして一つのHttpのエンドポイントとして作成します。

そしてBacklogのGitリポジトリのwebhookにエンドポイントを登録します。確認方法は指定したブランチに何らかのファイル変更を行い、eventのログを取ったりすればひとまず疎通は完了です。

Backlogのwebhook周りの情報はこちらに記載があります。

Gitの概要 – Backlog ヘルプセンター

Webhook 送信サーバーの IP アドレスを教えてください – Backlog ヘルプセンター

接続元の認証、つまりBacklogからのリクエストかどうかを判別するHow toみたいな資料は見当たりませんでした。

接続元のIPやUserAgentで判別はできそうですが、決済代行のシステムにあるような致命的になるユースケースがあまりないと思うのでそれほど重要ではないのかもしれません。今回は受け取ったパラメータを使うわけではないので、パラメータのリポジトリURLが一致するか、という程度にします。

2. Lambda上でGitの操作(fetchやmerge)

pygit2の情報をググりまくる必要があるわけですが、ここが一番大変な部分です。

CodeCommitのリポジトリをcloneし、Backlogのリモートリポジトリを追加してmerge。ファイルの変更が1つ以上あればコミットを作成してpushをします。

コードでいうとこの辺り。

github.com

あ、さっきLambda一本と書いたのですがBacklogやCodeCommitのクレデンシャル情報はSecrets Managerから取り込んでいます。さすがに😅

3. LambdaからCodeCommitへpush

こちらも2のコードと一緒に記述しています。push自体に特筆することはありませんが、通信はsshではなくhttpsで行っています。そのため、認証にはパスワードが必要になります。

ここは結構時間をかけてsshで出来ないか試みたのですが、pygit2上でunknown hostのエラーが起きて断念しました。自前でコンテナ作ってビルド時にごにょごにょすれば突破できるんじゃないかと思ってますが検証に時間がかかるので。。

まとめ

フェンリルさんの記事にも書いてありますが、ストレージを永続化するかどうか問題があります。プロジェクトのサイズが大きい場合はcloneするだけで時間かかるので都度落とすのがネックになることがあります。

ただ、LambdaからGit操作を行っていることでコミットメッセージや完了後の通知(メールやSlack)などを自由度高く作れるのは利点だと思います。他にも、特定のファイルに変更を加えるような動的な処理を組み込むことも可能です。

 

ただ、まあ正直ちょっと面倒ですが( ´Д`)y━・~~

以上、マニアックな検証でした。