Blog Banner

Part 5: Using a Bicep Container Registry

(Part 5 in a 10-part series)

Referencing a Bicep module in a registry is almost exactly the same as referencing a Bicep file in your repo – you just change the name format slightly, like the following example. The trick is getting the “br/mybicepmodules:” defined, which is shown in the next step.


Referencing a Bicep Container Registry

In the previous example, the module names were preceded by a “br/mybicepmodules:” tag. That tag is defined in a bicepconfig.json file which is located alongside your main.bicep file in your project. You can make the “mybicepmodules” reference on line 11 to be whatever you want it to be. I’d recommend keeping it fairly generic so you can easily change your bicepconfig.json file later without having to refactor all of your main.bicep files.

In your pipelines, you may also have to include an “az login” to get a access to your registry, like this, and the user that is logging in will need at least “acr pull” rights:


Creating Your Own Bicep Registry

You can create your own registry using this bicep template:

Once the registry is created, create an Azure DevOps Pipeline that is fired whenever you check in a Bicep file into your repo. In that pipeline execute the following script, which will scan your repo for new or updated Bicep files, add them to the registry with a date stamp, and also create a “LATEST” version of each file that was updated.

# az acr login -n $(registryName)
$moduleCount = 0
$modulesAdded = 0
$modulesUpdated = 0
$version = (Get-Date -f 'yyyy-MM-dd') + ".$env:BUILD_BUILDID"
Write-Host "Publishing new and updated modules as version $version"
Write-Host $modulePrefix
Write-Host "Updating Registry: $(registryName)"
Write-Host "Scanning for modulePrefix: $(modulePrefix)"
Write-Host "-------------------------------------------------------------"
Write-Host "List of modules currently in the registry:"
Write-Host "az acr repository list --name $(registryName) --query ''[?contains(@, '${modulePrefix}')]'' -o tsv"
az acr repository list --name $(registryName) --query "[?contains(@, '${modulePrefix}')]" -o tsv
Write-Host "-------------------------------------------------------------"
Write-Host "Searching for new modules to add..."
$publishedModules = $(az acr repository list --name $(registryName) --query "[?contains(@, '${modulePrefix}')]" -o tsv)
Get-ChildItem -Recurse -Path ./Bicep/*.bicep | Foreach-Object {
  $moduleCount += 1
  $filename = ($_ | Resolve-Path -Relative) -replace "^./" -replace '\..*'
  $lowerfilename = $filename.ToLower().replace("bicep/", "").replace("Bicep/", "").replace("modules/", "")
  Write-Host "-- Checking for existing registry entry: $lowerfileName"
  If (-not ($publishedModules ?? @()).Contains(("bicep/" + $lowerfilename))) {
    $image = "bicep/$lowerfilename`:$version"
    Write-Host "  *** $lowerfilename doesn't exist - adding Image $image"
    $modulesAdded += 1
    Write-Host "    az bicep publish --file $_ --target br:$(registryName).azurecr.io/bicep/${lowerfilename}:${version}"
    az bicep publish --file $_ --target br:$(registryName).azurecr.io/bicep/${lowerfilename}:${version}
    Write-Host "    az acr import --name $(registryName) --source $(registryName).azurecr.io/bicep/${lowerfilename}:${version} --image bicep/${lowerfilename}:LATEST --force"
    az acr import --name $(registryName) --source $(registryName).azurecr.io/bicep/${lowerfilename}:${version} --image bicep/${lowerfilename}:LATEST --force
    Write-Host "    Marking module $image as read-only"
    Write-Host "    az acr repository update --name $(registryName) --image $image --write-enabled false"
    az acr repository update --name $(registryName) --image $image --write-enabled false
  }
}

Write-Host "-------------------------------------------------------------"
Write-Host "Searching for existing modules to update..."
git diff-tree --no-commit-id --name-only --diff-filter=ad -r -m $(Build.SourceVersion) | Where-Object {$_.EndsWith('.bicep')} | Foreach-Object {
  $moduleName = ($_ | Resolve-Path -Relative) -replace "^./" -replace '\..*'
  If (-not ($moduleName ?? @()).Contains(('main.bicep'))) {
    $lowerfilename = $moduleName.ToLower().replace("bicep/", "").replace("modules/", "")
    Write-Host "  *** Updating existing module $lowerfilename with version $version"
    $modulesUpdated += 1
    Write-Host "    az bicep publish --file $_ --target br:$(registryName).azurecr.io/bicep/${lowerfilename}:${version}"
    az bicep publish --file $_ --target br:$(registryName).azurecr.io/bicep/${lowerfilename}:${version}
    Write-Host "    az acr import --name $(registryName) --source $(registryName).azurecr.io/bicep/${lowerfilename}:${version} --image bicep/${lowerfilename}:LATEST --force"
    az acr import --name $(registryName) --source $(registryName).azurecr.io/bicep/${lowerfilename}:${version} --image bicep/${lowerfilename}:LATEST --force
    Write-Host "    Marking module ${lowerfilename}:${version} as read-only"
    Write-Host "    az acr repository update --name $(registryName) --image bicep/${lowerfilename}:${version} --write-enabled false"
    az acr repository update --name $(registryName) --image bicep/${lowerfilename}:${version} --write-enabled false
  }
}
Write-Host "-------------------------------------------------------------"
Write-Host "Total Modules in repository:   $moduleCount" 
Write-Host "  Modules added to registry:   $modulesAdded"
Write-Host "  Modules updated in registry: $modulesUpdated"

And there you go — with that script in a pipeline, each time you update a Bicep file in your repository, your Bicep Container Registry will be updated, and you will be able to reference the registry in your projects and get the LATEST and greatest version of your Bicep files.


Next step: Azure DevOps Pipeline Layers


References

Microsoft Learn: Creating a Private Bicep Repository

Lyle’s Sample Code for publishing to a Bicep Container Repository


Posted

in

, , ,

by

Tags:

%d bloggers like this: