Если ваш Bicep вырос из «одного файлика» в маленькую экосистему из параметров, модулей и выходов — добро пожаловать в клуб. Я тоже устал «парсить глазами» зависимости по коду. Поэтому написал PSBicepGraph — модуль PowerShell, который строит семантический граф из ваших .bicep и даёт нормальные инструменты для анализа и визуализации.
Что это и зачем
PSBicepGraph:
- проходится по точке входа
main.bicep, рекурсивно подхватывает импортированные модули; - извлекает семантические зависимости между параметрами, переменными, ресурсами, модулями, аутпутами и т.д.;
- собирает из этого двунаправленный граф (
PsBidirectionalGraph); - даёт отправную точку для экспортов: GraphViz/MSAGL-графы, Design Structure Matrix (DSM), кластеризацию.
Под капотом — мой модуль PSGraph, тонкая обёртка вокруг QuickGraph/QuikGraph с утилитами для экспорта и визуализаций (включая Vega).
Текущая версия PSBicepGraph: v1.1.0-beta. Модуль опубликован в PowerShell Gallery.
Установка
Install-Module -Name PSBicepGraph -Repository PSGallery -Scope CurrentUser
Install-Module -Name PSGraph -Repository PSGallery -Scope CurrentUser
Import-Module PSBicepGraph
Import-Module PSGraph
Как это работает (коротко)
Извлечение семантики. New-BicepSemanticGraph регистрирует сервисы Bicep, резолвит путь, собирает все .bicep, компилирует и проходится по семантической модели кастомным DependencyCollectorVisitor, сопоставляя каждую декларацию с тем, на что она ссылается.
Построение графа. На основе карты зависимостей создаётся PsBidirectionalGraph — вершины (декларации) и рёбра (A→B, где A зависит от B).
Интеграция с PSGraph. Дальше — экспортируйте граф как удобно: граф-картинка, интерактивное HTML-дерево или DSM для крупных проектов.
Быстрый старт
Создадим простой storage.bicep и построим граф:
param location string = resourceGroup().location
var storageName = 'st${uniqueString(resourceGroup().id)}'
resource stg 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageName
location: location
sku: { name: 'Standard_LRS' }
kind: 'StorageV2'
}
output accountId string = stg.id
# 1) Построить семантический граф:
$graph = New-BicepSemanticGraph -Path ./storage.bicep
# 2) Экспортировать в HTML (MSAGL):
Export-Graph -Graph $graph -Format MSAGL_MDS -Path $Env:TEMP/storage.html
Start-Process $Env:TEMP/storage.html
Для многомодульного проекта:
$graph = New-BicepSemanticGraph -Path ./main.bicep
$dsm = New-DSM -Graph $graph
$ret = Start-DSMClustering -Dsm $dsm # Classic или Graph
Export-DSM -Result $ret -Format VEGA_HTML -Path $Env:TEMP/dsm.html
Start-Process $Env:TEMP/dsm.html
Пара примеров
Посмотрим к примеру avm модуль.
Его Force Directed визуализацию можно получить вот таким образом. Выглядит, она, правда, довольно мутно.
$graph = New-BicepSemanticGraph -Path "./bicep-registry-modules/avm/res/key-vault/vault/main.bicep"
Export-Graph -Graph $graph -Format Vega_ForceDirected -Path $outFile
Можно посмотреть на это с другой стороны, построить некое дерево с виртуальным корнем. Параметр -UseVirtualTreeRoot добавит виртуальный корень, если граф, вдруг, содержит более одного корня, для визуализации.
$graph = New-BicepSemanticGraph -Path "./bicep-registry-modules/avm/res/key-vault/vault/main.bicep"
$visual = Export-Graph -Graph $graph -Format Vega_TreeLayout -UseVirtualTreeRoot
Что такое DSM и почему это удобно
Design Structure Matrix — это квадратная матрица зависимостей: строки и столбцы — один и тот же набор сущностей; отметка в (i, j) означает «строка i зависит от столбца j».
В PSBicepGraph/PSGraph принята ориентация: строка = потребитель, столбец = провайдер; ребро A→B превращается в заполненную ячейку (A, B). Это компактно показывает циклы, слои и «сцепление» модулей. Кластеризация группирует взаимозависимые узлы и намекает, где провести границы. (Алгоритмы DSM ещё в работе — но посмотреть можно уже сейчас.)
Для key vault она, к сожалению, в разметку не помещается. Поэтому в качестве примера посмотрим другую, от avm/res/web/serverfarm
$graph = New-BicepSemanticGraph -Path "./bicep-registry-modules/avm/res/web/serverfarm/main.bicep"
$dsm1 = New-DSM -graph $graph
$ret1 = Start-DSMClustering -Dsm $dsm1 -ClusteringAlgorithm Classic
$visual = Export-DSM -Result $ret1 -Format VEGA_JSON
По горизонтали зависимости вида “зависит от”, например appServicePlan: Resource, зависит от кучи всяких параметров. А по вертикли, на оборот “зависит от меня”, от того же appServicePlan: Resource зависят всякие outputs и другие ресурсы.
Ссылки
Репозиторий PSBicepGraph (dev). Там же README с установкой, примерами и скриншотами. Модуль PSGraph - экспорт, DSM, Vega.
P.S. Если вы когда-нибудь пытались объяснить сложный Bicep-проект через «смотри, тут var, тут module, а здесь output», то вы знаете, как это больно. Теперь вместо 30-минутного стендапа — одна картинка. И спорить можно уже по фактам, а не по интерпретациям.
Хочется ваш фидбек: issues/PR приветствуются.