Quickstart: Use GitHub Actions to push to Azure Artifacts

Azure DevOps Services

Get started using GitHub Actions and Azure Artifacts together. GitHub Actions help you automate your software development workflows from within GitHub. You can use GitHub Actions to deploy to an Azure Artifacts feed.

Prerequisites

Note

An alternative approach is to use an Microsoft Entra application with a service principal and federated authentication credential to connect Azure DevOps and GitHub Actions. To learn more about this approach, see Configure an app to trust an external identity provider.

Assign permissions to your managed identity in Azure DevOps

To assign your managed identity to the Contributor team, follow these steps:

  1. Sign in to your project (https://dev.azure.com/{Your_Organization/Your_Project}).

  2. Go to Project settings.

  3. Select General > Permissions.

  4. Choose the Contributors group.

    Screenshot of contributors group permission option.

  5. Select the Members tab and then select Add.

  6. Search and find the managed identity.

  7. Select Save to add the identity to the Contributors group.

    Screenshot of adding a managed identity.

Create GitHub secrets

You need to provide your managed identity's Client ID, Tenant ID, and Subscription ID to the login action. These values are stored in GitHub secrets and referenced in your workflow.

  1. In GitHub, go to your repository.

  2. Go to Settings in the navigation menu.

  3. Select Security > Secrets and variables > Actions.

    Screenshot of adding a secret

  4. Select New repository secret.

  5. Create secrets for AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_SUBSCRIPTION_ID. Use these values from your managed identity for your GitHub secrets:

    GitHub secret Microsoft Entra application
    AZURE_CLIENT_ID Application (client) ID
    AZURE_TENANT_ID Directory (tenant) ID
    AZURE_SUBSCRIPTION_ID Subscription ID
  6. Save each secret by selecting Add secret.

Create a GitHub workflow that builds an artifact

GitHub workflows are a series of actions (like tasks in Azure Pipelines). This workflow automates the process of building, testing, packaging, and publishing a .NET project to Azure Artifacts using a managed identity and federated authentication. The workflow:

  1. Uses the azure/login action to log in to Azure using a managed identity.
  2. Installs the credential provider for Azure Artifacts.
  3. Extracts an access token using Azure CLI and configures the authentication provider to use the Azure DevOps token.
  4. Sets up a .NET Core CLI environment with the setup-dotnet action.
  5. Restores dependencies, builds the project and its dependencies into a set of binaries, and runs all unit tests associated with the project.
  6. Packs the code into a NuGet package with the GitHub Run ID environmental variable included in the version number.
  7. Publishes the NuGet package to Azure Artifacts.

Create a new YAML file

  1. In your repository on GitHub, create a new YAML file in the .github/workflows directory.

  2. Copy the following contents into your YAML file. Customize the AZURE_ARTIFACTS_FEED_URL, BUILD_CONFIGURATION, and DOTNET_VERSION values.

    • Set AZURE_ARTIFACTS_FEED_URL to the registry url for your Azure Artifacts Feed.
    • Set the BUILD_CONFIGURATION.
    • Set DOTNET_VERSION to the version of your project.
    name: Push a NuGet package to Azure Artifacts with managed identity and federated authentication
    
    on:
      push:
        branches:
          - main
    
    permissions:
      id-token: write # Require write permission to Fetch an federated identity token.
      contents: read # Require read permission to access the repository contents.
    
    env:
      AZURE_ARTIFACTS_FEED_URL: https://pkgs.dev.azure.com/myorg/nuget-artifact/_packaging/Fabrikam_Feed/nuget/v3/index.json    
      BUILD_CONFIGURATION: 'Release'    # set this to the appropriate build configuration
      DOTNET_VERSION: '6.0' 
      NuGetDirectory: ${{ github.workspace}}/nuget
      VSS_NUGET_URI_PREFIXES: https://pkgs.dev.azure.com/myorg/
    
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          # Checkout the repo
          - uses: actions/checkout@v4
            with:
              token: ${{ secrets.GITHUB_TOKEN }}
    
          - name: Azure CLI Login
            uses: azure/login@v2
            with:
              client-id: ${{ secrets.AZURE_CLIENT_ID }}
              tenant-id: ${{ secrets.AZURE_TENANT_ID }}
              subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    
          # Setup .NET Core SDK
          - name: Setup .NET Core
            uses: actions/setup-dotnet@v3
            with:
              dotnet-version: ${{ env.DOTNET_VERSION }}
    
          # Run dotnet build and package
          - name: dotnet build and test
            run: |
              dotnet restore
              dotnet build --configuration '${{ env.BUILD_CONFIGURATION }}'
              dotnet test --configuration '${{ env.BUILD_CONFIGURATION }}'
    
        # Create the NuGet package in the folder from the environment variable NuGetDirectory
          - run: dotnet pack --configuration Release --output ${{ env.NuGetDirectory }}
    
        # Publish the NuGet package as an artifact, so they can be used in the following jobs
          - uses: actions/upload-artifact@v3
            with:
              name: nuget
              if-no-files-found: error
              retention-days: 7
              path: ${{ env.NuGetDirectory }}/*.nupkg
    
      az-artifacts-build-and-deploy:
        needs: build
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
            with:
              token: ${{ secrets.GITHUB_TOKEN }}
    
          - name: Azure CLI Login
            uses: azure/login@v2
            with:
              client-id: ${{ secrets.AZURE_CLIENT_ID }}
              tenant-id: ${{ secrets.AZURE_TENANT_ID }}
              subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    
          - uses: actions/download-artifact@v3
            with:
              name: nuget
              path: ${{ env.NuGetDirectory }}
    
          - name: Setup .NET Core
            uses: actions/setup-dotnet@v3
            with:
              dotnet-version: ${{ env.DOTNET_VERSION }}
              source-url: ${{ env.AZURE_ARTIFACTS_FEED_URL }}
            env:
              NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
    
          - name: Install credential provider for Azure Artifacts
            run: sh -c "$(curl -fsSL https://aka.ms/install-artifacts-credprovider.sh)"
    
          - name: Extract access token
            run: |
                accessToken=$(az account get-access-token --query accessToken --resource 499b84ac-1321-427f-aa17-267ca6975798 -o tsv)
                echo "::add-mask::$accessToken"
                echo "ACCESS_TOKEN=$accessToken" >> $GITHUB_ENV
    
          - name: Configure authentication provider to use Azure DevOps token
            run: |
              echo "VSS_NUGET_ACCESSTOKEN=$ACCESS_TOKEN" >> $GITHUB_ENV
    
          - name: dotnet build and publish
            run: |
              dotnet restore
              dotnet build --configuration '${{ env.BUILD_CONFIGURATION }}'
              dotnet pack --configuration '${{ env.BUILD_CONFIGURATION }}' --output ./nupkg --version-suffix ${{ github.run_id }}
    
          - name: 'Publish the package to Azure Artifacts'
            run: dotnet nuget push ${{ env.NuGetDirectory }}/*.nupkg --api-key AzureDevOps --source ${{ env.AZURE_ARTIFACTS_FEED_URL }}    
    

Prerequisites

Authenticate with Azure Pipelines

Use a personal access token (PAT) to connect your GitHub account to Azure DevOps. You can generate a PAT from within Azure DevOps and then store it as a GitHub secret. Within your GitHub workflow, reference the secret so that your GitHub action can authenticate with your Azure DevOps project.

  1. Open your GitHub repository and go to Settings.

  2. Select Security > Secrets and variables > Actions.

    Choose to add a secret

  3. Paste in your PAT and give it the name AZURE_DEVOPS_TOKEN.

  4. Select Add secret.

Create a GitHub workflow that builds an artifact

GitHub workflows are a series of actions (like tasks in Azure Pipelines). This workflow:

  1. Sets up a .NET Core CLI environment with the setup-dotnet action.
  2. Restores dependencies, builds the project and its dependencies into a set of binaries, and runs all unit tests associated with the project.
  3. Packs the code into a NuGet package with the GitHub Run ID environmental variable included in the version number.
  4. Publishes the NuGet package to Azure Artifacts.

Create a new YAML file

  1. In your repository on GitHub, create a new YAML file in the .github/workflows directory.

  2. Copy the following contents into your YAML file. Customize the AZURE_ARTIFACTS_FEED_URL, BUILD_CONFIGURATION, and DOTNET_VERSION values.

    • Set AZURE_ARTIFACTS_FEED_URL to the registry url for your Azure Artifacts Feed.
    • Set the BUILD_CONFIGURATION.
    • Set DOTNET_VERSION to the version of your project.
    name: Push a NuGet package to Azure Artifacts
    
    on:
      push:
        branches:
          - main
    
    env:
      AZURE_ARTIFACTS_FEED_URL: https://pkgs.dev.azure.com/myorg/nuget-artifact/_packaging/Fabrikam_Feed/nuget/v3/index.json    
      BUILD_CONFIGURATION: 'Release'    # set this to the appropriate build configuration
      DOTNET_VERSION: '6.x' 
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          # Checkout the repo
          - uses: actions/checkout@v2
    
          # Setup .NET Core SDK
          - name: Setup .NET Core
            uses: actions/setup-dotnet@v1
            with:
              dotnet-version: ${{ env.DOTNET_VERSION }}
    
          # Run dotnet build and package
          - name: dotnet build and test
            run: |
              dotnet restore
              dotnet build --configuration '${{ env.BUILD_CONFIGURATION }}'
              dotnet test --configuration '${{ env.BUILD_CONFIGURATION }}'
    
      az-artifacts-build-and-deploy:
        needs: build
        runs-on: ubuntu-latest
        steps:
          # Checkout the repo
          - uses: actions/checkout@v2
    
          # Setup .NET Core SDK
          - name: Setup .NET Core
            uses: actions/setup-dotnet@v1
            with:
              dotnet-version: ${{ env.DOTNET_VERSION }}
              source-url: ${{ env.AZURE_ARTIFACTS_FEED_URL }}
            env:
              NUGET_AUTH_TOKEN: ${{ secrets.AZURE_DEVOPS_TOKEN }} 
    
          # Run dotnet build and package
          - name: dotnet build and publish
            run: |
              dotnet restore
              dotnet build --configuration '${{ env.BUILD_CONFIGURATION }}'
              dotnet pack -c '${{ env.BUILD_CONFIGURATION }}' --version-suffix $GITHUB_RUN_ID
    
          # Publish the package to Azure Artifacts
          - name: 'dotnet publish'
            run: dotnet nuget push --api-key AzureArtifacts bin/Release/*.nupkg 
    
  3. Go to your Azure Artifacts feed to verify that you see the package you pushed.

    Screenshot of review for new Azure Artifacts feed.

Clean up resources

If you're not going to continue to use your GitHub workflow, disable the workflow.

Next steps