Skip to content

Commit 304dd78

Browse files
committed
Optimize GitHub Actions cache usage
Simplify the caching of the embedded executables. Makes the cache size smaller, at the cost of some extra packaging time spent to build the gzipped blob during build time. This requires some tricks to tell make what needs to be built and what doesn't. Only keep the most recent cache per branch. All caches ending in a hash will be pruned so that only the newest cache is retained on a per-branch and per-key-prefix basis. Don't use leading slashes for URLs passed to the gh CLI. Leading slashes would otherwise trigger file path normalization in bash on Windows, which would render the URL fragment illegal. Use a fixed source date epoch in unit tests to better leverage cache usage. Signed-off-by: Tom Wieczorek <[email protected]>
1 parent 3566994 commit 304dd78

File tree

6 files changed

+103
-47
lines changed

6 files changed

+103
-47
lines changed

.github/workflows/build-k0s.yml

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,34 +58,35 @@ jobs:
5858
echo executable-suffix="$executableSuffix" >>"$GITHUB_OUTPUT"
5959
6060
- name: "Cache :: embedded binaries"
61+
id: cache-embedded-bins
6162
uses: actions/cache@v4
6263
with:
63-
key: build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-embedded-bins-${{ hashFiles('embedded-bins/**/*') }}
64-
path: |
65-
.bins.${{ inputs.target-os }}.stamp
66-
bindata_${{ inputs.target-os }}
67-
embedded-bins/staging/${{ inputs.target-os }}/bin/
68-
embedded-bins/Makefile.variables
69-
pkg/assets/zz_generated_offsets_${{ inputs.target-os }}.go
64+
key: "build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-embedded-bins-${{ hashFiles('embedded-bins/**/*') }}"
65+
path: embedded-bins/staging/${{ inputs.target-os }}/bin/
7066

71-
- name: "Cache :: GOCACHE"
67+
- name: "Cache :: Go cache"
7268
id: cache-gocache
7369
uses: actions/cache@v4
7470
with:
75-
key: build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-gocache-${{ github.ref_name }}-${{ github.sha }}
76-
restore-keys: |
77-
build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-gocache-${{ github.ref_name }}-
78-
path: |
79-
build/cache/go/build
71+
key: "build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
72+
restore-keys: "build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-gocache-go${{ env.GO_VERSION }}-"
73+
path: build/cache/go/build
8074

81-
- name: "Cache :: GOCACHE :: Prepare"
75+
- name: "Cache :: Go cache :: Prepare"
8276
if: steps.cache-gocache.outputs.cache-hit
8377
run: |
8478
touch -t "$(TZ=UTC+24 date +%Y%m%d%H%M.%S)" build/cache/_cache_sentinel
8579
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -exec touch -r build/cache/_cache_sentinel {} +
8680
8781
- name: "Build :: k0s"
82+
env:
83+
EMBEDDED_BINS_CACHED: "${{ steps.cache-embedded-bins.outputs.cache-hit }}"
8884
run: |
85+
make .k0sbuild.docker-image.k0s
86+
touch go.sum
87+
if [ "$EMBEDDED_BINS_CACHED" == true ]; then
88+
make --touch ".bins.$TARGET_OS.stamp"
89+
fi
8990
make bindata
9091
make --touch codegen
9192
make build
@@ -129,7 +130,7 @@ jobs:
129130
name: ipv6-test-image-list-${{ inputs.target-os }}-${{ inputs.target-arch }}
130131
path: ipv6-test-images.txt
131132

132-
- name: "Cache :: GOCACHE :: Trim"
133+
- name: "Cache :: Go cache :: Trim"
133134
if: steps.cache-gocache.outputs.cache-hit
134135
run: |
135136
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -not -newer build/cache/_cache_sentinel -delete
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Go build completed
2+
3+
on:
4+
workflow_run:
5+
workflows: [Go build]
6+
types: [completed]
7+
8+
jobs:
9+
# Based on https://github.com/actions/cache/blob/v4.2.0/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy
10+
cleanup-actions-caches:
11+
name: Cleanup GitHub Actions caches
12+
runs-on: ubuntu-latest
13+
permissions:
14+
# `actions:write` permission is required to delete caches
15+
# See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id
16+
actions: write
17+
18+
steps:
19+
# Group all caches that end with a Git commit hash by branch and keep only the most recently created one.
20+
- name: Cleanup
21+
env:
22+
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
23+
GH_REPO: "${{ github.repository }}"
24+
QUERY: |
25+
[ .actions_caches[]
26+
| . + { key_prefix: .key | sub("-[0-9a-f]{40}$"; "") } # Calculate cache prefix
27+
| select(.key_prefix != .key) # Only keep caches which have the right suffix
28+
]
29+
| [
30+
group_by([.ref, .key_prefix])[] # Look at all the caches per branch with the same prefix
31+
| sort_by(.created_at) # Sort by creation date ...
32+
| reverse # ... so that the newest cache is the first in the array
33+
| del(.[0]) # Remove that newest cache, i.e. don't delete it
34+
]
35+
| flatten # Remove the grouping
36+
| .[] # Unpack the resulting flat array
37+
| [.id, .ref, .key] # Extract the values to be returned
38+
| @sh # Escape them to be used in POSIX shells
39+
40+
run: |
41+
set -euo pipefail
42+
gh api -X GET repos/{owner}/{repo}/actions/caches -q "$QUERY" | while read -r args; do
43+
eval "set -- $args"
44+
echo Deleting cache with id "$1" from "$2": "$3"
45+
gh api -X DELETE repos/{owner}/{repo}/actions/caches/"$1" || :
46+
done

