前回の記事ではSCANOSS GitHub Actionsを使った基本的なコードスキャン自動化の手順を紹介しました。基本スキャンやポリシーチェック、サブディレクトリスキャンまで確認できたところで、次に気になるのはモノレポ構成への対応です。
scanPathパラメータは単一の相対パスしか受け付けないため、複数のサブディレクトリを個別にスキャンするにはワークフロー側で工夫が必要です。本記事では、SCANOSS公式のMONOREPO_SETUP.mdで推奨されているreusable workflow(workflow_call)パターンを使い、PRで変更されたコンポーネントだけを自動スキャンする構成を実際に構築・検証します。
この記事でわかること:
- モノレポで
scanPathが抱える制約と解決策 - reusable workflow(
workflow_call)による共通スキャンワークフローの作り方 - パスフィルターとの連携で、変更コンポーネントだけスキャンする構成
- 構築時のハマりポイント(
permissionsの配置)と解決策
前提条件
- 前回の記事の内容を理解していること(基本スキャン、
scanPathの動作) - GitHubリポジトリにActions実行権限があること
- リポジトリのSettings > Secretsに
SCANOSS_KEYを登録済みであること scanoss/gha-code-scan@v1.5.0を使用
検証に使用したリポジトリ構成
本記事の検証には、application/tools/src/配下に複数のPythonパッケージを持つモノレポ構成のリポジトリを使用しました。
application/tools/src/
├── blog_scraper/ # ブログスクレイピングツール(Pythonファイル9個)
├── svg_to_png/ # SVG→PNG変換ツール(Pythonファイル6個)
├── html_to_png/ # HTMLスクリーンショットツール
├── cleanup_articles/ # 記事クリーンアップツール
├── thumbnail_generator/ # サムネイル生成ツール
├── pv_analyzer/ # PV分析ツール
└── notion_sync/ # Notion同期ツールこのうちblog_scraperとsvg_to_pngの2ディレクトリをスキャン対象として検証します。
モノレポでのスキャン課題
前回の記事で紹介したscanPathパラメータを使えば、スキャン対象をサブディレクトリに限定できます。しかし、scanPathは単一の相対パスしか受け付けません。複数パスのカンマ区切りやワイルドカードには対応していません。
# これはできる
scanPath: application/tools/src/blog_scraper
# これはできない
scanPath: application/tools/src/blog_scraper, application/tools/src/svg_to_pngモノレポで複数パッケージを個別にスキャンするには、ワークフロー側で対応が必要です。SCANOSS公式のMONOREPO_SETUP.mdでは、GitHub Actionsのreusable workflow(workflow_call)を使ったパターンが推奨されています。
ワークフローの全体構成

