From 25b9c23398280a3747c83e9bc28ae8f59c8570f5 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Mon, 11 Dec 2023 13:30:05 +0100 Subject: [PATCH] feat: Added 'Publish from tag' pipeline for AVM (#673) ## Description - Added 'Publish from tag' pipeline for AVM - Updated description of current publishing script | Pipeline | | - | | [Test-Run in fork](https://github.com/AlexanderSehr/bicep-registry-modules/actions/runs/6995186301/job/19029748855) | --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../templates/avm-publishModule/action.yml | 10 +-- .../workflows/avm.platform.publish-tag.yml | 64 ++++++++++++++++++ .../platform/Publish-ModuleFromTagToPBR.ps1 | 67 +++++++++++++++++++ .../publish/Publish-ModuleFromPathToPBR.ps1 | 23 ++++--- .../publish/Publish-ModuleFromTagToPBR.ps1 | 66 ------------------ 5 files changed, 148 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/avm.platform.publish-tag.yml create mode 100644 avm/utilities/pipelines/platform/Publish-ModuleFromTagToPBR.ps1 delete mode 100644 avm/utilities/pipelines/publish/Publish-ModuleFromTagToPBR.ps1 diff --git a/.github/actions/templates/avm-publishModule/action.yml b/.github/actions/templates/avm-publishModule/action.yml index a5c1ba60ac..498ed2c5d6 100644 --- a/.github/actions/templates/avm-publishModule/action.yml +++ b/.github/actions/templates/avm-publishModule/action.yml @@ -57,22 +57,16 @@ runs: # Load used functions . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'publish' 'Publish-ModuleFromPathToPBR.ps1') - ################################ - ## Get modules to publish ## - ################################ $functionInput = @{ TemplateFilePath = Join-Path $env:GITHUB_WORKSPACE "${{ inputs.templateFilePath }}" PublicRegistryServer = ConvertTo-SecureString '${{ env.PUBLISH_REGISTRY_SERVER }}' -AsPlainText -Force + RepoRoot = $env:GITHUB_WORKSPACE } Write-Verbose "Invoke function with" -Verbose Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose - # Get the modified child resources - if($publishOutputs = Publish-ModuleFromPathToPBR @functionInput -Verbose) { - Write-Output ('{0}={1}' -f 'version', $publishOutputs.version) >> $env:GITHUB_OUTPUT - Write-Output ('{0}={1}' -f 'publishedModuleName', $publishOutputs.publishedModuleName) >> $env:GITHUB_OUTPUT - } + Publish-ModuleFromPathToPBR @functionInput -Verbose Write-Output '::endgroup::' diff --git a/.github/workflows/avm.platform.publish-tag.yml b/.github/workflows/avm.platform.publish-tag.yml new file mode 100644 index 0000000000..e69f212dff --- /dev/null +++ b/.github/workflows/avm.platform.publish-tag.yml @@ -0,0 +1,64 @@ +name: "avm.platform.publish-tag" + +on: + workflow_dispatch: + inputs: + tag: + description: "The git tag of the module to publish. For example: [avm/res/key-vault/vault/1.0.0]" + required: true + type: string + +permissions: + id-token: write + contents: read + +jobs: + job_publish_module_with_tag: + runs-on: ubuntu-latest + name: "Publish module with tag" + steps: + - name: Checkout tag + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag }} + + - name: Log in to Azure + uses: azure/login@v1 + with: + client-id: ${{ env.PUBLISH_CLIENT_ID }} + tenant-id: ${{ env.PUBLISH_TENANT_ID }} + subscription-id: ${{ env.PUBLISH_SUBSCRIPTION_ID }} + + # Adding a step to explicitly install the latest Bicep CLI because there is + # always a delay in updating Bicep CLI in the job runner environments. + - name: Install the latest Bicep CLI + shell: bash + run: | + curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64 + chmod +x ./bicep + sudo mv ./bicep /usr/local/bin/bicep + bicep --version + + - name: "Publish tagged module to public bicep registry" + uses: azure/powershell@v1 + with: + azPSVersion: "latest" + inlineScript: | + # Grouping task logs + Write-Output '::group::Publish tagged module to public bicep registry' + + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'platform' 'Publish-ModuleFromTagToPBR.ps1') + + $functionInput = @{ + ModuleReleaseTagName = '${{ github.event.inputs.tag }}' + PublicRegistryServer = ConvertTo-SecureString '${{ secrets.PUBLISH_REGISTRY_SERVER }}' -AsPlainText -Force + RepoRoot = $env:GITHUB_WORKSPACE + } + + Write-Verbose 'Invoke function with' -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Publish-ModuleFromTagToPBR @functionInput -Verbose + + Write-Output '::endgroup::' diff --git a/avm/utilities/pipelines/platform/Publish-ModuleFromTagToPBR.ps1 b/avm/utilities/pipelines/platform/Publish-ModuleFromTagToPBR.ps1 new file mode 100644 index 0000000000..8ca1dd5b84 --- /dev/null +++ b/avm/utilities/pipelines/platform/Publish-ModuleFromTagToPBR.ps1 @@ -0,0 +1,67 @@ +<# +.SYNOPSIS +Publish a module based on the provided git tag + +.DESCRIPTION +Publish a module based on the provided git tag + +.PARAMETER ModuleReleaseTagName +Mandatory. The git tag to identify the module with & publish its code state of + +.PARAMETER PublicRegistryServer +Mandatory. The public registry server. + +.PARAMETER RepoRoot +Optional. Path to the root of the repository. + +.EXAMPLE +Publish-ModuleFromTagToPBR -ModuleReleaseTagName 'avm/res/key-vault/vault/0.3.0' -PublicRegistryServer (ConvertTo-SecureString 'myServer' -AsPlainText -Force) + +Publish the module 'avm/res/key-vault/vault' of git tag 'avm/res/key-vault/vault/0.3.0' to the public registry server 'myServer' +#> +function Publish-ModuleFromTagToPBR { + + [CmdletBinding(SupportsShouldProcess)] + param ( + [Parameter(Mandatory = $true)] + [string] $ModuleReleaseTagName, + + [Parameter(Mandatory = $true)] + [secureString] $PublicRegistryServer, + + [Parameter(Mandatory = $false)] + [string] $RepoRoot = (Get-Item -Path $PSScriptRoot).parent.parent.parent.parent.FullName + ) + + # Load used functions + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'publish' 'helper' 'Get-ModuleReadmeLink.ps1') + + # 1. Extract information from the tag + $targetVersion = Split-Path $ModuleReleaseTagName -Leaf + $moduleRelativeFolderPath = $ModuleReleaseTagName -replace "\/$targetVersion$", '' + $moduleFolderPath = Join-Path $repositoryRoot $moduleRelativeFolderPath + $moduleJsonFilePath = Join-Path $moduleFolderPath 'main.json' + Write-Verbose "Determined JSON template Path [$moduleJsonFilePath]" + + # 2. Get the documentation link + $documentationUri = Get-ModuleReadmeLink -TagName $ModuleReleaseTagName -ModuleFolderPath $moduleFolderPath + Write-Verbose "Determined documentation URI [$documentationUri]" + + ################### + ## 3. Publish ## + ################### + $plainPublicRegistryServer = ConvertFrom-SecureString $PublicRegistryServer -AsPlainText + + $publishInput = @( + $moduleJsonFilePath + '--target', ("br:{0}/public/bicep/{1}:{2}" -f $plainPublicRegistryServer, $moduleRelativeFolderPath, $targetVersion) + '--documentationUri', $documentationUri + '--force' + ) + + Write-Verbose "Publish Input:`n $($publishInput | ConvertTo-Json -Depth 10)" -Verbose + + if ($PSCmdlet.ShouldProcess("Module of tag [$ModuleReleaseTagName]", "Publish")) { + bicep publish @publishInput + } +} diff --git a/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 b/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 index 1cbbbf6d22..deb935a71d 100644 --- a/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 +++ b/avm/utilities/pipelines/publish/Publish-ModuleFromPathToPBR.ps1 @@ -15,9 +15,13 @@ Mandatory. The path to the deployment file .PARAMETER PublicRegistryServer Mandatory. The public registry server. +.PARAMETER RepoRoot +Optional. Path to the root of the repository. + .EXAMPLE -Publish-ModuleFromPathToPBR -TemplateFilePath 'C:\avm\res\key-vault\vault\main.bicep -PublicRegistryServer '' +Publish-ModuleFromPathToPBR -TemplateFilePath 'C:\avm\res\key-vault\vault\main.bicep -PublicRegistryServer (ConvertTo-SecureString 'myServer' -AsPlainText -Force) +Publish the module in path 'key-vault/vault' to the public registry server 'myServer' #> function Publish-ModuleFromPathToPBR { @@ -27,16 +31,19 @@ function Publish-ModuleFromPathToPBR { [string] $TemplateFilePath, [Parameter(Mandatory = $true)] - [secureString] $PublicRegistryServer + [secureString] $PublicRegistryServer, + + [Parameter(Mandatory = $false)] + [string] $RepoRoot = (Get-Item -Path $PSScriptRoot).parent.parent.parent.parent.FullName ) # Load used functions - . (Join-Path $PSScriptRoot 'helper' 'Get-ModulesToPublish.ps1') - . (Join-Path $PSScriptRoot 'helper' 'Get-ModuleTargetVersion.ps1') - . (Join-Path (Split-Path $PSScriptRoot) 'sharedScripts' 'Get-BRMRepositoryName.ps1') - . (Join-Path $PSScriptRoot 'helper' 'New-ModuleReleaseTag.ps1') - . (Join-Path $PSScriptRoot 'helper' 'Get-ModuleReadmeLink.ps1') - . (Join-Path (Split-Path $PSScriptRoot -Parent) 'sharedScripts' 'tokenReplacement' 'Convert-TokensInFileList.ps1') + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'publish' 'helper' 'Get-ModulesToPublish.ps1') + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'publish' 'helper' 'Get-ModuleTargetVersion.ps1') + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'publish' 'helper' 'New-ModuleReleaseTag.ps1') + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'publish' 'helper' 'Get-ModuleReadmeLink.ps1') + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'sharedScripts' 'Get-BRMRepositoryName.ps1') + . (Join-Path $RepoRoot 'avm' 'utilities' 'pipelines' 'sharedScripts' 'tokenReplacement' 'Convert-TokensInFileList.ps1') $moduleFolderPath = Split-Path $TemplateFilePath -Parent $moduleJsonFilePath = Join-Path $moduleFolderPath 'main.json' diff --git a/avm/utilities/pipelines/publish/Publish-ModuleFromTagToPBR.ps1 b/avm/utilities/pipelines/publish/Publish-ModuleFromTagToPBR.ps1 deleted file mode 100644 index 3c692f07c3..0000000000 --- a/avm/utilities/pipelines/publish/Publish-ModuleFromTagToPBR.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -function Publish-ModuleFromTagToPBR { - - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true)] - [string] $ModuleReleaseTagName, - - [Parameter(Mandatory = $true)] - [secureString] $PublicRegistryServer - ) - - # Load used functions - . (Join-Path (Split-Path $PSScriptRoot) 'sharedScripts' 'Get-BRMRepositoryName.ps1') - . (Join-Path $PSScriptRoot 'helper' 'Get-ModuleReadmeLink.ps1') - . (Join-Path (Split-Path $PSScriptRoot -Parent) 'sharedScripts' 'tokenReplacement' 'Convert-TokensInFileList.ps1') - - # TODO: Diff in between tag & tag^-1 to find modules to publish? - - # 1. Find tag as per function input - $repositoryRoot = (Get-Item $PSScriptRoot).Parent.Parent.Parent.Parent.Parent - $targetVersion = Split-Path $ModuleReleaseTagName -Leaf - $moduleRelativeFolderPath = $ModuleReleaseTagName -replace "\/$targetVersion$", '' - $moduleFolderPath = Join-Path $repositoryRoot $moduleRelativeFolderPath - $moduleJsonFilePath = Join-Path $moduleFolderPath 'main.json' - - - # 2. Get Target Published Module Name - $publishedModuleName = Get-BRMRepositoryName -TemplateFilePath $moduleJsonFilePath - - # 3. Get the documentation link - $documentationUri = Get-ModuleReadmeLink -TagName $ModuleReleaseTagName -ModuleRelativeFolderPath $moduleRelativeFolderPath - - # 4. Replace telemetry version value (in JSON) - $tokenConfiguration = @{ - FilePathList = @($moduleJsonFilePath) - AbsoluteTokens = @{ - '-..--..-' = $targetVersion - } - } - $null = Convert-TokensInFileList @tokenConfiguration - - # Double-check that tokens are correctly replaced - $templateContent = Get-Content -Path $moduleJsonFilePath - $incorrectLines = @() - for ($index = 0; $index -lt $templateContent.Count; $index++) { - if ($templateContent[$index] -match '-..--..-') { - $incorrectLines += ('You have the token [{0}] in line [{1}] of file [{2}]. Please seek advice from the AVM team.' -f $matches[0], ($index + 1), $moduleJsonFilePath) - } - } - if ($incorrectLines) { - throw ($incorrectLines | ConvertTo-Json) - } - - ################### - ## 5. Publish ## - ################### - $plainPublicRegistryServer = ConvertFrom-SecureString $PublicRegistryServer -AsPlainText - - $publishInput = @( - $moduleJsonFilePath - '--target', ("br:{0}/public/bicep/{1}:{2}" -f $plainPublicRegistryServer, $publishedModuleName, $targetVersion) - '--documentationUri', $documentationUri - '--force' - ) - # bicep publish @publishInput -}