@@ -37,14 +37,29 @@ jobs:
3737 if : github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true)
3838 runs-on : ubuntu-latest
3939 outputs :
40- changed_recipes : ${{ steps.detect .outputs.changed_recipes }}
41- has_changes : ${{ steps.detect .outputs.has_changes }}
40+ changed_recipes : ${{ steps.filter .outputs.recipes_to_build }}
41+ has_changes : ${{ steps.filter .outputs.has_changes }}
4242 steps :
4343 - name : Checkout repository
4444 uses : actions/checkout@v4
4545 with :
4646 fetch-depth : 2
4747
48+ - name : Download tools
49+ run : |
50+ curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/latest/sbuild-linter-x86_64-linux" \
51+ -o /usr/local/bin/sbuild-linter && chmod +x /usr/local/bin/sbuild-linter || true
52+ curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/latest/sbuild-cache-x86_64-linux" \
53+ -o /usr/local/bin/sbuild-cache && chmod +x /usr/local/bin/sbuild-cache || true
54+
55+ - name : Download build cache
56+ continue-on-error : true
57+ env :
58+ GH_TOKEN : ${{ github.token }}
59+ run : |
60+ gh release download build-cache -p build_cache.sdb -D /tmp/ --repo "${{ github.repository }}" || \
61+ sbuild-cache --cache /tmp/build_cache.sdb init 2>/dev/null || true
62+
4863 - name : Detect changed recipes
4964 id : detect
5065 run : |
@@ -87,12 +102,59 @@ jobs:
87102
88103 # Output results
89104 RECIPE_COUNT=$(echo "$CHANGED_RECIPES" | jq 'length')
90- echo "Found $RECIPE_COUNT recipes to build "
105+ echo "Found $RECIPE_COUNT changed recipes "
91106 echo "$CHANGED_RECIPES" | jq .
92107
93- # Save to outputs
94108 echo "changed_recipes=$(echo "$CHANGED_RECIPES" | jq -c .)" >> $GITHUB_OUTPUT
95109
110+ - name : Filter already-built recipes
111+ id : filter
112+ run : |
113+ CHANGED_RECIPES='${{ steps.detect.outputs.changed_recipes }}'
114+ FORCE_REBUILD="${{ inputs.force_rebuild }}"
115+ RECIPES_TO_BUILD="[]"
116+ SKIPPED=0
117+
118+ echo "$CHANGED_RECIPES" | jq -c '.[]' | while read -r recipe; do
119+ path=$(echo "$recipe" | jq -r '.path')
120+ pkg_name=$(basename "$(dirname "$path")")
121+
122+ # Skip cache check if force rebuild
123+ if [ "$FORCE_REBUILD" == "true" ]; then
124+ echo "$recipe"
125+ continue
126+ fi
127+
128+ # Compute current recipe hash
129+ if [ -f "$path" ] && command -v sbuild-linter &>/dev/null; then
130+ current_hash=$(sbuild-linter hash --exclude-version "$path" 2>/dev/null || sha256sum "$path" | cut -d' ' -f1)
131+ else
132+ current_hash=$(sha256sum "$path" 2>/dev/null | cut -d' ' -f1 || echo "unknown")
133+ fi
134+
135+ # Check if already built with same hash
136+ if [ -f "/tmp/build_cache.sdb" ] && command -v sbuild-cache &>/dev/null; then
137+ cached_info=$(sbuild-cache --cache /tmp/build_cache.sdb get --package "$pkg_name" --json 2>/dev/null || echo "")
138+ cached_hash=$(echo "$cached_info" | jq -r '.recipe_hash // ""' 2>/dev/null || echo "")
139+ cached_status=$(echo "$cached_info" | jq -r '.last_build_status // ""' 2>/dev/null || echo "")
140+
141+ if [ "$cached_hash" == "$current_hash" ] && [ "$cached_status" == "success" ]; then
142+ echo "::notice::Skipping $pkg_name - already built with same hash"
143+ continue
144+ fi
145+ fi
146+
147+ echo "$recipe"
148+ done | jq -s '.' > /tmp/recipes_to_build.json
149+
150+ RECIPES_TO_BUILD=$(cat /tmp/recipes_to_build.json)
151+ RECIPE_COUNT=$(echo "$RECIPES_TO_BUILD" | jq 'length')
152+
153+ echo "Recipes to build after filtering: $RECIPE_COUNT"
154+ echo "$RECIPES_TO_BUILD" | jq .
155+
156+ echo "recipes_to_build=$(echo "$RECIPES_TO_BUILD" | jq -c .)" >> $GITHUB_OUTPUT
157+
96158 if [ "$RECIPE_COUNT" -gt 0 ]; then
97159 echo "has_changes=true" >> $GITHUB_OUTPUT
98160 else
@@ -122,18 +184,22 @@ jobs:
122184 if : always() && needs.detect-changes.outputs.has_changes == 'true'
123185 runs-on : ubuntu-latest
124186 steps :
125- - name : Download sbuild-cache
187+ - name : Checkout repository
188+ uses : actions/checkout@v4
189+
190+ - name : Download tools
126191 run : |
127192 curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/latest/sbuild-cache-x86_64-linux" \
128- -o /usr/local/bin/sbuild-cache || exit 0
129- chmod +x /usr/local/bin/sbuild-cache
193+ -o /usr/local/bin/sbuild-cache && chmod +x /usr/local/bin/sbuild-cache || true
194+ curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/latest/sbuild-linter-x86_64-linux" \
195+ -o /usr/local/bin/sbuild-linter && chmod +x /usr/local/bin/sbuild-linter || true
130196
131197 - name : Download existing cache
132198 continue-on-error : true
133199 env :
134200 GH_TOKEN : ${{ github.token }}
135201 run : |
136- gh release download cache-latest -p build_cache.sdb -D /tmp/ --repo "${{ github.repository }}" || \
202+ gh release download build-cache -p build_cache.sdb -D /tmp/ --repo "${{ github.repository }}" || \
137203 sbuild-cache --cache /tmp/build_cache.sdb init
138204
139205 - name : Download build status artifacts
@@ -154,8 +220,21 @@ jobs:
154220 # Extract package name from path (e.g., binaries/hello/static.yaml -> hello)
155221 pkg_name=$(basename "$(dirname "$path")")
156222
223+ # Extract version from recipe's pkgver field
224+ pkg_version="unknown"
225+ if [ -f "$path" ]; then
226+ pkg_version=$(grep -E "^pkgver:" "$path" | head -1 | sed 's/pkgver:[[:space:]]*//; s/^["'"'"']//; s/["'"'"']$//' || echo "unknown")
227+ [ -z "$pkg_version" ] && pkg_version="unknown"
228+ fi
229+
230+ # Compute recipe hash for cache
231+ if [ -f "$path" ] && command -v sbuild-linter &>/dev/null; then
232+ recipe_hash=$(sbuild-linter hash --exclude-version "$path" 2>/dev/null || sha256sum "$path" | cut -d' ' -f1)
233+ else
234+ recipe_hash=$(sha256sum "$path" 2>/dev/null | cut -d' ' -f1 || echo "unknown")
235+ fi
236+
157237 # Find build status from artifacts
158- # The recipe_url in the status JSON contains the path
159238 status="unknown"
160239
161240 if [ -d "/tmp/build-statuses" ]; then
@@ -165,7 +244,6 @@ jobs:
165244 recipe_url=$(jq -r '.recipe_url // ""' "$status_file" 2>/dev/null || echo "")
166245 if echo "$recipe_url" | grep -q "$path"; then
167246 file_status=$(jq -r '.status // "unknown"' "$status_file" 2>/dev/null || echo "unknown")
168- # If any host failed, mark as failure
169247 if [ "$file_status" = "failure" ]; then
170248 status="failure"
171249 break
@@ -181,11 +259,12 @@ jobs:
181259 status="${{ needs.build.result }}"
182260 fi
183261
184- echo "Package: $pkg_name, Status: $status"
262+ echo "Package: $pkg_name, Version: $pkg_version, Hash: ${recipe_hash:0:16}..., Status: $status"
185263
186264 sbuild-cache --cache /tmp/build_cache.sdb update \
187265 --package "$pkg_name" \
188- --version "latest" \
266+ --version "$pkg_version" \
267+ --hash "$recipe_hash" \
189268 --status "$status" || true
190269 done
191270
@@ -200,10 +279,11 @@ jobs:
200279 GH_TOKEN : ${{ github.token }}
201280 run : |
202281 if [ -f "/tmp/build_cache.sdb" ]; then
203- gh release upload cache-latest /tmp/build_cache.sdb --clobber --repo "${{ github.repository }}" || {
204- gh release create cache-latest \
282+ gh release upload build-cache /tmp/build_cache.sdb --clobber --repo "${{ github.repository }}" || {
283+ gh release create build-cache \
205284 --title "Build Cache" \
206285 --notes "Build cache for CI" \
286+ --prerelease \
207287 --repo "${{ github.repository }}" \
208288 /tmp/build_cache.sdb
209289 }
0 commit comments