The build workflow can use a private Cloudflare R2 bucket through vcpkg's
experimental x-aws provider. Transfers go directly to the R2 S3 endpoint.
The local cache stays enabled. This branch leaves GitHub NuGet caching disabled.
Create a dedicated private R2 bucket using Standard storage. Configure these GitHub Actions repository variables and secrets before enabling the integration.
| Actions setting | Kind | Pipeline environment variable | Value |
|---|---|---|---|
VCPKG_R2_ENABLED |
Variable | Workflow condition | true to enable |
VCPKG_R2_ENDPOINT_URL |
Variable | R2_ENDPOINT_URL |
https://<account-id>.r2.cloudflarestorage.com |
VCPKG_R2_BUCKET |
Variable | R2_BUCKET |
Bucket name without a path |
VCPKG_R2_ACCESS_KEY_ID |
Secret | R2_ACCESS_KEY_ID |
Writer's R2 S3 access key ID |
VCPKG_R2_SECRET_ACCESS_KEY |
Secret | R2_SECRET_ACCESS_KEY |
Writer's R2 S3 secret access key |
VCPKG_R2_READ_ACCESS_KEY_ID |
Secret | R2_ACCESS_KEY_ID |
Reader's R2 S3 access key ID, reserved for restoring read-only PR access |
VCPKG_R2_READ_SECRET_ACCESS_KEY |
Secret | R2_SECRET_ACCESS_KEY |
Reader's R2 S3 secret access key, reserved for restoring read-only PR access |
No account, bucket, or credential is embedded in the repository. Jurisdictional
<account-id>.eu.r2.cloudflarestorage.com and
<account-id>.fedramp.r2.cloudflarestorage.com endpoints are also accepted.
Objects use cache/<ABI>.zip. The prefix is fixed so build configuration and
retention rules address the same objects.
For the temporary cache population test, protected non-PR runs and
same-repository PRs both use R2_CACHE_MODE=readwrite and the bucket-scoped
Object Read & Write credentials. After testing, restore the PR step to
R2_CACHE_MODE=read and switch both credential references back to
VCPKG_R2_READ_ACCESS_KEY_ID and VCPKG_R2_READ_SECRET_ACCESS_KEY.
The script still defaults to read when the mode is omitted. The reader
credential must enforce Object Read permissions at R2; setting vcpkg to read
does not restrict a credential that can write.
Protect the branches and tags that should publish cache entries. A manual dispatch on an unprotected branch skips R2. Fork PRs also skip R2 to keep the bucket private without exposing credentials. All PRs retain local read/write caching. Same-repository Dependabot PRs need the credentials selected by the PR step under Dependabot secrets as well, using the same names. Missing credentials fail setup when R2 is enabled for a same-repository PR. Do not put R2 credentials in job-wide environment variables or expose them to fork builds. Anyone able to change a workflow that receives write credentials can publish cache binaries, so limit that access to trusted maintainers.
Windows and Linux hosted runners supply AWS CLI v2. The workflow installs it
with Homebrew on macOS. Custom runners must install AWS CLI v2.13.0 or newer.
The setup script calls the repository's vcpkg fetch aws to find the executable
vcpkg will use, checks its version, and lists at most one object under cache/.
This read preflight uses AWS_ENDPOINT_URL_S3, without a command-line endpoint
override. A missing credential, CLI, or inaccessible bucket fails setup before
changing the job environment. It does not prove upload or restore behavior.
After preflight, the script exports R2 credentials, the S3 endpoint, region
auto, and the extended VCPKG_BINARY_SOURCES through GITHUB_ENV. Protected
non-PR builds and same-repository PRs can write to R2 during this test.
Packages restored from the local cache
are not automatically copied into R2. Seed required ABIs explicitly or allow
R2 to fill as dependencies rebuild.
No lifecycle rule or Worker is deployed by this integration. Choose retention
on the bucket separately. A starting policy is expiration after 90 days under
cache/, with incomplete multipart uploads aborted after seven days. Age-based
expiration can delete frequently used packages. It does not measure usage or
enforce a storage quota. Retain release dependencies separately if rebuilding
them later is unacceptable.
Use a scheduled Worker only when a concrete policy needs more than native expiration. Tracking dependencies used by successful builds also accounts for local cache hits; remote read logs alone do not.
Install AWS CLI v2.13.0 or newer and obtain bucket-scoped Object Read credentials.
Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY through your credential
manager, or select a dedicated AWS_PROFILE. Then, in PowerShell:
$env:AWS_ENDPOINT_URL_S3 = $env:R2_ENDPOINT_URL
$env:AWS_REGION = 'auto'
$env:AWS_DEFAULT_REGION = 'auto'
$env:AWS_IGNORE_CONFIGURED_ENDPOINT_URLS = 'false'
$env:AWS_PAGER = ''
$env:VCPKG_BINARY_SOURCES = "clear;default,readwrite;x-aws,s3://$($env:R2_BUCKET)/cache/,read"
cmake -S indra --preset vs2026-osSet R2_ENDPOINT_URL and R2_BUCKET in the shell environment first. On macOS
or Linux, export the same values and use the appropriate CMake preset. Read-only
credentials must enforce permissions at R2; the vcpkg read mode alone is not
an access control. Avoid stale AWS_SESSION_TOKEN values when using permanent
R2 credentials.
Run these before relying on R2 across the build matrix. The supplied
logs_96086559729.zip confirmed authenticated read preflights on all ten build
jobs, with zero restored packages and R2 in read-only mode. Uploads and
successful restores still need validation.
-
On each runner platform, confirm the setup log identifies the vcpkg-selected AWS CLI and passes the read preflight. Check a same-repository PR reports
readwritemode and uses the writer credential during this test. After reverting the temporary change, expectreadand the reader credential. Check a fork PR skips both R2 setup steps, and a protected non-PR run reportsreadwritemode. -
Pick a real Alchemy cache ZIP larger than 100 MiB. Upload it using
aws s3 cpto a uniquevalidation/<run-id>/prefix, download it to a different local path, and compare SHA-256 hashes. Keep this separate fromcache/. Do not infer integrity from multipart ETags. -
Demonstrate a vcpkg restore with only R2 configured. Use a new build directory and a new install directory. For example, after a trusted producer has populated matching ABIs on Windows:
$run = [guid]::NewGuid().ToString('N') $build = Join-Path $PWD "build-r2-verify-$run" $env:VCPKG_BINARY_SOURCES = "clear;x-aws,s3://$($env:R2_BUCKET)/cache/,read" cmake -S indra --preset vs2026-os -B $build ` -DVCPKG_TARGET_TRIPLET=x64-windows-alchemy-avx2-release ` "-DVCPKG_INSTALLED_DIR=$build/vcpkg_installed" ` -DVCPKG_INSTALL_OPTIONS=--only-binarycaching if ($LASTEXITCODE -ne 0) { throw 'Remote-only restore failed' }
Match the producer's compiler, vcpkg revision, features, and triplets. Require the vcpkg log to report packages restored from AWS and a successful configure.
--only-binarycachingmakes a missing binary fail instead of quietly building from source. The fresh directories avoid Alchemy's install stamp and existing installed packages.clearremoves local and NuGet cache reads. -
With a separate empty validation prefix and another fresh build directory, run without
--only-binarycachingand confirm a cache miss builds successfully. Usereadwritewith the writer credential and then repeat with a fresh install directory andreadto demonstrate the resulting upload and restore. Do not delete production cache entries to manufacture a miss. -
With the consumer credential, confirm a known object downloads and an upload to a unique validation key fails with
AccessDenied. A network failure is not evidence of read-only permissions. Use an authorized writer to remove only the validation prefix after checking it contains the intended test objects.
This branch already disables NuGet caching and its authentication step. R2 is
added alongside the local cache. Run the remote-only checks on each platform;
a successful build with local caching enabled does not prove that R2 served a
package. Disabling VCPKG_R2_ENABLED restores local-only caching immediately.
It leaves bucket contents and retention policy untouched. Cache misses build
from source.
Local setup checks:
python -m unittest discover -s scripts/vcpkg -p test_*.py -v