.github/workflows/go.yml

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ jobs:
181181

182182
env:
183183
EMBEDDED_BINS_BUILDMODE: none
184+
# Set SOURCE_DATE_EPOCH to optimize cache usage
185+
MAKEFLAGS: -j SOURCE_DATE_EPOCH=315532800
184186

185187
steps:
186188
- name: Check out code into the Go module directory
@@ -211,15 +213,13 @@ jobs:
211213
go-version: ${{ env.GO_VERSION }}
212214
cache: false
213215

214-
- name: Cache GOCACHE
216+
- name: Cache Go cache
215217
id: cache-gocache
216218
uses: actions/cache@v4
217219
with:
218-
key: unittests-k0s-${{ matrix.name }}-gocache-${{ github.ref_name }}-${{ github.sha }}
219-
restore-keys: |
220-
unittests-k0s-${{ matrix.name }}-gocache-${{ github.ref_name }}-
221-
path: |
222-
build/cache/go/build
220+
key: "unittests-k0s-${{ matrix.name }}-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
221+
restore-keys: "unittests-k0s-${{ matrix.name }}-gocache-go${{ env.GO_VERSION }}-"
222+
path: build/cache/go/build
223223

224224
- name: Run unit tests
225225
env:
@@ -321,35 +321,40 @@ jobs:
321321
go-version: ${{ env.GO_VERSION }}
322322

323323
- name: Cache embedded binaries
324+
id: cache-embedded-bins
324325
uses: actions/cache@v4
325326
with:
326-
key: ${{ runner.os }}-embedded-bins-arm-${{ hashFiles('**/embedded-bins/**/*') }}
327-
path: |
328-
.bins.linux.stamp
329-
embedded-bins/staging/linux/bin/
330-
embedded-bins/Makefile.variables
327+
key: "build-k0s-linux-arm-embedded-bins-${{ hashFiles('embedded-bins/**/*') }}"
328+
path: embedded-bins/staging/linux/bin/
331329

332-
- name: Cache GOCACHE
330+
- name: Cache Go cache
333331
id: cache-gocache
334332
uses: actions/cache@v4
335333
with:
336-
key: ${{ runner.os }}-smoketest-arm-gocache-arm-${{ github.ref_name }}-${{ github.sha }}
337-
restore-keys: |
338-
${{ runner.os }}-smoketest-arm-gocache-arm-${{ github.ref_name }}-
339-
path: |
340-
build/cache/go/build
334+
key: "build-k0s-linux-arm-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
335+
restore-keys: "build-k0s-linux-arm-gocache-go${{ env.GO_VERSION }}-"
336+
path: build/cache/go/build
341337

342-
- name: Cache GOCACHE - Prepare
338+
- name: Prepare Go cache
343339
if: steps.cache-gocache.outputs.cache-hit
344340
run: |
345341
touch -t "$(TZ=UTC+24 date +%Y%m%d%H%M.%S)" build/cache/_cache_sentinel
346342
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -exec touch -r build/cache/_cache_sentinel {} +
347343
348344
- name: Build
345+
env:
346+
EMBEDDED_BINS_CACHED: "${{ steps.cache-embedded-bins.outputs.cache-hit }}"
349347
run: |
348+
gh --version || echo No gh installed
349+
make .k0sbuild.docker-image.k0s
350+
touch go.sum
351+
if [ "$EMBEDDED_BINS_CACHED" == true ]; then
352+
make --touch .bins.linux.stamp
353+
fi
350354
make bindata
351355
make --touch codegen
352356
make build
357+
echo "k0s binary size: **$(du -sh k0s | cut -f1)**" >>$GITHUB_STEP_SUMMARY
353358
354359
- name: Upload compiled executable
355360
uses: actions/upload-artifact@v4
@@ -382,7 +387,7 @@ jobs:
382387
name: airgap-image-bundle-linux-arm.tar
383388
path: airgap-image-bundle-linux-arm.tar
384389

