はじめに
e2infoではシステムリリースの準備として、ソースコードのウイルスチェックをしています。GitHubのリリースからzipをダウンロードして、手元のESETでスキャンして、検査ログを残す。という作業を手作業で実施していまいした。
リリースが月に数十回あるため、この作業の自動化を考えました。リリースを作ったらGitHub Actionsが動いてClamAVでチェックするフローに変更しました。
方針
- 検査エンジンはESETからClamAVに置き換える(GitHub Actions上で動かせるので)
- 結果結果はGitHubのリリースに貴録する
- 各リポジトリにコピーせず、共通のワークフローとして作る
結果はリリースノートの末尾に追記し、検査ログをリリースに添付することにしました。
仕組み
共通リポジトリに on: workflow_call の本体を置き、各リポジトリには呼び出すだけのYAMLを置きます。前回のDB設計書の自動出力と同じ形です。
各リポジトリに置く .github/workflows/virus-scan.yml
name: virus-scan
on:
release:
types: [published]
# 既存のタグを検査し直す場合の手動実行用。
workflow_dispatch:
inputs:
tag:
description: 検査するタグ(例:v1.2.3)
required: true
type: string
write-release:
description: 結果をリリースに書き込む
type: boolean
default: true
# リリースノートの編集とログの添付に必要。
permissions:
contents: write
concurrency:
group: virus-scan-${{ inputs.tag || github.event.release.tag_name }}
cancel-in-progress: false
jobs:
virus-scan:
uses: your-org/shared-workflows/.github/workflows/virus-scan.yml@main
with:
tag: ${{ inputs.tag }}
write-release: ${{ github.event_name == 'release' || inputs.write-release }}
本体でやっていることは次のとおりです。
- リリースの「Source code (zip)」と同じzipを
gh api repos/<repo>/zipball/<tag>で取得して展開する - 公式のDockerイメージ
clamav/clamavを起動し、freshclamで定義ファイルを最新にする clamscanで検査する- 結果をリリースノートに追記し、ログを添付する
- 検出したらジョブを失敗させる(releaseを作った人にGitHubから通知が届く)
検査の部分はこんな感じです。
- name: ウイルスを検査する
id: scan
shell: bash
run: |
(略)
status=0
docker exec clamav clamscan --stdout --recursive --alert-exceeds-max=yes /scan | tee -a "$log" || status=$?
echo "status=$status" >> "$GITHUB_OUTPUT"
zipのまま検査せずに展開しているのは、検出したときにどのファイルかをログに出したいからです。--alert-exceeds-max=yes は、サイズの上限を超えたファイルを検査しないまま通さず、検出として扱うオプションです。
リリースノートには、次のような表が追記されます。

結果
自社サービスのリリースで試したところ、ジョブ全体で56秒でした(約1,900ファイル、18MiB)。
| 処理 | 時間 |
|---|---|
| zipの取得・展開 | 2秒 |
| イメージの取得 | 3秒 |
| コンテナの起動 | 1秒 |
| 定義ファイルの更新 | 6秒 |
| 検査 | 38秒 |
事前の見込みは数分だったので、思ったより速かったです。
検出の確認は、テスト用の検体(EICAR)でやっています。EICARのファイルと、EICARを入れたzipの両方が Eicar-Test-Signature FOUND で検出され、ジョブが失敗することを確認しました。
/scan/eicar.com: Eicar-Test-Signature FOUND
/scan/sub/archive.zip: Eicar-Test-Signature FOUND
AIに任せたこと、任せなかったこと
最初の壁打ち以外は、すべてAIまかせ
- ワークフロー本体・セルフテスト・説明書の作成
- Pull Requestの作成
- Backlogの課題への記録
- 全案件のPR作成、案件担当者へのバックログ課題作成・通知。
まとめ
成功した




