Skip to content

Commit

Permalink
run-vcpkg@v11: leverage BinaryCaching with GH Action's cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
lukka committed Mar 27, 2023
1 parent 12bbe97 commit 549a9ea
Show file tree
Hide file tree
Showing 14 changed files with 5,607 additions and 3,321 deletions.
13 changes: 6 additions & 7 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,16 @@ jobs:
uses: ./
with:
vcpkgDirectory: ${{ github.workspace }}/vcpkg
vcpkgGitCommitId: '14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44'
vcpkgGitCommitId: '02b6fe4f9e8c97afceddd0d2e3802cf469882a4e'
vcpkgGitUrl: 'https://github.com/lukka/vcpkg.git'

- name: basic test for run-vcpkg with running 'vcpkg install'.
uses: ./
with:
vcpkgDirectory: ${{ github.workspace }}/vcpkg
vcpkgGitCommitId: '14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44'
vcpkgGitCommitId: '02b6fe4f9e8c97afceddd0d2e3802cf469882a4e'
runVcpkgInstall: true
# This forces the creation of a new cache entry each time the workflow is run.
# It is the same across jobs in the same workflows.
prependedCacheKey: ${{ env.GITHUB_RUN_ID }}
vcpkgGitUrl: 'https://github.com/lukka/vcpkg.git'
env:
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/vcpkg_installed

Expand All @@ -91,8 +90,8 @@ jobs:
uses: ./
with:
vcpkgDirectory: ${{ github.workspace }}/vcpkg
vcpkgGitCommitId: '14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44'
prependedCacheKey: ${{ env.GITHUB_RUN_ID }}
vcpkgGitCommitId: '02b6fe4f9e8c97afceddd0d2e3802cf469882a4e'
vcpkgGitUrl: 'https://github.com/lukka/vcpkg.git'