作成するファイルは以下の3つです。スキャン対象のコンポーネントが増えるたびにトリガーワークフローを1つ追加します。
.github/workflows/
├── scanoss-monorepo-base.yml # ベースワークフロー(共通、1つだけ)
├── scanoss-monorepo-blog-scraper.yml # blog_scraper 用トリガー
└── scanoss-monorepo-svg-to-png.yml # svg_to_png 用トリガー| ファイル | 役割 |
|---|---|
scanoss-monorepo-base.yml | workflow_callで呼び出される共通スキャン処理。scan_pathを入力として受け取る |
scanoss-monorepo-blog-scraper.yml | blog_scraperディレクトリの変更時にベースワークフローを呼び出す |
scanoss-monorepo-svg-to-png.yml | svg_to_pngディレクトリの変更時にベースワークフローを呼び出す |
ベースワークフローの作成
workflow_callで呼び出される共通のスキャンワークフローです。スキャン対象のパスをinputs.scan_pathとして受け取ります。
# .github/workflows/scanoss-monorepo-base.yml
name: SCANOSS Monorepo Base Scan
on:
workflow_call:
inputs:
scan_path:
description: 'Directory to scan'
required: true
type: string
jobs:
scanoss-scan:
name: SCANOSS Scan (${{ inputs.scan_path }})
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
checks: write
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run SCANOSS Code Scan
id: scanoss-scan
uses: scanoss/gha-code-scan@v1.5.0
with:
scanPath: ${{ inputs.scan_path }}
api.key: ${{ secrets.SCANOSS_KEY }}permissionsをジョブレベルに配置している点が重要です。トップレベルに置くとstartup_failureで失敗します。詳細は後述の「ハマりポイント」で説明します。
コンポーネント別トリガーワークフロー
各コンポーネントにつき1つのワークフローファイルを作成し、ベースワークフローを呼び出します。
# .github/workflows/scanoss-monorepo-blog-scraper.yml
name: SCANOSS Scan - blog_scraper
on:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
checks: write
actions: read
jobs:
scan:
uses: ./.github/workflows/scanoss-monorepo-base.yml
with:
scan_path: application/tools/src/blog_scraper
secrets: inherit# .github/workflows/scanoss-monorepo-svg-to-png.yml
name: SCANOSS Scan - svg_to_png
on:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
checks: write
actions: read
jobs:
scan:
uses: ./.github/workflows/scanoss-monorepo-base.yml
with:
scan_path: application/tools/src/svg_to_png
secrets: inheritsecrets: inheritでリポジトリのSecretsを呼び出し先に渡します。これにより、ベースワークフロー側で${{ secrets.SCANOSS_KEY }}が使えます。
まずはこのworkflow_dispatch(手動実行)の構成で動作確認した後、次のセクションでパスフィルターを追加します。
パスフィルターとの連携
この構成の最大の利点は、パスフィルター(on.pull_request.paths)との組み合わせです。トリガーワークフローにpathsを追加するだけで、PRで変更されたコンポーネントだけスキャンを発火させることができます。
# .github/workflows/scanoss-monorepo-blog-scraper.yml
name: SCANOSS Scan - blog_scraper
on:
pull_request:
paths:
- 'application/tools/src/blog_scraper/**'
workflow_dispatch:
permissions:
contents: write
pull-requests: write
checks: write
actions: read
jobs:
scan:
uses: ./.github/workflows/scanoss-monorepo-base.yml
with:
scan_path: application/tools/src/blog_scraper
secrets: inherit変更点はon:セクションにpull_request.pathsを追加しただけです。workflow_dispatchも残しておけば、手動実行も引き続き可能です。
この構成により、以下の動作になります。
| PRの変更内容 | blog_scraper スキャン | svg_to_png スキャン |
|---|---|---|
blog_scraper/main.pyを修正 | 実行される | 実行されない |
svg_to_png/converter.pyを修正 | 実行されない | 実行される |
| 両方を修正 | 実行される | 実行される |
docs/のみ修正 | 実行されない | 実行されない |
モノレポで7つのパッケージがある場合、全パッケージをフルスキャンすると不要なAPI呼び出しと待ち時間が発生します。パスフィルターを使えば、PRで触ったコンポーネントだけをスキャンできるため、レビューのフィードバックが速くなり、API利用量も抑えられます。
ハマりポイント:permissionsの配置
構築時に遭遇したハマりポイントを紹介します。
ベースワークフローのpermissionsをトップレベルに置くとstartup_failure
最初にベースワークフローのpermissionsをワークフローのトップレベルに配置したところ、呼び出し元のワークフローがstartup_failureで即座に失敗しました。
# NG: トップレベルに配置すると startup_failure になる
permissions:
contents: write
pull-requests: write
checks: write
actions: read
jobs:
scanoss-scan:
...startup_failureはログが一切生成されないため、原因の特定に手間取ります。
呼び出し元にpermissionsを書かないとstartup_failure
ベースワークフローのpermissionsをジョブレベルに移動しても、呼び出し元ワークフローにpermissionsがないと同じくstartup_failureで失敗します。
reusable workflowでは、呼び出し元のpermissionsが上限となります。呼び出し元にpermissionsを書かない場合はリポジトリのデフォルト権限が適用されますが、SCANOSS Code Scan Actionが必要とする権限(contents: write、checks: write等)が不足する場合にstartup_failureが発生します。
解決策
2つの対応を同時に行います。
- ベースワークフローの
permissionsをジョブレベルに配置する - 呼び出し元ワークフローにも
permissionsを明示的に記述する
本記事のワークフロー例はすべてこの対応済みの構成です。
実行結果
workflow_dispatchで手動実行した結果です。
| ワークフロー | ステータス | 実行時間 |
|---|---|---|
| SCANOSS Scan – blog_scraper | success | 40秒 |
| SCANOSS Scan – svg_to_png | success | 47秒 |
各コンポーネントが独立したワークフローランとして実行されます。GitHub Actions UIでは別々のワークフローとして表示されるため、どのコンポーネントのスキャンが失敗したかが一目でわかります。
コンポーネントの追加方法
新しいパッケージ(例: html_to_png)をスキャン対象に追加する場合、トリガーワークフローを1つ作成するだけです。ベースワークフローの変更は不要です。
# .github/workflows/scanoss-monorepo-html-to-png.yml
name: SCANOSS Scan - html_to_png
on:
pull_request:
paths:
- 'application/tools/src/html_to_png/**'
workflow_dispatch:
permissions:
contents: write
pull-requests: write
checks: write
actions: read
jobs:
scan:
uses: ./.github/workflows/scanoss-monorepo-base.yml
with:
scan_path: application/tools/src/html_to_png
secrets: inheritコピーしてscan_pathとpathsを書き換えるだけなので、追加コストは低いです。
まとめ
SCANOSS GitHub Actionsのreusable workflowパターンを使い、モノレポでコンポーネント別にスキャンを実行する構成を紹介しました。
| 項目 | ポイント |
|---|---|
| scanPathの制約 | 単一の相対パスのみ。複数パスやワイルドカードは非対応 |
| 公式推奨パターン | reusable workflow(workflow_call)でベースワークフローを共通化 |
| パスフィルター連携 | on.pull_request.pathsで変更コンポーネントだけスキャンを発火 |
| permissions | ベースワークフローはジョブレベル、呼び出し元にも明示的に記述 |
| コンポーネント追加 | トリガーワークフローを1ファイル追加するだけ |
参考資料
関連リンク
- SCANOSS Code Scan Action(GitHub リポジトリ)
- SCANOSS MONOREPO_SETUP.md(公式モノレポガイド)
- SCANOSS Code Scan Action(GitHub Marketplace)
- GitHub Actions: Reusing workflows
- GitHub Actions: paths フィルター

