Skip to content

Commit ba7e771

Browse files
authored
Merge pull request #6573 from k0sproject/backport-6555-to-release-1.34
[Backport release-1.34] Optimize GitHub Actions cache usage
2 parents 7e28043 + 77e597c commit ba7e771

File tree

6 files changed

+153
-78
lines changed

6 files changed

+153
-78
lines changed

.github/workflows/build-k0s.yml

Lines changed: 25 additions & 19 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"
68+
id: cache-gocache
7269
uses: actions/cache@v4
7370
with:
74-
key: build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-gocache-${{ github.ref_name }}-${{ github.sha }}
75-
restore-keys: |
76-
build-k0s-${{ inputs.target-os }}-${{ inputs.target-arch }}-gocache-${{ github.ref_name }}-
77-
path: |
78-
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
7974

80-
- name: "Cache :: GOMODCACHE"
81-
uses: actions/cache@v4
82-
with:
83-
key: build-k0s-gomodcache-${{ hashFiles('go.sum') }}
84-
path: build/cache/go/mod
85-
enableCrossOsArchive: true
75+
- name: "Cache :: Go cache :: Prepare"
76+
if: steps.cache-gocache.outputs.cache-hit
77+
run: |
78+
touch -t "$(TZ=UTC+24 date +%Y%m%d%H%M.%S)" build/cache/_cache_sentinel
79+
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
@@ -119,3 +120,8 @@ jobs:
119120
with:
120121
name: ipv6-test-image-list-${{ inputs.target-os }}-${{ inputs.target-arch }}
121122
path: ipv6-test-images.txt
123+
124+
- name: "Cache :: Go cache :: Trim"
125+
if: steps.cache-gocache.outputs.cache-hit
126+
run: |
127+
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: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ jobs:
178178

179179
env:
180180
EMBEDDED_BINS_BUILDMODE: none
181+
# Set SOURCE_DATE_EPOCH to optimize cache usage
182+
MAKEFLAGS: -j SOURCE_DATE_EPOCH=315532800
181183

182184
steps:
183185
- name: Check out code into the Go module directory
@@ -208,24 +210,30 @@ jobs:
208210
go-version: ${{ env.GO_VERSION }}
209211
cache: false
210212

211-
- name: Cache GOCACHE
213+
- name: Cache Go cache
214+
id: cache-gocache
212215
uses: actions/cache@v4
213216
with:
214-
key: unittests-k0s-${{ matrix.name }}-gocache-${{ github.ref_name }}-${{ github.sha }}
215-
restore-keys: |
216-
unittests-k0s-${{ matrix.name }}-gocache-${{ github.ref_name }}-
217-
path: |
218-
build/cache/go/build
219-
220-
- name: Cache GOMODCACHE
221-
uses: actions/cache@v4
222-
with:
223-
key: unittests-k0s-gomodcache-${{ hashFiles('go.sum') }}
224-
path: build/cache/go/mod
225-
enableCrossOsArchive: true
217+
key: "unittests-k0s-${{ matrix.name }}-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
218+
restore-keys: "unittests-k0s-${{ matrix.name }}-gocache-go${{ env.GO_VERSION }}-"
219+
path: build/cache/go/build
226220

227221
- name: Run unit tests
228-
run: make check-unit $UNITTEST_EXTRA_ARGS
222+
env:
223+
CACHE_HIT_GOCACHE: "${{ steps.cache-gocache.outputs.cache-hit }}"
224+
run: |
225+
if [ -n "$CACHE_HIT_GOCACHE" ]; then
226+
echo Preparing Go cache
227+
touch -t "$(TZ=UTC+24 date +%Y%m%d%H%M.%S)" build/cache/_cache_sentinel
228+
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -exec touch -r build/cache/_cache_sentinel {} +
229+
fi
230+
231+
make check-unit $UNITTEST_EXTRA_ARGS
232+
233+
if [ -n "$CACHE_HIT_GOCACHE" ]; then
234+
echo Trimming Go cache
235+
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -not -newer build/cache/_cache_sentinel -delete
236+
fi
229237
230238
smoketests:
231239
strategy:
@@ -308,35 +316,40 @@ jobs:
308316
go-version: ${{ env.GO_VERSION }}
309317

310318
- name: Cache embedded binaries
319+
id: cache-embedded-bins
311320
uses: actions/cache@v4
312321
with:
313-
key: ${{ runner.os }}-embedded-bins-arm-${{ hashFiles('**/embedded-bins/**/*') }}
314-
path: |
315-
.bins.linux.stamp
316-
embedded-bins/staging/linux/bin/
317-
embedded-bins/Makefile.variables
322+
key: "build-k0s-linux-arm-embedded-bins-${{ hashFiles('embedded-bins/**/*') }}"
323+
path: embedded-bins/staging/linux/bin/
318324

319-
- name: Cache GOCACHE
325+
- name: Cache Go cache
326+
id: cache-gocache
320327
uses: actions/cache@v4
321328
with:
322-
key: ${{ runner.os }}-smoketest-arm-gocache-arm-${{ github.ref_name }}-${{ github.sha }}
323-
restore-keys: |
324-
${{ runner.os }}-smoketest-arm-gocache-arm-${{ github.ref_name }}-
325-
path: |
326-
build/cache/go/build
329+
key: "build-k0s-linux-arm-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
330+
restore-keys: "build-k0s-linux-arm-gocache-go${{ env.GO_VERSION }}-"
331+
path: build/cache/go/build
327332