385-
- name: Cache GOCACHE - Trim
390+
- name: Trim Go cache
386391
if: steps.cache-gocache.outputs.cache-hit
387392
run: |
388393
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -not -newer build/cache/_cache_sentinel -delete

.github/workflows/lint.yaml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ env:
3030
MAKEFLAGS: -j
3131
EMBEDDED_BINS_BUILDMODE: none
3232

33+
permissions:
34+
contents: read
35+
3336
jobs:
3437
lint-go:
3538
strategy:
@@ -67,14 +70,13 @@ jobs:
6770
go-version: ${{ env.GO_VERSION }}
6871
cache: false
6972

70-
- name: "Cache :: golangci-lint"
73+
- name: Cache golangci-lint cache
7174
id: cache-golangci
7275
uses: actions/cache@v4
7376
with:
74-
key: lint-${{ matrix.target-os }}-amd64-golangci-${{ github.ref_name }}-${{ github.sha }}
77+
key: "lint-${{ matrix.target-os }}-amd64-golangci-${{ env.GOLANGCI_LINT_VERSION }}-go-${{ env.GO_VERSION }}-${{ github.sha }}"
7578
restore-keys: |
76-
lint-${{ matrix.target-os }}-amd64-golangci-${{ github.ref_name }}-
77-
lint-${{ matrix.target-os }}-amd64-golangci-main-
79+
lint-${{ matrix.target-os }}-amd64-golangci-${{ env.GOLANGCI_LINT_VERSION }}-go-${{ env.GO_VERSION }}-
7880
path: |
7981
build/cache/go/build
8082
build/cache/golangci-lint
@@ -103,16 +105,18 @@ jobs:
103105
- uses: actions/checkout@v4
104106
with:
105107
fetch-depth: 0
108+
preserve-credentials: false
109+
110+
- name: Prepare build environment
111+
run: .github/workflows/prepare-build-env.sh
106112

107-
- name: "Cache :: GOCACHE"
113+
- name: Restore Go cache
108114
uses: actions/cache/restore@v4
109115
with:
110-
key: build-k0s-linux-amd64-gocache-${{ github.ref_name }}-${{ github.sha }}
116+
key: "build-k0s-linux-amd64-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
111117
restore-keys: |
112-
build-k0s-linux-amd64-gocache-${{ github.ref_name }}-
113-
build-k0s-linux-amd64-gocache-main-
114-
path: |
115-
build/cache/go/build
118+
build-k0s-linux-amd64-gocache-go${{ env.GO_VERSION }}-
119+
path: build/cache/go/build
116120

117121
- name: Check go.mod/go.sum to be consistent
118122
run: make --always-make go.sum && git diff --exit-code

.github/workflows/ostests-nightly.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ jobs:
134134
# Message format described here: https://api.slack.com/surfaces/messages#payloads
135135
# The block structure can be tested online: https://app.slack.com/block-kit-builder
136136
run: |
137-
gh api "/repos/{owner}/{repo}/actions/runs/$GITHUB_RUN_ID/jobs" -q '
137+
gh api "repos/{owner}/{repo}/actions/runs/$GITHUB_RUN_ID/jobs" -q '
138138
def fmt_duration:
139139
if . >= 3600 then "\(./3600|floor) h \((.%3600/60|floor)) min"
140140
elif . >= 60 then "\(./60|floor) min \(.%60) sec"

.github/workflows/pr-closed.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ jobs:
2323
BRANCH: "refs/pull/${{ github.event.pull_request.number }}/merge"
2424
run: |
2525
set -euo pipefail
26-
gh api -X GET /repos/{owner}/{repo}/actions/caches -f ref="$BRANCH" --paginate -q '.actions_caches[] | "\(.id) \(.key)"' | {
26+
gh api -X GET repos/{owner}/{repo}/actions/caches -f ref="$BRANCH" --paginate -q '.actions_caches[] | "\(.id) \(.key)"' | {
2727
fail=0
2828
while read -r id key; do
2929
echo Deleting cache with ID $id: $key
30-
gh api -X DELETE /repos/{owner}/{repo}/actions/caches/"$id" || fail=1
30+
gh api -X DELETE repos/{owner}/{repo}/actions/caches/"$id" || fail=1
3131
done
3232
[ $fail -eq 0 ]
3333
}

0 commit comments

Comments
 (0)