Skip to content
Merged
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
20aad2a
Refactor Azure DevOps release pipeline for BcContainerHelper deployment
mazhelez Dec 5, 2025
0d7c306
Update repository references in Release.yml for consistency
mazhelez Dec 5, 2025
2ce5535
Refactor Release.yml to streamline stages and job definitions for BcC…
mazhelez Dec 5, 2025
b390b03
Fix deployment stages to depend on 'Prepare' instead of 'Release'
mazhelez Dec 5, 2025
0ce0e8f
Update Release.yml to rename 'Prepare' stage to 'PrepareModule' and a…
mazhelez Dec 5, 2025
bd9874a
Update Release.yml to change template reference from 'Official' to 'N…
mazhelez Dec 5, 2025
ffbfb9c
Refactor Release.yml to simplify the PrepareModule job by removing un…
mazhelez Dec 5, 2025
726dce1
Disable Azure Storage upload task and update script to indicate confi…
mazhelez Dec 5, 2025
6fa66d6
Add WindowsContainerImage variable to Release.yml for improved config…
mazhelez Dec 5, 2025
716b8ff
Add feature flags for WindowsHostVersion in Release.yml
mazhelez Dec 5, 2025
a87e418
Update Release.yml to use Build.StagingDirectory and Build.SourcesDir…
mazhelez Dec 5, 2025
4988116
Add logging for file copying in PrepareModule job
mazhelez Dec 5, 2025
8ea39b0
Refine file copying logic in PrepareModule job to target specific dir…
mazhelez Dec 5, 2025
4a6470f
Update module path and error logging in PrepareModule job for improve…
mazhelez Dec 5, 2025
79d2f0c
Update signing task in Release.yml to use specific signing profile fo…
mazhelez Dec 5, 2025
6793043
Update signing profile in Release.yml for OSS components
mazhelez Dec 5, 2025
4fd1844
Update signing profile in Release.yml to use 'external_distribution' …
mazhelez Dec 7, 2025
0dd6ab7
Refactor WindowsHostVersion parameter in Release.yml for consistency
mazhelez Dec 8, 2025
4901088
Refactor signing task in Release.yml to use template for improved mai…
mazhelez Dec 8, 2025
9340e1b
Remove display name for signing task in Release.yml for clarity
mazhelez Dec 8, 2025
397ea69
Update output directory path in Release.yml for consistency in artifa…
mazhelez Dec 8, 2025
9ccc293
Update NavContainerHelper.md to replace hardcoded password with place…
mazhelez Dec 8, 2025
2903202
Update example in Renew-LetsEncryptCertificate.ps1 to use placeholder…
mazhelez Dec 8, 2025
23120fd
Add Credential Scanner suppressions configuration for security compli…
mazhelez Dec 8, 2025
22a6834
Add Credential Scanner suppressions configuration and update path in …
mazhelez Dec 9, 2025
e6d6bbd
Update Credential Scanner suppressions file path in Release.yml for a…
mazhelez Dec 9, 2025
9fd3c8f
Remove unnecessary line number from Credential Scanner suppressions f…
mazhelez Dec 9, 2025
8ccbae7
Remove redundant cleanup of .azuredevops directory in Release.yml
mazhelez Dec 9, 2025
f9e56df
Remove redundant path from output directory in Release.yml
mazhelez Dec 9, 2025
136d82a
Add enableGitCheckout parameter to pipeline configuration
mazhelez Dec 9, 2025
35185f8
Remove unnecessary checkout step from Release.yml
mazhelez Dec 9, 2025
08d522f
Remove enableGitCheckout parameter from pipeline configuration
mazhelez Dec 9, 2025
bf37850
Revert "Remove unnecessary checkout step from Release.yml"
mazhelez Dec 9, 2025
cd21a53
Update file path in Release.yml to use current directory for copying …
mazhelez Dec 9, 2025
3f59300
Remove unnecessary checkout step from Release.yml
mazhelez Dec 9, 2025
415bff6
Refactor Release.yml to standardize module naming and improve artifac…
mazhelez Dec 10, 2025
e6806b6
Update output path variable in Release.yml for file operations
mazhelez Dec 10, 2025
35e1e7d
Update output directory structure in Release.yml to include module su…
mazhelez Dec 10, 2025
a15ab35
Update OutputPath parameter in codesign template to use base output d…
mazhelez Dec 10, 2025
80b5c1f
Add MockRun parameter and update artifact handling in Release.yml
mazhelez Dec 10, 2025
096b2ea
Refactor Release.yml to conditionally include codesign templates base…
mazhelez Dec 10, 2025
e008222
Update Release.yml to conditionally include codesign templates based …
mazhelez Dec 10, 2025
134a582
Add variables for output directory and artifact base name in Publish …
mazhelez Dec 10, 2025
e250958
Remove unnecessary checkout steps in artifact download jobs
mazhelez Dec 10, 2025
e91b406
Refactor Release.yml to use a script for preparing BcContainerHelper …
mazhelez Dec 11, 2025
a2a1c84
Ensure output directory exists before zipping module and register def…
mazhelez Dec 11, 2025
e65f26a
Add ProductionRelease parameter to Release pipeline and update module…
mazhelez Dec 11, 2025
47afa29
Update release name format to include date and revision number
mazhelez Dec 11, 2025
a47a630
Update Release.yml to replace MockRun with TestRun parameter and adju…
mazhelez Dec 11, 2025
935b292
Update argument parsing for PrepareBCContainerHelperModule script in …
mazhelez Dec 11, 2025
319f192
Fix ProductionRelease parameter parsing in Release.yml
mazhelez Dec 11, 2025
1c93ade
Fix blob name assignment for Azure Storage upload based on Production…
mazhelez Dec 11, 2025
61221fd
Fix preview suffix formatting in PrepareBCContainerHelperModule script
mazhelez Dec 11, 2025
c27b191
Merge branch 'main' of https://github.com/microsoft/navcontainerhelpe…
mazhelez Dec 11, 2025
76b9a8e
Add dynamic naming for Release BCContainerHelper based on ProductionR…
mazhelez Dec 11, 2025
3c68319
Refactor Azure Storage container assignment logic based on TestRun pa…
mazhelez Dec 11, 2025
de370f7
Fix naming syntax for Release BCContainerHelper based on ProductionRe…
mazhelez Dec 11, 2025
ff035e4
Fix naming syntax for Release BCContainerHelper to correctly reflect …
mazhelez Dec 11, 2025
d5e9bda
Refactor Azure Storage container variable assignment based on TestRun…
mazhelez Dec 11, 2025
d222998
Refactor zip file creation process in Azure DevOps pipeline and add d…
mazhelez Dec 11, 2025
ac3e9e5
Refactor Azure Storage upload process by moving inline script to dedi…
mazhelez Dec 11, 2025
2615444
Refactor PowerShell Gallery publishing process by moving inline scrip…
mazhelez Dec 11, 2025
51e5db4
Refactor Release pipeline by removing TestRun parameter and simplifyi…
mazhelez Dec 12, 2025
0cda49a
Refactor CI workflow by updating event triggers and removing unused D…
mazhelez Dec 12, 2025
d6390e4
Refactor release name generation to differentiate between Production …
mazhelez Dec 12, 2025
e793c22
Refactor release name generation to remove conditional logic for Prod…
mazhelez Dec 12, 2025
3389304
Refactor Release pipeline by updating variable group and script argum…
mazhelez Dec 12, 2025
6ebe512
Do not trigger CI tests on PRs
mazhelez Dec 12, 2025
6bc3677
Update .azuredevops/scripts/PublishToPSGallery.ps1
mazhelez Dec 15, 2025
d82d9c8
Update .azuredevops/scripts/PrepareBCContainerHelperModule.ps1
mazhelez Dec 15, 2025
df3c4a1
Fix $fullVersion undefined for production releases (#4067)
Copilot Dec 15, 2025
7754393
Update .azuredevops/scripts/PrepareBCContainerHelperModule.ps1
mazhelez Dec 15, 2025
12b85cd
Add error handling for PSGallery repository registration (#4068)
Copilot Dec 15, 2025
f4c33b1
Standardize Author field to "Microsoft" across all module manifests (…
Copilot Dec 15, 2025
eed6d30
Update .azuredevops/pipelines/Release.yml
mazhelez Dec 15, 2025
48024bc
Change trigger from push to pull_request for CI workflow
mazhelez Dec 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .azuredevops/pipelines/CredScanSuppressions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tool": "Credential Scanner",
"suppressions": [
{
"file": "CreateScript.ps1",
"_justification": "This is a default example password parameter used in the wizard script, not a real credential"
}
]
}
237 changes: 115 additions & 122 deletions .azuredevops/pipelines/Release.yml
Original file line number Diff line number Diff line change
@@ -1,127 +1,120 @@
trigger: none

name: Release BCContainerHelper - $(Date:yyyy).$(Date:MM).$(Date:dd)-$(Rev:r)
pr: none

pool:
vmImage: 'windows-latest'
resources:
repositories:
- repository: onebranchTemplates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
- repository: PipelineTemplates
type: git
name: Infrastructure-PipelineTemplates
ref: master

variables:
- group: Release-Secrets # Create a variable group with: AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID, CodeSignCertificatePfx, CodeSignCertificatePassword, NugetKey

jobs:
- job: Deploy
displayName: 'Deploy BcContainerHelper'
condition: eq(variables['Build.Repository.Name'], 'Microsoft/NavContainerHelper')
steps:
- task: AzureCLI@2
displayName: 'Az CLI login'
inputs:
azureSubscription: 'BcContainerHelper-ServiceConnection' # Create a service connection with federated credentials
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
Write-Host "Authenticated with Azure"
addSpnToEnvironment: true
useGlobalConfig: true

- task: PowerShell@2
displayName: 'Install Azure PowerShell Modules'
inputs:
targetType: 'inline'
script: |
if(-not (Get-Module 'Az.Storage' -ListAvailable)) {
Install-Module -Name 'Az.Storage' -Force -AllowClobber
}
pwsh: false

- checkout: self
displayName: 'Checkout'

- task: PowerShell@2
displayName: 'Deploy'
inputs:
targetType: 'inline'
pwsh: false
script: |
$errorActionPreference = "stop"
try {
$path = Join-Path ([System.IO.Path]::GetTempPath()) "BcContainerHelper"
New-Item -path $path -itemType Directory | Out-Null
Copy-Item -path (Join-Path $ENV:BUILD_SOURCESDIRECTORY "*") -Destination $path -Recurse -Force
Remove-Item -Path (Join-Path $path "Tests") -Force -Recurse
Remove-Item -Path (Join-Path $path ".github") -Force -Recurse -ErrorAction Ignore
Remove-Item -Path (Join-Path $path ".azuredevops") -Force -Recurse -ErrorAction Ignore
Remove-Item -Path (Join-Path $path ".git") -Force -Recurse
Remove-Item -Path (Join-Path $path ".gitignore") -Force
Remove-Item -Path (Join-Path $path "README.md") -Force
$versionFile = Join-Path $path 'Version.txt'
$version = (Get-Content -Path $versionFile).split('-')[0]
Write-Host "BcContainerHelper version $Version"
Set-Content -Path $versionFile -Value $version
$modulePath = Join-Path $ENV:BUILD_SOURCESDIRECTORY "BcContainerHelper.psm1"
Import-Module $modulePath -DisableNameChecking
$functionsToExport = (get-module -Name BcContainerHelper).ExportedFunctions.Keys | Sort-Object
$aliasesToExport = (get-module -Name BcContainerHelper).ExportedAliases.Keys | Sort-Object
$labels = Get-BcContainerImageLabels -imageName 'mcr.microsoft.com/businesscentral:ltsc2022'
Write-Host "Set latest generic tag version to $($labels.tag)"
Set-Content -Path (Join-Path $path 'LatestGenericTagVersion.txt') -value $labels.tag
$releaseNotes = Get-Content -Path (Join-Path $path "ReleaseNotes.txt")
$idx = $releaseNotes.IndexOf($version)
if ($idx -lt 0) {
throw 'No release notes identified'
}
$versionReleaseNotes = @()
while ($releaseNotes[$idx]) {
$versionReleaseNotes += $releaseNotes[$idx]
$idx++
}
Write-Host "Release Notes:"
Write-Host $VersionReleaseNotes
Write-Host "Update Module Manifest"
Update-ModuleManifest -Path (Join-Path $path "BcContainerHelper.psd1") `
-RootModule "BcContainerHelper.psm1" `
-ModuleVersion $version `
-Author "Freddy Kristiansen" `
-FunctionsToExport $functionsToExport `
-AliasesToExport $aliasesToExport `
-CompanyName "Microsoft" `
-ReleaseNotes $versionReleaseNotes `
-LicenseUri 'https://github.com/microsoft/navcontainerhelper/blob/main/LICENSE' `
-ProjectUri 'https://github.com/microsoft/navcontainerhelper'
$certFileName = Join-Path ([System.IO.Path]::GetTempPath()) "$([GUID]::NewGuid().ToString()).pfx"
[System.IO.File]::WriteAllBytes($certFileName, ([Convert]::FromBase64String('$(CodeSignCertificatePfx)')))
Remove-Module BcContainerHelper
Write-Host $path
Write-Host "Signing scripts"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certFileName, '$(CodeSignCertificatePassword)')
$filesToSign = @((Get-ChildItem $path -Filter "*.ps1" -Recurse -Depth 99).FullName)+
@((Get-ChildItem $path -Filter "*.psm1" -Recurse -Depth 99).FullName)
Set-AuthenticodeSignature -Certificate $cert -HashAlgorithm SHA256 -TimestampServer "http://timestamp.digicert.com" -FilePath $filesToSign
Write-Host "Upload to storage (preview)"
$storageContext = New-AzStorageContext -StorageAccountName 'bccontainerhelper' -UseConnectedAccount
New-AzStorageContainer -Name 'public' -Context $storageContext -Permission 'Container' -ErrorAction Ignore | Out-Null
Compress-Archive -path $path -DestinationPath "$($path).zip"
Set-AzStorageBlobContent -File "$($path).zip" -Context $storageContext -Container 'public' -Blob "$version.zip" -Force | Out-Null
Set-AzStorageBlobContent -File "$($path).zip" -Context $storageContext -Container 'public' -Blob "latest.zip" -Properties @{"CacheControl" = "no-cache"} -Force | Out-Null
Write-Host "Publishing Module"
Publish-Module -Path $path -NuGetApiKey '$(NugetKey)' -SkipAutomaticTags
}
catch {
Write-Host "##vso[task.logissue type=error]Error publishing module. Error was $($_.Exception.Message)"
exit 1
}
- name: WindowsContainerImage
value: onebranch.azurecr.io/windows/ltsc2022/vse2022:latest
- template: codesign-variables.yml@PipelineTemplates
- group: Engineering Systems - BCContainerHelper

parameters:
- name: ProductionRelease
displayName: Production Release
type: boolean
default: false

extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates
parameters:
globalSdl: # https://aka.ms/obpipelines/sdl
credscan:
suppressionsFile: $(Build.SourcesDirectory)/.azuredevops/pipelines/CredScanSuppressions.json
featureFlags:
WindowsHostVersion: '1ESWindows2022'
stages:
- stage: PrepareModule
displayName: 'Prepare BcContainerHelper'
jobs:
- job: PrepareModule
displayName: 'Prepare BCContainerHelper Module'
pool:
type: 'windows'
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT/module'
- name: ob_artifactBaseName
value: BCContainerHelper_Module
steps:
- task: PowerShell@2
displayName: 'Prepare Module'
inputs:
targetType: 'filePath'
filePath: '$(Build.SourcesDirectory)/.azuredevops/scripts/PrepareBCContainerHelperModule.ps1'
arguments: "-OutputPath '$(ob_outputDirectory)' -ProductionRelease:([bool]::Parse('${{ parameters.ProductionRelease }}'))"
pwsh: false
- template: codesign.yml@PipelineTemplates
parameters:
OutputPath: '$(ob_outputDirectory)'

- stage: DeployToStorage
displayName: 'Deploy to Azure Storage'
dependsOn: ['PrepareModule']
jobs:
- job: UploadToStorage
displayName: 'Upload to Storage Account'
pool:
type: 'windows'
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT/zip'
- name: ob_artifactBaseName
value: BCContainerHelper_Zip
steps:
- download: current
artifact: BCContainerHelper_Module
displayName: 'Download BcContainerHelper Artifact'

- task: PowerShell@2
displayName: 'Create Zip File of Module'
inputs:
targetType: 'filePath'
filePath: '$(Build.SourcesDirectory)/.azuredevops/scripts/CreateZipFile.ps1'
arguments: "-ModulePath '$(Pipeline.Workspace)/BCContainerHelper_Module' -OutputDirectory '$(ob_outputDirectory)'"
pwsh: true

- task: AzureCLI@2
displayName: 'Upload to Azure Storage'
inputs:
azureSubscription: 'NAVDocker-PartnerArtifacts'
scriptType: 'pscore'
scriptLocation: 'scriptPath'
scriptPath: '$(Build.SourcesDirectory)/.azuredevops/scripts/UploadToAzureStorage.ps1'
arguments: "-StorageAccountName $(BCContainerHelperStorageAccount) -ContainerName '$(BCContainerHelperContainer)' -ZipPath '$(BCContainerHelperZipPath)' -Version '$(BCContainerHelperVersion)' -IsProductionRelease:([bool]::Parse('${{ parameters.ProductionRelease }}'))"

- stage: DeployToPSGallery
displayName: 'Deploy to PowerShell Gallery'
dependsOn: ['PrepareModule']
jobs:
- job: PublishToPSGallery
displayName: 'Publish to PowerShell Gallery'
pool:
type: 'windows'
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_artifactBaseName
value: BCContainerHelper_PSGallery
steps:
- download: current
artifact: BCContainerHelper_Module
displayName: 'Download BcContainerHelper Artifact'

- task: PowerShell@2
displayName: 'Publish to PowerShell Gallery'
inputs:
targetType: 'filePath'
filePath: '$(Build.SourcesDirectory)/.azuredevops/scripts/PublishToPSGallery.ps1'
arguments: "-ModulePath '$(Pipeline.Workspace)/BCContainerHelper_Module' -ApiKey '$(BCContainerHelperPSGalleryApiKey)'"
pwsh: true
43 changes: 43 additions & 0 deletions .azuredevops/scripts/CreateZipFile.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<#
.SYNOPSIS
Creates a versioned zip file of the BcContainerHelper module.

.DESCRIPTION
This script reads the version from the module's Version.txt file, creates a zip archive
of the module contents, and sets Azure DevOps pipeline variables for the zip path and version.

.PARAMETER ModulePath
The path to the BcContainerHelper module directory.

.PARAMETER OutputDirectory
The directory where the zip file will be created.

.OUTPUTS
Creates a zip file named "BcContainerHelper-{version}.zip" and sets pipeline variables:
- BCContainerHelperZipPath: Full path to the created zip file
- BCContainerHelperVersion: Version number from Version.txt
#>
param(
[Parameter(Mandatory=$true)]
[string]$ModulePath,

[Parameter(Mandatory=$true)]
[string]$OutputDirectory
)

$errorActionPreference = "Stop"

$versionFile = Join-Path $ModulePath 'Version.txt'
$version = Get-Content -Path $versionFile

# Create a zip file of the module
if(-not (Test-Path -Path $OutputDirectory)) {
New-Item -ItemType Directory -Path $OutputDirectory | Out-Null
}
$zipPath = Join-Path $OutputDirectory "BcContainerHelper-$version.zip"

Write-Host "Zipping module from $ModulePath to $zipPath"
Compress-Archive -Path "$ModulePath/*" -DestinationPath $zipPath -Force

Write-Host "##vso[task.setvariable variable=BCContainerHelperZipPath;isreadonly=true]$zipPath"
Write-Host "##vso[task.setvariable variable=BCContainerHelperVersion;isreadonly=true]$version"
Loading