Search code examples
githubnugetpull-requestazure-artifactsgithub-package-registry

How to Securely Publish to NuGet from PR's In Azure Artifacts


I'm using the following yaml in my GitHub repository to publish NuGet packages to Azure Artifacts and GitHub packages on each commit and to the official NuGet repository when I use a Git Tag.

- stage: Deploy
  jobs:
  - deployment: AzureArtefacts
    displayName: 'Azure Artefacts'
    pool:
      vmImage: windows-latest
    environment: 'Azure Artefacts'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: NuGetToolInstaller@1
            displayName: 'NuGet Install'
          - task: NuGetAuthenticate@0
            displayName: 'NuGet Authenticate'
          - script: nuget push $(Agent.BuildDirectory)\Windows\*.nupkg -Source https://pkgs.dev.azure.com/serilog-exceptions/_packaging/serilog-exceptions/nuget/v3/index.json -ApiKey AzureArtifacts -SkipDuplicate
            displayName: 'NuGet Push'
            failOnStderr: true
  - deployment: GitHub
    pool:
      vmImage: windows-latest
    environment: 'GitHub'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: NuGetToolInstaller@1
            displayName: 'NuGet Install'
          - script: nuget source Add -Name GitHub -Source https://nuget.pkg.github.com/RehanSaeed/index.json -UserName $(GitHubUserName) -Password $(GitHubPersonalAccessToken)
            displayName: 'NuGet Add Source'
            failOnStderr: true
          - script: nuget push $(Agent.BuildDirectory)\Windows\*.nupkg -Source GitHub -SkipDuplicate
            displayName: 'NuGet Push'
            failOnStderr: true
  - deployment: NuGet
    pool:
      vmImage: windows-latest
    environment: 'NuGet'
    condition: startsWith(variables['Build.sourceBranch'], 'refs/tags/')
    strategy:
      runOnce:
        deploy:
          steps:
          - task: NuGetToolInstaller@1
            displayName: 'Install NuGet'
          - script: nuget push $(Agent.BuildDirectory)\Windows\*.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey $(NuGetApiKey) -SkipDuplicate
            displayName: 'NuGet Push'
            failOnStderr: true

This works fine when I checkin but when someone creates a PR, the above publish steps fail because:

  • Azure Artifacts - The user does not have permissions.
  • GitHub - The user does not have access to use the secret variables GitHubUserName and GitHubPersonalAccessToken.
  • NuGet - The build is not running from a Git tag so this step does not run.

Is it possible to safely run the Azure Artifacts and GitHub publish steps from PR's? In particular, I don't want someone changing the azure-pipelines.yml or my Cake build build.cake file to steal my secret variables or publish their own packages.

If this is not possible, I guess I have to skip these steps from PR's. How can I do this?


Solution

  • If this is not possible?

    I am afraid this is impossible to do that. Since the user do not have the permissions, the secret variables GitHubUserName and GitHubPersonalAccessToken. This is the key to this issue and cannot be circumvented, if you don't want to leak your secret variables.

    I guess I have to skip these steps from PR's. How can I do this?

    The answer is yes.

    You could use the expression evaluates the built-in variable Build.Reason to determine if the task is executing the build as part of a pull request branch policy, like:

    condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
    

    Then those task will be skip when the build is triggered by the PullRequest.

    Check the document Conditions for some more details.

    Hope this helps.