finalize_coveralls:
needs: build_and_unit_test
Expand Down
103 changes: 43 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Coverage Status](https://coveralls.io/repos/github/lukka/run-vcpkg/badge.svg?branch=main)](https://coveralls.io/github/lukka/run-vcpkg?branch=main)

- [Quickstart with a C++ project template](#quickstart-with-a-c-project-template)
- [The **run-vcpkg@v10** action for caching artifacts and using vcpkg with manifest files on GitHub workflows](#the-run-vcpkgv10-action-for-caching-artifacts-and-using-vcpkg-with-manifest-files-on-github-workflows)
- [The **run-vcpkg@v11** action for caching artifacts and using vcpkg with manifest files on GitHub workflows](#the-run-vcpkgv11-action-for-caching-artifacts-and-using-vcpkg-with-manifest-files-on-github-workflows)
- [Quickstart with instructions](#quickstart-with-instructions)
- [Action reference: all input/output parameters](#action-reference-all-inputoutput-parameters)
- [Flowchart](#flowchart)
Expand All @@ -20,13 +20,13 @@

Take a look at this [C++ project template](https://github.com/lukka/CppCMakeVcpkgTemplate) that applies all the following instructions, but also shows how to create a __pure__ workflow without using special GitHub action that you cannot run locally on your development machine, but directly using the tools (`CMake`, `Ninja`, `vcpkg`, `C++` compilers) you already use daily.

# [The **run-vcpkg@v10** action for caching artifacts and using vcpkg with manifest files on GitHub workflows](https://github.com/marketplace/actions/run-vcpkg)
# [The **run-vcpkg@v11** action for caching artifacts and using vcpkg with manifest files on GitHub workflows](https://github.com/marketplace/actions/run-vcpkg)

The **run-vcpkg** action restores from cache [vcpkg](https://github.com/microsoft/vcpkg) along with the previously installed packages, and then setup vcpkg to be run in a subsequent step. Or it runs it for you.
The **run-vcpkg** action runs [vcpkg](https://github.com/microsoft/vcpkg) to install the packages specified
in the vcpkg.json manifest file.

Special features which provide added value over a pure workflow are:
- automatic cache management of vcpkg's artifacts by computing a cache key based (among others) on content of `vcpkg.json`.
- automatic computation of the set of keys (primary key and secondary keys) used maximize the reuse of existing cached vcpkg's artifacts.
- drive `vcpkg` to use its [Binary Caching feature](https://learn.microsoft.com/en-us/vcpkg/users/binarycaching) and to store/restore the built packages with the GitHub Action cache so that they are built only once and reused in subsequent workflow runs.
- automatic dump of log files created by `CMake` (e.g., `CMakeOutput.log`) and `vcpkg`. The content of those files flow into the workflow output log. Customizable by the user.
- automatic parsing of `CMake`, `vcpkg` and `gcc`, `clang`, `msvc` errors, reporting them contextually in the workflow summary by means of annotations.

Expand Down Expand Up @@ -55,12 +55,11 @@ jobs:
# Or pin to a specific CMake version:
# lukka/get-cmake@v3.21.2

# Restore from cache the previously built ports. If a "cache miss" occurs,
# then vcpkg is bootstrapped. Since a the vcpkg.json is being used later on
# to install the packages when `run-cmake` runs, no packages are installed at
# this time.
- name: Restore artifacts, or setup vcpkg (do not install any package)
uses: lukka/run-vcpkg@v10
# Run vcpkg leveraging its own binary caching integration with GitHub Action
# cache. Since vcpkg.json is being used later on to install the packages
# when `run-cmake` runs, no packages are installed at this time.
- name: Setup vcpkg (do not install any package yet)
uses: lukka/run-vcpkg@v11
#with:
# This is the default location of the directory containing vcpkg sources.
# Change it to the right location if needed.
Expand All @@ -73,10 +72,10 @@ jobs:

# This is the glob expression used to locate the vcpkg.json and add its
# hash to the cache key. Change it to match a single manifest file you want
# to use.
# Note: do not use `${{ github.context }}` to compose the value as it
# to use.
# Note: do not use `${{ github.context }}` to compose the value as it
# contains backslashes that would be misinterpreted. Instead
# compose a value relative to the root of the repository using
# compose a value relative to the root of the repository using
# `**/path/from/root/of/repo/to/vcpkg.json` to match the desired `vcpkg.json`.
# vcpkgJsonGlob: '**/vcpkg.json'

Expand All @@ -86,20 +85,8 @@ jobs:
# (i.e. let CMake run `vcpkg install`) using the vcpkg.cmake toolchain.
# runVcpkgInstall: true

# The following `run` step is useful to prevent storing partial cache in the GH cache
# service.
# This is useful when vcpkg is not run at `run-vcpkg`'s runtime, but later when CMake
# is running, e.g. at `run-cmake` runtime.
# Driving the environment variable `RUNVCPKG_NO_CACHE`, at the end of the workflow the
# `run-vcpkg` post step is instructed to not save anything when the workflow has been
# cancelled or it has failed.
#- run: |
# echo "RUNVCPKG_NO_CACHE=1" >> $GITHUB_ENV
# if: ${{ failure() || cancelled() }}
# shell: bash

- name: Run CMake consuming CMakePreset.json and vcpkg.json by mean of vcpkg.
uses: lukka/run-cmake@v10
uses: lukka/run-cmake@v11
with:
# This is the default path to the CMakeLists.txt along side the
# CMakePresets.json. Change if you need have CMakeLists.txt and CMakePresets.json
Expand All @@ -115,14 +102,14 @@ jobs:
buildPreset: 'ninja-multi-vcpkg'

#env:
# By default the action disables vcpkg's telemetry by defining VCPKG_DISABLE_METRICS.
# By default the action disables vcpkg's telemetry by defining VCPKG_DISABLE_METRICS.
# This behavior can be disabled by defining `VCPKG_ENABLE_METRICS` as follows.
# VCPKG_ENABLE_METRICS: 1
# VCPKG_ENABLE_METRICS: 1
#
# [OPTIONAL] Define the vcpkg's triplet you want to enforce, otherwise the default one
# for the hosting system will be automatically choosen (x64 is the default on all
# for the hosting system will be automatically choosen (x64 is the default on all
# platforms, e.g. `x64-osx`).
# VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
# VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
```

## Action reference: all input/output parameters
Expand All @@ -136,26 +123,25 @@ Flowchart with related input in [action.yml](https://github.com/lukka/run-vcpkg/
```
┌──────────────────────────┐
│ Compute cache key from: │ Inputs:
│ - vcpkg Git commit │ - `prependedCacheKey` and `appendedCacheKey`
│ - platform and OS │ - `vcpkgGitCommitId`
│ - vcpkg Git commit │ - `vcpkgGitCommitId`
│ - platform and OS │
│ - user provided keys │
└─────────────┬────────────┘
┌─────────────────────────┐
│ Locate vcpkg.json. │ Inputs:
If found, add its hash │ - `vcpkgJsonGlob`
to cache key_ `vcpkgJsonIgnores`
│ - `vcpkgJsonGlob`
- `vcpkgJsonIgnores`
└────────────┬────────────┘
┌─────────────────────────┐ Inputs:
│ Restore vcpkg and │ - `doNotCache`
│ packages from cache │ - `vcpkgDirectory`
│ to cache key │ - `binaryCachePath`
└────────────┬────────────┘ Environment variable:
│ - `VCPKG_DEFAULT_BINARY_CACHE`: where previous built packages
▼ are going to be restored
│ Restore vcpkg │ - `vcpkgDirectory`
│ from the GH cache │
└────────────┬────────────┘
┌─────────────────────────┐
│ If vcpkg is not a │ Inputs:
│ submodule, fetch it │ - `vcpkgGitCommitId`
Expand All @@ -180,7 +166,7 @@ Flowchart with related input in [action.yml](https://github.com/lukka/run-vcpkg/
│ been located │ │ Environment variables:
└────────────┬────────────┘ │ - `VCPKG_DEFAULT_TRIPLET` is used. If not yet
│ │ set, it is set to the current platform.
│ │ - `VCPKG_INSTALLED_DIR` is used as value for
│ │ - `VCPKG_INSTALLED_DIR` is used as value for
│ │ `--x-install-root` when running `vcpkg install`.
│ │ Check out the `runVcpkgFormatString` input.
▼ │
Expand All @@ -191,17 +177,14 @@ Flowchart with related input in [action.yml](https://github.com/lukka/run-vcpkg/
└────────────┬────────────┘ │
├───────────── ┘
┌───────────────────────────┐
│ Schedule this step at │
│ end of the workflow: │
│┌─────────────────────────┐│
│| If no cache-hit, ││ Inputs:
││ store `VCPKG_ROOT` and ││ - `binaryCachePath`
││ binary packages in cache││ - `doNotCache`
││ ││ Environment variables:
│└────────────┬────────────┘│ - RUNVCPKG_NO_CACHE: Any step before the post action
└────────────┬──────────────┘ may set this environment variable to disable saving
▼ the cache.
┌─────────────────────────┐
│ If no cache-hit, │ Inputs:
│ store vcpkg onto │ - `doNotCache`
│ GH cache │
└────────────┬────────────┘
|
|
```

Expand Down Expand Up @@ -230,12 +213,12 @@ The dependencies specified in the vcpkg.json file are installed when CMake runs

_Checkmarks_ indicates whether the samples "uses" or specifies the thing in the header or whether it is true.

|workflow link|`vcpkg` as submodule|explicit triplet|`vcpkg` toolchain|`CMake`'s Presets|`Ninja`|`run-vcpkg` runs vcpkg|`CMake` runs `vcpkg`
|:-|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|[link](https://github.com/lukka/CppBuildTasks-Validation/blob/v10/.github/workflows/hosted-ninja-vcpkg_submod.yml)||||||||
|[link](https://github.com/lukka/CppBuildTasks-Validation/blob/v10/.github/workflows/hosted-ninja-vcpkg.yml)|❌|❌|✅|✅|✅|❌|✅
|[link](https://github.com/lukka/CppBuildTasks-Validation/blob/v10/.github/workflows/hosted-ninja-vcpkg-install.yml)||||||||
|[link](https://github.com/lukka/CppBuildTasks-Validation/blob/v10/.github/workflows/hosted-ninja-vcpkg_submod-triplet.yml)|✅|✅|✅|✅|✅|❌|✅
| workflow link | `vcpkg` as submodule | explicit triplet | `vcpkg` toolchain | `CMake`'s Presets | `Ninja` | `run-vcpkg` runs vcpkg | `CMake` runs `vcpkg` |
| :------------------------------------------------------------------------------------------------------------------------- | :------------------: | :--------------: | :---------------: | :---------------: | :-----: | :--------------------: | :------------------: |
| [link](https://github.com/lukka/CppBuildTasks-Validation/blob/v11/.github/workflows/hosted-ninja-vcpkg_submod.yml) ||||||||
| [link](https://github.com/lukka/CppBuildTasks-Validation/blob/v11/.github/workflows/hosted-ninja-vcpkg.yml) ||||||||
| [link](https://github.com/lukka/CppBuildTasks-Validation/blob/v11/.github/workflows/hosted-ninja-vcpkg-install.yml) ||||||||
| [link](https://github.com/lukka/CppBuildTasks-Validation/blob/v11/.github/workflows/hosted-ninja-vcpkg_submod-triplet.yml) ||||||||

<br>

Expand All @@ -249,7 +232,7 @@ _Checkmarks_ indicates whether the samples "uses" or specifies the thing in the

All the content in this repository is licensed under the [MIT License](LICENSE.txt).

Copyright © 2019-2020-2021-2022 Luca Cappa
Copyright © 2019-2020-2021-2022-2023 Luca Cappa

# Disclaimer

Expand Down
24 changes: 17 additions & 7 deletions __tests__/functional.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021-2022 Luca Cappa
// Copyright (c) 2021-2022-2023 Luca Cappa
// Released under the term specified in file LICENSE.txt
// SPDX short identifier: MIT

Expand All @@ -24,6 +24,9 @@ const baseLibUtils = new BaseUtilLib(actionLib);
describe('run-vcpkg functional tests', () => {
beforeEach(async () => {
process.env.GITHUB_WORKSPACE = assetDirectory;
// The GH Action cache is not enabled when running tests because these env vars are not defined:
// ACTIONS_RUNTIME_TOKEN and ACTIONS_CACHE_URL. Set a default that uses the filesystem and won't fail.
process.env.VCPKG_BINARY_SOURCES = 'clear;default,readwrite';

await actionLib.rmRF(vcpkgDirectory);
await actionLib.rmRF(tempDirectory);
Expand All @@ -46,12 +49,16 @@ describe('run-vcpkg functional tests', () => {
}, 100000);

test('vcpkg setup and install must succeed', () => {
process.env.INPUT_VCPKGGITURL = "https://github.com/lukka/vcpkg.git";
process.env.INPUT_VCPKGDIRECTORY = vcpkgDirectory;
process.env.INPUT_VCPKGJSONGLOB = "**/vcpkg.json";
process.env.INPUT_VCPKGGITCOMMITID = "6ca56aeb457f033d344a7106cb3f9f1abf8f4e98";
process.env.INPUT_VCPKGGITCOMMITID = "02b6fe4f9e8c97afceddd0d2e3802cf469882a4e";
process.env.INPUT_RUNVCPKGINSTALL = "true";
process.env.INPUT_RUNVCPKGFORMATSTRING = runvcpkglib.VcpkgRunner.VCPKGINSTALLCMDDEFAULT;

// Ensure child is running in the GH workspace, needed to find vcpkg.json.
process.chdir(vcpkgProject);

const options: cp.ExecSyncOptions = {
env: process.env,
stdio: "inherit"
Expand All @@ -60,9 +67,10 @@ describe('run-vcpkg functional tests', () => {
});

test('vcpkg setup and no install must succeed', () => {
process.env.INPUT_VCPKGGITURL = "https://github.com/lukka/vcpkg.git";
process.env.INPUT_VCPKGDIRECTORY = vcpkgDirectory;
process.env.INPUT_VCPKGJSONGLOB = "**/vcpkg.json";
process.env.INPUT_VCPKGGITCOMMITID = "6ca56aeb457f033d344a7106cb3f9f1abf8f4e98";
process.env.INPUT_VCPKGGITCOMMITID = "02b6fe4f9e8c97afceddd0d2e3802cf469882a4e";
process.env.INPUT_RUNVCPKGINSTALL = "false";
process.env.INPUT_RUNVCPKGFORMATSTRING = "['invalid command']";

Expand All @@ -77,7 +85,8 @@ describe('run-vcpkg functional tests', () => {
delete process.env.INPUT_VCPKGDIRECTORY;
console.log(process.env.INPUT_VCPKGDIRECTORY);
delete process.env.INPUT_VCPKGJSONGLOB;
process.env.INPUT_VCPKGGITCOMMITID = "6ca56aeb457f033d344a7106cb3f9f1abf8f4e98";
process.env.INPUT_VCPKGGITURL = "https://github.com/lukka/vcpkg.git";
process.env.INPUT_VCPKGGITCOMMITID = "02b6fe4f9e8c97afceddd0d2e3802cf469882a4e";
process.env.INPUT_RUNVCPKGINSTALL = "false";
process.env.INPUT_RUNVCPKGFORMATSTRING = runvcpkglib.VcpkgRunner.VCPKGINSTALLCMDDEFAULT;

Expand All @@ -101,8 +110,9 @@ describe('run-vcpkg functional tests', () => {
await actionLib.rmRF(await runvcpkglib.getDefaultVcpkgDirectory(baseLibUtils.baseLib));
await actionLib.rmRF(await runvcpkglib.getDefaultVcpkgInstallDirectory(baseLibUtils.baseLib));
await actionLib.rmRF(await runvcpkglib.getDefaultVcpkgCacheDirectory(baseLibUtils.baseLib));

process.env.INPUT_VCPKGGITCOMMITID = "6ca56aeb457f033d344a7106cb3f9f1abf8f4e98";

process.env.INPUT_VCPKGGITURL = "https://github.com/lukka/vcpkg.git";
process.env.INPUT_VCPKGGITCOMMITID = "02b6fe4f9e8c97afceddd0d2e3802cf469882a4e";
process.env.INPUT_RUNVCPKGINSTALL = "true";
process.env.INPUT_RUNVCPKGFORMATSTRING = runvcpkglib.VcpkgRunner.VCPKGINSTALLCMDDEFAULT;

Expand All @@ -124,7 +134,7 @@ describe('run-vcpkg functional tests', () => {
console.log(cp.execSync(`node ${testScript}`, options)?.toString());
const elapsedWithInstalled = new Date().getTime() - startTime.getTime();
console.log(`********* With vcpkg_installed it took: ${elapsedWithInstalled}ms`)
expect(elapsedWithInstalled).toBeLessThan(elapsed / 3);
expect(elapsedWithInstalled).toBeLessThan((elapsed / 3) + 5000);// Allow 5 seconds of abs err.

// Consume the generated cache, and it should take considerably less than without cache.
await actionLib.rmRF(await runvcpkglib.getDefaultVcpkgInstallDirectory(baseLibUtils.baseLib));
Expand Down

0 comments on commit 549a9ea

Please sign in to comment.