Publishing VS Code extension via Azure DevOps

Viewed 898

After reading VSCode Publish Extension docs, I've succeeded to publish a VSCode extension manually with vsce.

I'm wondering if there is a way to publish extensions automatically via Azure DevOps pipelines (build or release) instead of doing it manually.

I've tried to use vsce there but I'm getting an authentication error

Resource not available for anonymous access. Client authentication required.

Using vsce publish -p <access_token> is not possible because the pipeline is public and everyone can see the access token...

So, is there a way to publish a Visual Studio Code extension automatically via Azure DevOps Pipeline or even Travis CI?

3 Answers

You can add the Personal Access Token as a secret variable, then nobody can couldn't see it.

Go to Azure DevOps to your pipeline and click on "Edit", not in the top left click on "Variables":

enter image description here

Now click on the + icon and add the variable, mark the checkbox "Keep this value secret":

enter image description here

Now you can use it in this way: $(PAT), for example:

vsce publish -p $(PAT)

The variable value will not appear in the YAML :)

Is there a way to publish a Visual Studio Code extension automatically via Azure DevOps Pipeline?

Of course yes!

To have a good experience for CI/CD in Azure Devops, I recommend you store the source code in Azure Devops or Github.

  • Build \ CI

In build, most of work is update the version which in manifest of VSIX, build\create package. For the version increased, here I use the counter expression feature which supported in VSTS to achieve that:

counter('name', seed)

Use this expression in variable declaration bloc. For detailed and completed build process, refer to my sample YAML code:

trigger:
- '*'

pool:
  vmImage: 'windows-2019'

variables:
  VersionPatch: $[counter('versioncount', 24)]
  solution: '**/*.sln'
  BuildPlatform: 'Any CPU'
  BuildConfiguration: 'Release'

name: 2.0.$(VersionPatch)

steps:
- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '3.0.100'
    includePreviewVersions: true

- task: NuGetToolInstaller@1
  inputs:
    versionSpec: 5.1.0

- task: PowerShell@2
  displayName: Update version
  inputs:
    filePath: 'Build\VersionUpdate.ps1'
    arguments: '$(Build.BuildNumber)'
    pwsh: true

- task: NuGetCommand@2
  inputs:
    command: 'restore'

- task: DotNetCoreCLI@2
  displayName: 
  inputs:
    command: 'restore'
    projects: 'tests/**/*.csproj'
    vstsFeed: '{My feed ID}'
    includeNuGetOrg: false

- task: VSBuild@1
  inputs:
    solution: '**\*.sln'
    maximumCpuCount: true
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'

- task: VSTest@2
  inputs:
    platform: '$(BuildPlatform)'
    configuration: '$(BuildConfiguration)'

- task: CopyFiles@2
  inputs:
    SourceFolder: '$(Build.SourcesDirectory)'
    Contents: |
      Build/**
      **/*.vsix
      **/*.nupkg
      README.md
    TargetFolder: '$(Build.ArtifactStagingDirectory)'

- task: PublishPipelineArtifact@0
  inputs:
    artifactName: 'ExtensionDrop'
    targetPath: '$(Build.ArtifactStagingDirectory)'

In UpdateVersion.ps1 file:

$VerbosePreference="Continue"
$version = $args[0]
if (!$version) {
    $version = "0.0.0"
}
Write-Host "This Version is: $version"
$FullPath = Resolve-Path $PSScriptRoot\..\src\Merlin.Compiler.Vsix\source.vsixmanifest
Write-Host $FullPath
[xml]$content = Get-Content $FullPath
$content.PackageManifest.Metadata.Identity.Version = $version
$content.Save($FullPath)
  • Release\ CD

After build succeed, set the release pipeline for this repos. In release, use powershell script and VsixPublisher.exe to publish the vsix file.

$PAToken = $args[0]
$VsixPath = "$PSScriptRoot\..\src\Merlin.Compiler.Vsix\bin\Release\Merlin.Compiler.Vsix"
$ManifestPath = "$PSScriptRoot\ExtensionManifest.json"
$Installation = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -prerelease -format json | ConvertFrom-Json
$Path = $Installation.installationPath
$VsixPublisher = Join-Path -Path $Path -ChildPath "VSSDK\VisualStudioIntegration\Tools\Bin\VsixPublisher.exe" -Resolve
& $VsixPublisher publish -payload $VsixPath -publishManifest $ManifestPath -personalAccessToken $PAToken -ignoreWarnings "VSIXValidatorWarning01,VSIXValidatorWarning02,VSIXValidatorWarning08"

In CD, use VsixPublisher.exe which exist in VS to publish the vsix file.


You can set the PAToken in Variable tab, then set it as secret. Thus it would not be public for others. Here PAT token is a necessary one which could not be replaced by others. And also, when generate the token, need choose All accessible organizations. Or it will cause the permission error.

enter image description here

Further @Shayki's answer there are some more steps because you can't just run vsce publish -p $(PAT).

  1. The vsce should be installed (can be in devDependencies)
  2. Add a "deploy" (or name it as you like) script to the package.json scripts.
"deploy": "vsce publish -p"
  1. Add a "publish" step in the azure-pipeline.yml file. the condition is for running the publish script only on master so Pull Requests will not publish. Also run it only in Linux's build, in case you configured multiple platforms. If you configured only one (for example, windows) replace Linux with that platform
- bash: |
   echo ">>> Publish"
   yarn deploy $(token)
 displayName: Publish
 condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['Agent.OS'], 'Linux'))

Example azure-pipeline.yml

Related