Skip to content

Commit 892bc8a

Browse files
authored
chore: add binary caching (#408)
1 parent 58e1ed1 commit 892bc8a

File tree

3 files changed

+232
-33
lines changed

3 files changed

+232
-33
lines changed

.github/workflows/ci-base.yaml

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -96,38 +96,8 @@ jobs:
9696
run: echo "✅ Source generation skipped - no source changes detected"
9797

9898
- name: Verify source files exist
99-
run: |
100-
SOURCE_PATH="distributions/${{inputs.distribution}}/_build"
101-
if [ ${{ inputs.fips }} = "true" ]; then
102-
SOURCE_PATH="${SOURCE_PATH}-fips"
103-
fi
104-
if [ ! -d "$SOURCE_PATH" ]; then
105-
echo "❌ $SOURCE_PATH not found!"
106-
exit 1
107-
fi
108-
files=(
109-
"build.log" "components.go" "go.mod" "go.sum"
110-
"main_others.go" "main_windows.go" "main.go"
111-
)
112-
if [ ${{ inputs.fips }} = "true" ]; then
113-
files+=("fips.go")
114-
fi
115-
cd "$SOURCE_PATH"
116-
missing_files=()
117-
for file in "${files[@]}"; do
118-
if [ ! -f "$file" ]; then
119-
missing_files+=("$file")
120-
else
121-
echo "Found: $file"
122-
fi
123-
done
124-
if [ ${#missing_files[@]} -eq 0 ]; then
125-
echo "✅ All source files found!"
126-
else
127-
echo "❌ files not found: ${missing_files[*]}"
128-
exit 1
129-
fi
130-
99+
run: ./scripts/validate-source-files.sh -d ${{ inputs.distribution }} -f ${{ inputs.fips }}
100+
131101
- name: Login to Docker
132102
uses: docker/login-action@v3
133103
if: ${{ env.ACT }}
@@ -174,17 +144,42 @@ jobs:
174144
run: |
175145
if [ ${{ inputs.nightly }} = "true" ] && [ ${{ inputs.fips }} = "true" ]; then
176146
echo "goreleaser_args=--snapshot --clean --skip=publish,validate --timeout 2h --config .goreleaser-nightly-fips.yaml" >> $GITHUB_ENV
147+
echo "goreleaser_file=.goreleaser-nightly-fips.yaml" >> $GITHUB_ENV
177148
elif [ ${{ inputs.nightly }} = "true" ]; then
178149
echo "goreleaser_args=--snapshot --clean --skip=publish,validate --timeout 2h --config .goreleaser-nightly.yaml" >> $GITHUB_ENV
150+
echo "goreleaser_file=.goreleaser-nightly.yaml" >> $GITHUB_ENV
179151
elif [ ${{ inputs.fips }} = "true" ]; then
180152
echo "goreleaser_args=--snapshot --clean --skip=publish,validate --timeout 2h --config .goreleaser-fips.yaml" >> $GITHUB_ENV
153+
echo "goreleaser_file=.goreleaser-fips.yaml" >> $GITHUB_ENV
181154
elif [ ${{github.event.pull_request.user.login == 'dependabot[bot]' }} ]; then
182155
echo "goreleaser_args=--snapshot --clean --skip=publish,validate,sign --timeout 2h" >> $GITHUB_ENV
156+
echo "goreleaser_file=.goreleaser.yaml" >> $GITHUB_ENV
183157
else
184158
echo "goreleaser_args=--snapshot --clean --skip=publish,validate --timeout 2h" >> $GITHUB_ENV
159+
echo "goreleaser_file=.goreleaser.yaml" >> $GITHUB_ENV
185160
fi
186161
162+
- name: Generate binary cache key
163+
id: generate_binary_key
164+
run: |
165+
BINARY_HASH="${{ hashFiles(
166+
format('distributions/{0}/.goreleaser*.yaml', inputs.distribution),
167+
format('distributions/{0}/_build*/*', inputs.distribution)
168+
) }}"
169+
ARGS_HASH=$(echo "${{ env.goreleaser_args }}" | sha256sum | cut -d' ' -f1)
170+
echo binary_key=goreleaser-build-${{ inputs.distribution }}-${ARGS_HASH}-${BINARY_HASH} >> $GITHUB_OUTPUT
171+
172+
- name: Cache goreleaser build
173+
id: cache-goreleaser
174+
if: ${{ env.caching_enabled }}
175+
uses: actions/cache@v4
176+
with:
177+
path: |
178+
distributions/${{ inputs.distribution }}/dist
179+
key: ${{ steps.generate_binary_key.outputs.binary_key }}
180+
187181
- name: Build binaries & packages with GoReleaser
182+
if: steps.cache-goreleaser.outputs.cache-hit != 'true'
188183
id: goreleaser
189184
uses: goreleaser/goreleaser-action@v6
190185
env:
@@ -197,10 +192,24 @@ jobs:
197192
version: '2.11.2'
198193
args: ${{ env.goreleaser_args }}
199194
workdir: distributions/${{ inputs.distribution }}
195+
196+
- name: Skip GoReleaser build (cached)
197+
if: steps.cache-goreleaser.outputs.cache-hit == 'true'
198+
run: echo "✅ GoReleaser build skipped - using cached binaries"
200199

