解決したかった課題と開発したもの
WEBサービス開発を行っていると、ORMが生成したSQLクエリや、またはコード内に新規に追加したSQLクエリが意図しない、サービスのパフォーマンス劣化を起こしてしまうことがあります。その課題を解決すべく、それらのSQLクエリを自動テスト時に検知し、事前にExplain句などを利用してパフォーマンス計測をしたいと思い、Actionを作成しました。このActionを利用すると、下記のようにPRのコメントで新規クエリを開発者、レビューワーにお知らせします。こちらのPR が実際に動いた際の動作です。
利用方法
自動テストの実行前にMySQLのクエリログをテーブルに出力するようにします。この変更を行う専用のActionがあります。
- uses: pyama86/welcome-new-query/enable-querylog
with:
db_host: db
そして、テスト完了後に、クエリログのWhere句などを整形し、重複排除した結果と、前回のデフォルトブランチマージ時点の結果と差分を見ることで、該当のPRのコードで追加されているクエリを検知します。下記のActionをを利用します。
- uses: pyama86/welcome-new-query/analysis
with:
save_path: ./new-queries
db_host: db
aws_access_key_id : ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
s3_bucket: welcome-newquery
上記の例では突き合わせをするデフォルトブランチの結果はS3に保存しています。AWSを利用したくない場合はcacheアクションを利用して、こちらの例のように保存することもできます。
結果については steps.analysis.outputs.new_queries
に保存されているので、後続の処理で、GibHub Issueにコメントしています。
- uses: actions/github-script@v4
if: ${{ github.event_name == 'pull_request' }}
# for escape js syntax
env:
NEW_QUERIES: "${{ steps.analysis.outputs.new_queries }}"
with:
script: |
const opts = github.issues.listComments.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
per_page: 100,
})
const comments = await github.paginate(opts)
for(const comment of comments) {
if (comment.user.login === "github-actions[bot]" && comment.body.startsWith("#### New Queries found!")) {
return
}
}
const output = `#### New Queries found! 📖
<details><summary>Show Queries</summary>
\`\`\`sql
${process.env.NEW_QUERIES.replace(/\\n/g, '\n')}
\`\`\`
</details>
`;
if(process.env.NEW_QUERIES) {
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output,
})
}
最後に
ポイントは検知されたクエリをPR作成者だけでなくレビューワーも参照することができるので事前にパフォーマンスの問題についてもレビュー可能になることです。ぜひExplainのお供にご利用ください。