diff --git a/azure-pipelines/README.md b/azure-pipelines/README.md index 73777d516d..ebfa711c7f 100644 --- a/azure-pipelines/README.md +++ b/azure-pipelines/README.md @@ -214,4 +214,28 @@ The extension release pipeline has the following parameters. - name: publishCommands type: object default: ['vsce publish --azure-credential --packagePath $(vsixFileName) --manifestPath extension.manifest --signaturePath extension.signature.p7s'] + +# The subdirectory within the build artifacts where the extension files are located. +# Leave empty (default) for extensions at the root level. +# Set to the subdirectory name (e.g., "helper") for extensions in subdirectories. +- name: artifactSubdirectory + type: string + default: "" ``` + +#### Using with extensions in subdirectories + +If your extension is located in a subdirectory (e.g., `helper/`) and the build artifacts preserve that directory structure, you need to specify the `artifactSubdirectory` parameter when calling the release template: + +```yaml +extends: + template: azure-pipelines/release-extension.yml@azExtTemplates + parameters: + publishVersion: ${{ parameters.publishVersion }} + dryRun: ${{ parameters.dryRun }} + artifactSubdirectory: "helper" # Specify the subdirectory name + environmentName: AzCodeDeploy + ExtensionReleaseServiceConnection: AzCodeReleases +``` + +This ensures the release pipeline looks for `package.json`, `.vsix` files, and signing artifacts in the correct subdirectory within the downloaded build artifacts. diff --git a/azure-pipelines/release-extension.yml b/azure-pipelines/release-extension.yml index a1b161e661..cde63ed9f5 100644 --- a/azure-pipelines/release-extension.yml +++ b/azure-pipelines/release-extension.yml @@ -27,7 +27,7 @@ parameters: type: boolean default: false - # A list of publish commands to run. It defaults to publishing a single .vsix file. If you want to publish multiple .vsix files (platform specifc), you can add mutliple commands to this list. + # A list of publish commands to run. It defaults to publishing a single .vsix file. If you want to publish multiple .vsix files (platform specific), you can add multiple commands to this list. - name: publishCommands type: object default: @@ -35,6 +35,13 @@ parameters: "vsce publish --azure-credential --packagePath $(vsixFileName) --manifestPath extension.manifest --signaturePath extension.signature.p7s", ] + # The subdirectory within the build artifacts where the extension files are located. + # Leave empty (default) for extensions at the root level. + # Set to the subdirectory name (e.g., "helper") for extensions in subdirectories. + - name: artifactSubdirectory + type: string + default: "" + # `resources` specifies the location of templates to pick up, use it to get 1ES templates resources: repositories: @@ -75,8 +82,17 @@ extends: # Modify the build number to include repo name, extension version, and if dry run is true - powershell: | # Get the version from package.json + $artifactSubdirectory = "$env:artifactSubdirectory" + $workingDirectory = "$(System.DefaultWorkingDirectory)" + + if ($artifactSubdirectory) { + $workingDirectory = Join-Path $workingDirectory $artifactSubdirectory + Write-Output "Using subdirectory: $artifactSubdirectory" + Write-Output "Working directory: $workingDirectory" + } - $packageJsonPath = "$(System.DefaultWorkingDirectory)/package.json" + $packageJsonPath = Join-Path $workingDirectory "package.json" + Write-Output "Looking for package.json at: $packageJsonPath" $npmVersionString = (Get-Content $packageJsonPath | ConvertFrom-Json).version $isDryRun = "$env:dryRun" $currentBuildNumber = "$(Build.BuildId)" @@ -96,12 +112,22 @@ extends: displayName: "\U0001F449 Prepend version from package.json to build number" env: dryRun: ${{ parameters.dryRun }} + artifactSubdirectory: ${{ parameters.artifactSubdirectory }} # For safety, verify the version in package.json matches the version to publish entered by the releaser # If they don't match, this step fails - powershell: | # Get the version from package.json - $packageJsonPath = "$(System.DefaultWorkingDirectory)/package.json" + $artifactSubdirectory = "$env:artifactSubdirectory" + $workingDirectory = "$(System.DefaultWorkingDirectory)" + + if ($artifactSubdirectory) { + $workingDirectory = Join-Path $workingDirectory $artifactSubdirectory + Write-Output "Using subdirectory: $artifactSubdirectory" + } + + $packageJsonPath = Join-Path $workingDirectory "package.json" + Write-Output "Looking for package.json at: $packageJsonPath" $npmVersionString = (Get-Content $packageJsonPath | ConvertFrom-Json).version $publishVersion = "$env:publishVersion" Write-Output "Publishing version: $publishVersion" @@ -115,24 +141,42 @@ extends: displayName: "\U0001F449 Verify publish version" env: publishVersion: ${{ parameters.publishVersion }} + artifactSubdirectory: ${{ parameters.artifactSubdirectory }} # Find the vsix to release and set the vsix file name variable # Fails with an error if more than one .vsix file is found, or if no .vsix file is found - powershell: | # Get all .vsix files in the current directory - $vsixFiles = Get-ChildItem -Path $(System.DefaultWorkingDirectory) -Filter *.vsix -File + $artifactSubdirectory = "$env:artifactSubdirectory" + $workingDirectory = "$(System.DefaultWorkingDirectory)" + + if ($artifactSubdirectory) { + $workingDirectory = Join-Path $workingDirectory $artifactSubdirectory + Write-Output "Using subdirectory: $artifactSubdirectory" + } + + Write-Output "Looking for .vsix files in: $workingDirectory" + $vsixFiles = Get-ChildItem -Path $workingDirectory -Filter *.vsix -File # Check if no .vsix file is found if ($vsixFiles.Count -eq 0) { - Write-Error "No .vsix files found." + Write-Error "No .vsix files found in $workingDirectory" + exit 1 + } elseif ($vsixFiles.Count -gt 1) { + Write-Error "Multiple .vsix files found in $workingDirectory. Expected exactly one." + foreach ($file in $vsixFiles) { + Write-Output " - $($file.Name)" + } exit 1 } else { - # Set the pipeline variable - $vsixFileName = $vsixFiles.Name + # Set the pipeline variable with the full path + $vsixFileName = ($vsixFiles | Select-Object -First 1).FullName Write-Output "##vso[task.setvariable variable=vsixFileName;]$vsixFileName" Write-Output "Found .vsix file: $vsixFileName" } displayName: "\U0001F449 Find and Set .vsix File Variable" + env: + artifactSubdirectory: ${{ parameters.artifactSubdirectory }} - task: UseNode@1 inputs: @@ -142,6 +186,23 @@ extends: - script: npm i -g @vscode/vsce displayName: "\U0001F449 Install vsce" + # Set the working directory for vsce publish + - powershell: | + $artifactSubdirectory = "$env:artifactSubdirectory" + $workingDirectory = "$(System.DefaultWorkingDirectory)" + + if ($artifactSubdirectory) { + $workingDirectory = Join-Path $workingDirectory $artifactSubdirectory + Write-Output "Setting working directory for vsce publish: $workingDirectory" + } else { + Write-Output "Using default working directory: $workingDirectory" + } + + Write-Output "##vso[task.setvariable variable=vsceWorkingDirectory;]$workingDirectory" + displayName: "\U0001F449 Set vsce working directory" + env: + artifactSubdirectory: ${{ parameters.artifactSubdirectory }} + - ${{ each publishCommand in parameters.publishCommands }}: # log the publishCommand - powershell: | @@ -154,4 +215,5 @@ extends: azureSubscription: ${{ parameters.ExtensionReleaseServiceConnection }} scriptType: pscore scriptLocation: inlineScript + workingDirectory: $(vsceWorkingDirectory) inlineScript: ${{ publishCommand }}