200+
- name: Validate GoReleaser build
201+
run: ./scripts/validate-goreleaser-build.sh -d ${{ inputs.distribution }}
202+
201203
- name: Extract relevant metadata
202204
run: |
203-
VERSION=$(echo '${{ steps.goreleaser.outputs.metadata }}' | jq -r '.version')
205+
if [ "${{ steps.cache-goreleaser.outputs.cache-hit }}" = "true" ]; then
206+
VERSION=$(jq -r '.version' distributions/${{ inputs.distribution }}/dist/metadata.json)
207+
echo "Using cached version: $VERSION"
208+
else
209+
# Extract from fresh GoReleaser build
210+
VERSION=$(echo '${{ steps.goreleaser.outputs.metadata }}' | jq -r '.version')
211+
echo "Using fresh build version: $VERSION"
212+
fi
204213
ARCH=$(echo '${{ runner.arch }}' | sed 's/X/amd/g')
205214
ARCH=${ARCH@L}
206215
echo "version=$VERSION" >> $GITHUB_ENV
@@ -215,6 +224,45 @@ jobs:
215224
echo "image_tag=$VERSION-$ARCH" >> $GITHUB_ENV
216225
fi
217226
227+
- name: Copy GoReleaser binary to Docker context
228+
id: copy-binary
229+
if: steps.cache-goreleaser.outputs.cache-hit == 'true'
230+
run: |
231+
cd distributions/${{ inputs.distribution }}
232+
BINARY_PATH="$(find dist -name "${{ inputs.distribution }}*_linux_${{ env.arch }}*" -type d)/${{ inputs.distribution }}"
233+
if [ ${{ inputs.fips }} = "true" ]; then
234+
BINARY_PATH+="-fips"
235+
fi
236+
if [ ! -f "$BINARY_PATH" ]; then
237+
echo "❌ Error: Binary not found at $BINARY_PATH"
238+
find dist -name "*${{ inputs.distribution }}*" -type f
239+
exit 1
240+
fi
241+
# move dockerfile dependencies to .tmp for easy cleanup when running in Act
242+
BINARY_TMP="${{ runner.temp }}/docker/${{ inputs.distribution }}"
243+
if [ ${{ inputs.fips }} = "true" ]; then
244+
BINARY_TMP+="-fips"
245+
fi
246+
mkdir -p ${BINARY_TMP}
247+
cp "$BINARY_PATH" "${BINARY_TMP}/${{ inputs.distribution }}"
248+
cp Dockerfile ${BINARY_TMP}
249+
for file in $(yq ".dockers[] | select(.goarch == \"${{ env.arch }}\") | .extra_files[]" ${{ env.goreleaser_file }}); do
250+
cp "${file}" ${BINARY_TMP}
251+
done
252+
echo "✅ Binary copied: $(ls -la ${BINARY_TMP})"
253+
echo "binary_tmp=${BINARY_TMP}" >> $GITHUB_OUTPUT
254+
255+
- name: Build and load Docker image
256+
uses: docker/build-push-action@v5
257+
if: steps.cache-goreleaser.outputs.cache-hit == 'true'
258+
with:
259+
context: ${{ steps.copy-binary.outputs.binary_tmp }}
260+
platforms: linux/${{ env.arch }}
261+
push: false
262+
load: true
263+
tags: |
264+
${{ secrets.registry }}/${{ inputs.distribution }}:${{ env.image_tag }}
265+
218266
- name: Validate Usage of BoringCrypto
219267
if: inputs.fips
220268
run: |
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/bin/bash
2+
# Script to validate a goreleaser distribution's dist file
3+
set -e
4+
5+
while getopts d: flag
6+
do
7+
case "${flag}" in
8+
d) distro=${OPTARG};;
9+
*) exit 1;;
10+
esac
11+
done
12+
13+
if [ -z ${distro} ]; then
14+
echo "Distribution not provided. Please provide a distribution with -d."
15+
exit 1
16+
fi
17+
18+
cd "distributions/${distro}"
19+
if [ ! -d "dist" ]; then
20+
echo "❌ dist directory not found!"
21+
exit 1
22+
fi
23+
24+
echo "📋 Verifying metadata files exist..."
25+
files=("dist/artifacts.json" "dist/metadata.json")
26+
missing_files=()
27+
for file in "${files[@]}"; do
28+
if [ ! -f "$file" ]; then
29+
missing_files+=("$file")
30+
else
31+
echo "Found: $file"
32+
fi
33+
done
34+
if [ ${#missing_files[@]} -ne 0 ]; then
35+
echo "❌ files not found: ${missing_files[*]}"
36+
exit 1
37+
else
38+
echo "✅ All common build files found!"
39+
fi
40+
41+
echo "📋 Verifying Binaries exist..."
42+
binaries=$( jq -r '.[] | select(.type == "Binary") | .path' dist/artifacts.json )
43+
if [ -z "${binaries}" ]; then
44+
echo "❌ No binaries found in artifacts.json"
45+
exit 1
46+
else
47+
for binary in $binaries; do
48+
if [ ! -f "${binary}" ]; then
49+
echo "${binary} not found!"
50+
exit 1
51+
else
52+
echo "Found: ${binary}"
53+
fi
54+
done
55+
fi
56+
echo "✅ All binaries found!"
57+
58+
echo "📋 Validating Archives and Packages..."
59+
artifacts=$( jq -r '.[] | select(.type == "Archive" or .type == "Linux Package") | .path' dist/artifacts.json )
60+
if [ -z "${artifacts}" ]; then
61+
echo "⚠️ No archives or packages found in artifacts.json"
62+
else
63+
for artifact in $artifacts; do
64+
echo "Validating ${artifact}"
65+
# Verify the artifact file exists
66+
if [ ! -f "${artifact}" ]; then
67+
echo "${artifact} not found!"
68+
exit 1
69+
else
70+
echo " Found artifact: ${artifact}"
71+
fi
72+
# Search for the corresponding checksum file and verify it exists
73+
sum_file=$( jq -r ".[] | select(.type == \"Checksum\" and .extra.ChecksumOf == \"${artifact}\") | .path" dist/artifacts.json )
74+
if [ -z "${sum_file}" ]; then
75+
echo "❌ Checksum not defined for ${artifact} in artifacts.json"
76+
exit 1
77+
fi
78+
if [ ! -f "${sum_file}" ]; then
79+
echo "${sum_file} not found!"
80+
exit 1
81+
else
82+
echo " Found checksum: ${sum_file}"
83+
fi
84+
# Compare checksums to ensure file integrity
85+
artifact_sum=$(sha256sum ${artifact} | cut -d' ' -f1)
86+
expected_sum=$(cat ${sum_file})
87+
if [ "${artifact_sum}" != "${expected_sum}" ]; then
88+
echo "❌ Checksums do not match!"
89+
echo "Checksum: ${artifact_sum}"
90+
echo "Expected: ${expected_sum}"
91+
exit 1
92+
else
93+
echo " Checksum validated"
94+
fi
95+
done
96+
echo "✅ Archives and Packages validated!"
97+
fi

scripts/validate-source-files.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/bin/bash
2+
# Simple script to validate whether a distribution's OCB-generated source files exist.
3+
set -e
4+
5+
# default values
6+
fips=false
7+
8+
while getopts d:f: flag
9+
do
10+
case "${flag}" in
11+
d) distro=${OPTARG};;
12+
f) fips=${OPTARG};;
13+
*) exit 1;;
14+
esac
15+
done
16+
17+
if [ -z ${distro} ]; then
18+
echo "Distribution not provided. Please provide a distribution with -d."
19+
exit 1
20+
fi
21+
22+
path="distributions/${distro}/_build"
23+
if [ ${fips} = true ]; then
24+
path="${path}-fips"
25+
fi
26+
if [ ! -d "$path" ]; then
27+
echo "$path not found!"
28+
exit 1
29+
fi
30+
cd "$path"
31+
32+
files=(
33+
"build.log" "components.go" "go.mod" "go.sum"
34+
"main_others.go" "main_windows.go" "main.go"
35+
)
36+
if [ ${fips} = true ]; then
37+
files+=("fips.go")
38+
fi
39+
missing_files=()
40+
41+
for file in "${files[@]}"; do
42+
if [ ! -f "$file" ]; then
43+
missing_files+=("$file")
44+
else
45+
echo "Found: $file"
46+
fi
47+
done
48+
49+
if [ ${#missing_files[@]} -eq 0 ]; then
50+
echo "✅ All source files found!"
51+
else
52+
echo "❌ files not found: ${missing_files[*]}"
53+
exit 1
54+
fi

0 commit comments

Comments
 (0)