328-
- name: Cache GOMODCACHE
329-
uses: actions/cache@v4
330-
with:
331-
key: ${{ runner.os }}-smoketest-arm-gomodcache-arm-${{ hashFiles('go.sum') }}
332-
path: |
333-
build/cache/go/mod
333+
- name: Prepare Go cache
334+
if: steps.cache-gocache.outputs.cache-hit
335+
run: |
336+
touch -t "$(TZ=UTC+24 date +%Y%m%d%H%M.%S)" build/cache/_cache_sentinel
337+
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -exec touch -r build/cache/_cache_sentinel {} +
334338
335339
- name: Build
340+
env:
341+
EMBEDDED_BINS_CACHED: "${{ steps.cache-embedded-bins.outputs.cache-hit }}"
336342
run: |
343+
gh --version || echo No gh installed
344+
make .k0sbuild.docker-image.k0s
345+
touch go.sum
346+
if [ "$EMBEDDED_BINS_CACHED" == true ]; then
347+
make --touch .bins.linux.stamp
348+
fi
337349
make bindata
338350
make --touch codegen
339351
make build
352+
echo "k0s binary size: **$(du -sh k0s | cut -f1)**" >>$GITHUB_STEP_SUMMARY
340353
341354
- name: Upload compiled executable
342355
uses: actions/upload-artifact@v4
@@ -369,6 +382,11 @@ jobs:
369382
name: airgap-image-bundle-linux-arm.tar
370383
path: airgap-image-bundle-linux-arm.tar
371384

385+
- name: Trim Go cache
386+
if: steps.cache-gocache.outputs.cache-hit
387+
run: |
388+
find build/cache/go/build -type f \( -name '*-a' -o -name '*-d' \) -not -newer build/cache/_cache_sentinel -delete
389+
372390
# TODO We probably want to separate the smoketest into a separate callable workflow which we can call from the build step
373391
# This way we could actually fully parallelize the build and smoketest steps. Currently we are limited by the fact that
374392
# smoke-test step only start after both arm and armv7 builds have finished.

.github/workflows/lint.yaml

Lines changed: 30 additions & 25 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,26 +70,33 @@ jobs:
6770
go-version: ${{ env.GO_VERSION }}
6871
cache: false
6972

70-
- name: "Cache :: golangci-lint"
73+
- name: Cache golangci-lint cache
74+
id: cache-golangci
7175
uses: actions/cache@v4
7276
with:
73-
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 }}"
7478
restore-keys: |
75-
lint-${{ matrix.target-os }}-amd64-golangci-${{ github.ref_name }}-
76-
lint-${{ matrix.target-os }}-amd64-golangci-main-
79+
lint-${{ matrix.target-os }}-amd64-golangci-${{ env.GOLANGCI_LINT_VERSION }}-go-${{ env.GO_VERSION }}-
7780
path: |
7881
build/cache/go/build
7982
build/cache/golangci-lint
8083
81-
- name: "Cache :: GOMODCACHE"
82-
uses: actions/cache/restore@v4
83-
with:
84-
key: build-k0s-gomodcache-${{ hashFiles('go.sum') }}
85-
path: build/cache/go/mod
86-
enableCrossOsArchive: true
87-
8884
- name: Run linter
89-
run: make lint-go $MAKE_EXTRA_ARGS
85+
env:
86+
CACHE_HIT_GOLANGCI: "${{ steps.cache-golangci.outputs.cache-hit }}"
87+
run: |
88+
if [ -n "$CACHE_HIT_GOLANGCI" ]; then
89+
echo Preparing golangci-lint cache
90+
touch -t "$(TZ=UTC+24 date +%Y%m%d%H%M.%S)" build/cache/_cache_sentinel
91+
find build/cache/go/build build/cache/golangci-lint -type f \( -name '*-a' -o -name '*-d' \) -exec touch -r build/cache/_cache_sentinel {} +
92+
fi
93+
94+
make lint-go $MAKE_EXTRA_ARGS
95+
96+
if [ -n "$CACHE_HIT_GOLANGCI" ]; then
97+
echo Trimming golangci-lint cache
98+
find build/cache/go/build build/cache/golangci-lint -type f \( -name '*-a' -o -name '*-d' \) -not -newer build/cache/_cache_sentinel -delete
99+
fi
90100
91101
lint-codegen:
92102
name: Lint generated code
@@ -95,23 +105,18 @@ jobs:
95105
- uses: actions/checkout@v4
96106
with:
97107
fetch-depth: 0
108+
preserve-credentials: false
98109

99-
- name: "Cache :: GOCACHE"
100-
uses: actions/cache/restore@v4
101-
with:
102-
key: build-k0s-linux-amd64-gocache-${{ github.ref_name }}-${{ github.sha }}
103-
restore-keys: |
104-
build-k0s-linux-amd64-gocache-${{ github.ref_name }}-
105-
build-k0s-linux-amd64-gocache-main-
106-
path: |
107-
build/cache/go/build
110+
- name: Prepare build environment
111+
run: .github/workflows/prepare-build-env.sh
108112

109-
- name: "Cache :: GOMODCACHE"
113+
- name: Restore Go cache
110114
uses: actions/cache/restore@v4
111115
with:
112-
key: build-k0s-gomodcache-${{ hashFiles('go.sum') }}
113-
path: build/cache/go/mod
114-
enableCrossOsArchive: true
116+
key: "build-k0s-linux-amd64-gocache-go${{ env.GO_VERSION }}-${{ github.sha }}"
117+
restore-keys: |
118+
build-k0s-linux-amd64-gocache-go${{ env.GO_VERSION }}-
119+
path: build/cache/go/build
115120

116121
- name: Check go.mod/go.sum to be consistent
117122
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)