Edit

Share via


Tutorial: Set up a vcpkg binary cache using GitHub Packages in a GitHub Actions workflow

Note

This tutorial uses NuGet feeds hosted in GitHub Packages but the same instructions can be used for other NuGet feed providers, for example: Azure Artifacts, with minimal changes.

GitHub Packages offers a convenient repository for your NuGet binary packages produced by vcpkg. In this tutorial, we show you how to set up a binary cache in your GitHub Actions workflow that uses GitHub Packages as the remote storage.

In this tutorial, you'll learn how to:

Prerequisites

  • A code editor
  • A GitHub repository using GitHub Actions
  • A project using vcpkg

1 - Configure authentication for GitHub Packages

This tutorial uses the built-in GITHUB_TOKEN provided by GitHub Actions. To enable both read and write access to GitHub Packages, add the following permissions block to your workflow:

permissions:
  packages: write

This grants the GITHUB_TOKEN the necessary packages:write and packages:read permissions. Using GITHUB_TOKEN has several advantages:

  • No need to create or manage additional secrets
  • Works automatically for pull requests from forks (with read-only access)
  • Scoped to the specific repository and workflow run

Note

Alternatively, you can use a classic Personal Access Token (PAT) if you need cross-repository access or other advanced scenarios. Follow GitHub's instructions to generate a classic Personal Access Token (PAT) with packages:write and packages:read permissions, then add it as a secret in your repository and use ${{ secrets.YOUR_PAT_NAME }} instead of ${{ secrets.GITHUB_TOKEN }} in the examples below.

2 - Bootstrap vcpkg

vcpkg acquires its own copy of the nuget.exe executable that it uses during binary caching operations. This tutorial uses the vcpkg-acquired nuget.exe.

Add a step to bootstrap vcpkg in your workflow:

- name: Bootstrap vcpkg
  shell: pwsh
  run: ${{ github.workspace }}/vcpkg/bootstrap-vcpkg.bat
- name: Bootstrap vcpkg
  shell: bash
  run: ${{ github.workspace }}/vcpkg/bootstrap-vcpkg.sh

You may need to replace the location of the vcpkg bootstrap script with the correct one for your workflow, this tutorial assumes that vcpkg is located in a vcpkg folder in the root of the repository.

3 - Set up required environment variables

Add the following environment variables to your workflow file (replace <OWNER> with your GitHub's username or organization's name):

env: 
  USERNAME: <OWNER>
  VCPKG_EXE: ${{ github.workspace }}/vcpkg/vcpkg
  FEED_URL: https://nuget.pkg.github.com/<OWNER>/index.json
  VCPKG_BINARY_SOURCES: "clear;nuget,https://nuget.pkg.github.com/<OWNER>/index.json,readwrite"

You may need to replace the value of VCPKG_EXE with the location of the vcpkg executable generated in the bootstrap vcpkg step.

In this step you are configuring VCPKG_BINARY_SOURCES to use your GitHub Packages feed as a binary caching source, read the binary caching reference to learn more.

4 - Add GitHub Packages as a NuGet source

The vcpkg fetch nuget command outputs the location of the vcpkg-acquired nuget.exe, downloading the executable if necessary.

Add the following step to your workflow file to configure the NuGet source with your GITHUB_TOKEN:

permissions:
  packages: write

jobs:
  build:
    runs-on: windows-latest
    steps:
    # ... other steps ...
    - name: Add NuGet sources
      shell: pwsh
      run: |
        .$(${{ env.VCPKG_EXE }} fetch nuget) `
          sources add `
          -Source "${{ env.FEED_URL }}" `
          -StorePasswordInClearText `
          -Name GitHubPackages `
          -UserName "${{ env.USERNAME }}" `
          -Password "${{ secrets.GITHUB_TOKEN }}"
        .$(${{ env.VCPKG_EXE }} fetch nuget) `
          setapikey "${{ secrets.GITHUB_TOKEN }}" `
          -Source "${{ env.FEED_URL }}"

On Linux, you need mono to execute nuget.exe. You can install mono using your distribution's system package manager:

apt install mono-complete

Note that ubuntu-22.04 GitHub Actions runners come with mono preinstalled, but starting with ubuntu-24.04 (which ubuntu-latest currently points to), mono no longer comes preinstalled.

permissions:
  packages: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # ... other steps ...
    - name: Add NuGet sources
      shell: bash
      env: 
        VCPKG_EXE: ${{ github.workspace }}/vcpkg/vcpkg
        USERNAME: <OWNER>
        FEED_URL: https://nuget.pkg.github.com/<OWNER>/index.json
      run: |
        mono `${{ env.VCPKG_EXE }} fetch nuget | tail -n 1` \
          sources add \
          -Source "${{ env.FEED_URL }}" \
          -StorePasswordInClearText \
          -Name GitHubPackages \
          -UserName "${{ env.USERNAME }}" \
          -Password "${{ secrets.GITHUB_TOKEN }}"
        mono `${{ env.VCPKG_EXE }} fetch nuget | tail -n 1` \
          setapikey "${{ secrets.GITHUB_TOKEN }}" \
          -Source "${{ env.FEED_URL }}"

And that's it! vcpkg will now upload or restore packages from your NuGet feed hosted on GitHub Packages inside your GitHub Actions workflow.

Next steps

Here are other tasks to try next: