mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-08 02:53:25 -08:00
The cache had no prefix, and TAServers/vcpkg-cache restores every entry it finds under the prefix rather than only the hashes vcpkg asks for. With all legs sharing the single vcpkg/ namespace, each of the five of them downloads all 66 archives of all five on every run. Each restore also refreshes the entry's last access date, so a dead ABI generation stays fresh forever and GitHub's least recently used eviction can never reach it. Name the scope in the key after the platform, target and toolchain it belongs to, so a leg restores only its own archives. macOS 14, 15 and 26 on the same Xcode build identical binaries when they share the lowest deployment target, so point all three at 14 and let them share one scope instead of three. A pull request cannot write the shared cache either. Its entries are scoped to refs/pull/<n>/merge, so nothing it saves is ever readable again, and letting it write anyway only burns the repository's quota, which is what the previous attempt at this did. Keep the build read-only and hand the archives it had to build itself to a new workflow running in the default branch scope, which saves them where master can restore them. Forks stay read-only, they are the one case whose archives must not be trusted. Because the prefix changes every key, add a job that deletes the entries of retired scopes, which is the one-time clean up of the current flat namespace, and the per-run ones pull requests leave behind, which age based eviction also never reaches. Also pin the Linux ccache cache to its own subdirectory, since the directory is shared with the docker build context, and drop the clang-format install from the build images, which format nothing at runtime.
112 lines
No EOL
4.4 KiB
YAML
112 lines
No EOL
4.4 KiB
YAML
name: Import vcpkg cache
|
|
|
|
# A pull request run can only write caches into its own refs/pull/<n>/merge scope, which
|
|
# nothing else is allowed to restore. So after a runner image update changes every port's
|
|
# ABI hash, the first pull request rebuilds protobuf, openssl and abseil from source and
|
|
# the next one does the same, until somebody merges and a master run finally repopulates
|
|
# the shared cache. This workflow takes the archives such a run produced and saves them
|
|
# in the default branch scope instead, where every later run can restore them.
|
|
#
|
|
# repository_dispatch is not used on purpose: it would also resolve to the default branch,
|
|
# but it counts as a low-trust trigger and may only write there when it declares a
|
|
# write-capable cache-mode, which puts it in the same position as workflow_run.
|
|
|
|
permissions:
|
|
actions: write # needed to save entries into the default branch's cache scope
|
|
contents: read
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows: ["Build Desktop"]
|
|
types: [completed]
|
|
|
|
# Every import writes the same scopes, so let them queue instead of racing each other
|
|
concurrency:
|
|
group: vcpkg-cache-import
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
list:
|
|
name: List new vcpkg entries
|
|
# Only a successful same-repository pull request has archives worth importing. Forks
|
|
# build untrusted code and must never reach a cache that master runs restore and link.
|
|
if: >-
|
|
github.event.workflow_run.conclusion == 'success' &&
|
|
github.event.workflow_run.event == 'pull_request' &&
|
|
github.event.workflow_run.head_repository.full_name == github.repository
|
|
runs-on: ubuntu-slim # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md
|
|
# workflow_run is a low-trust trigger, so cache access is read-only by default even
|
|
# though this run resolves to the default branch. Assert below that this took effect,
|
|
# because a save under read-only access only warns and would import nothing silently.
|
|
cache-mode: write
|
|
outputs:
|
|
entries: ${{ steps.scan.outputs.entries }}
|
|
|
|
steps:
|
|
- name: "Download new vcpkg entries"
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: vcpkg-new-*
|
|
path: incoming
|
|
run-id: ${{ github.event.workflow_run.id }}
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: "Assert write access"
|
|
shell: bash
|
|
run: |
|
|
if [[ $ACTIONS_CACHE_MODE != *write* ]]; then
|
|
echo "::error::expected a write-capable cache, got '$ACTIONS_CACHE_MODE'"
|
|
exit 1
|
|
fi
|
|
|
|
- name: "List cache entries"
|
|
id: scan
|
|
shell: bash
|
|
working-directory: incoming
|
|
run: |
|
|
entries="$(find . -name keys.txt -type f -exec sh -c '
|
|
for manifest; do
|
|
artifact="$(basename "$(dirname "$manifest")")"
|
|
while read -r key path; do
|
|
printf "{\"artifact\": \"%s\", \"key\": \"%s\", \"path\": \"%s\"}\n" \
|
|
"$artifact" "$key" "$path"
|
|
done <"$manifest"
|
|
done
|
|
' _ {} +)"
|
|
[[ -n $entries ]] || exit 0
|
|
# Compact, because a multi line value cannot be written to GITHUB_OUTPUT
|
|
entries="$(jq -cs '.' <<<"$entries")"
|
|
echo "entries=$entries" >>"$GITHUB_OUTPUT"
|
|
echo "::notice::importing $(jq length <<<"$entries") vcpkg entries"
|
|
|
|
save:
|
|
name: "Save ${{ matrix.entry.key }}"
|
|
needs: list
|
|
if: needs.list.outputs.entries
|
|
runs-on: ubuntu-slim
|
|
cache-mode: write
|
|
strategy:
|
|
# One job per archive, they run in parallel and each only uploads a single file
|
|
fail-fast: false
|
|
max-parallel: 20
|
|
matrix:
|
|
entry: ${{ fromJSON(needs.list.outputs.entries) }}
|
|
|
|
steps:
|
|
- name: "Download new vcpkg entries"
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: ${{ matrix.entry.artifact }}
|
|
path: incoming
|
|
run-id: ${{ github.event.workflow_run.id }}
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: "Save vcpkg entry"
|
|
uses: actions/cache/save@v6
|
|
with:
|
|
# The payload is a Windows or macOS archive while the upload runs on Linux, and
|
|
# without this the entry would be stamped as a Linux cache that neither of them
|
|
# is allowed to restore.
|
|
enableCrossOsArchive: true
|
|
key: ${{ matrix.entry.key }}
|
|
path: incoming/${{ matrix.entry.path }} |