Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions .github/actions/download.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,67 @@
# Functions:
# - Download all referenced native and cross source files for packages.
# - Download all referenced python wheels needed to build.
# - Use the “download-all” target when a package has multiple (arch-specific) files.
# - Use the "download-all" target when a package has multiple (arch-specific) files.
# - Retry download if checksum fails (cached file may be outdated).

set -euo pipefail
# Report any error (with line and package context) and exit.
trap 'echo "::error::Error on line ${LINENO} while processing ${current:-<none>}"; exit 1' ERR
trap 'echo "::error::Error on line ${LINENO} while processing ${current:-unknown}"; exit 1' ERR

# Ensure required tooling is present.
command -v make >/dev/null 2>&1 || { echo "::error::make is not installed"; exit 1; }

# Function to download and verify with retry on checksum failure
download_with_retry() {
local target_dir="$1"
local target_name="$2"
local result=0
local output=""

echo " -> ${target_dir}: ${target_name} then checksum"

# First attempt
set +e
output=$(make -C "${target_dir}" ${target_name} checksum 2>&1)
result=$?
set -e

# Display output
echo "$output"

if [ $result -eq 0 ]; then
return 0
fi

# Check if checksum failure occurred by looking for .wrong rename in output
# Use escaped dot to match literal .wrong extension
if echo "$output" | grep -q 'Renamed as .*\.wrong'; then
echo " -> Checksum failed due to outdated cached file, retrying download for ${target_dir}..."

# Retry download and checksum
set +e
make -C "${target_dir}" ${target_name} checksum
result=$?
set -e

if [ $result -eq 0 ]; then
return 0
fi
fi

# Both attempts failed or failure was not due to cached file
echo "::error::Download/checksum failed for ${target_dir}"
return 1
}

echo ""
# 1) Download native / cross-compiled sources.
if [ -z "${DOWNLOAD_PACKAGES:-}" ]; then
echo "===> No packages to download. <==="
else
echo "===> Downloading packages: ${DOWNLOAD_PACKAGES}"
for current in ${DOWNLOAD_PACKAGES}; do
echo " → ${current}: download-all then checksum"
# download-all pulls down all sources; checksum verifies them.
make -C "${current}" download-all checksum
download_with_retry "${current}" "download-all"
done
fi

Expand All @@ -37,8 +79,8 @@ else
echo "===> Downloading wheels: ${build_pkgs[*]}"
for pkg in "${build_pkgs[@]}"; do
current="spk/${pkg}"
echo " ${current}: download-wheels"
# download-wheels grabs all needed .whl files.
echo " -> ${current}: download-wheels"
# Wheels don't have checksum verification, so no retry needed
make -C "${current}" download-wheels
done
fi
Expand Down
67 changes: 57 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ jobs:
prepare:
name: Prepare for Build
runs-on: ubuntu-latest
# provide results to other jobs
outputs:
arch_packages: ${{ steps.dependencies.outputs.arch_packages }}
noarch_packages: ${{ steps.dependencies.outputs.noarch_packages }}
has_min_dsm72_packages: ${{ steps.dependencies.outputs.has_min_dsm72_packages }}
distrib_hash: ${{ steps.distrib-hash.outputs.hash }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
Expand Down Expand Up @@ -109,19 +109,62 @@ jobs:
GH_DEPENDENCY_FOLDERS: ${{ steps.getchanges_push.outputs.dependency_folders }} ${{ steps.getchanges_pr.outputs.dependency_folders }}
USER_SPK_TO_BUILD: ${{ github.event.inputs.package }}

- name: Cache downloaded files
uses: actions/cache@v4
- name: Restore distrib cache
id: cache-restore
uses: actions/cache/restore@v4
with:
path: distrib
# use run_id in key to cache within workflow only.
key: distrib-${{ github.run_id }}
# Use a placeholder key that will never match for the exact key,
# forcing GitHub to use restore-keys to find the best available cache
key: distrib-placeholder-${{ github.run_id }}
restore-keys: |
distrib-

- name: Download source files
run: ./.github/actions/download.sh
env:
DOWNLOAD_PACKAGES: ${{ steps.dependencies.outputs.download_packages }}
ARCH_PACKAGES: ${{ needs.prepare.outputs.arch_packages }}
NOARCH_PACKAGES: ${{ needs.prepare.outputs.noarch_packages }}
ARCH_PACKAGES: ${{ steps.dependencies.outputs.arch_packages }}
NOARCH_PACKAGES: ${{ steps.dependencies.outputs.noarch_packages }}

- name: Compute distrib hash
id: distrib-hash
run: |
# Compute a hash based on file paths and sizes (not content) for performance.
# This is fast even with thousands of files since we don't read file contents.
# Including file size ensures that if a corrupted file (.wrong) is replaced
# by a fresh download with different size, the hash will change.
# Format: "path size" per line, sorted for reproducibility, then hashed.
if [ -d "distrib" ] && [ -n "$(ls -A distrib 2>/dev/null)" ]; then
HASH=$(find distrib -type f -printf '%p %s\n' | sort | sha256sum | cut -d' ' -f1)
else
HASH="empty"
fi
echo "hash=$HASH" >> $GITHUB_OUTPUT
echo "Distrib cache hash: $HASH"

- name: Check if cache already exists
id: cache-check
run: |
# Check if a cache with this exact hash already exists to avoid duplication.
# We search for the exact key pattern to see if this content was already cached.
CACHE_KEY="distrib-${{ steps.distrib-hash.outputs.hash }}"
if gh cache list --json key | jq -e --arg key "$CACHE_KEY" '.[] | select(.key == $key)' > /dev/null 2>&1; then
echo "Cache with key $CACHE_KEY already exists, skipping save"
echo "save_cache=false" >> $GITHUB_OUTPUT
else
echo "New cache content detected, will save with key: $CACHE_KEY"
echo "save_cache=true" >> $GITHUB_OUTPUT
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Save distrib cache
if: steps.cache-check.outputs.save_cache == 'true'
uses: actions/cache/save@v4
with:
path: distrib
key: distrib-${{ steps.distrib-hash.outputs.hash }}

set-defaults:
name: Set Defaults
Expand Down Expand Up @@ -256,11 +299,15 @@ jobs:
path: toolchain/*/work
key: toolchain-${{ matrix.arch }}-v3-${{ hashFiles(format('toolchain/syno-{0}/digests',matrix.arch)) }}

- name: Use cache of downloaded files
uses: actions/cache@v4
- name: Restore distrib cache
uses: actions/cache/restore@v4
with:
path: distrib
key: distrib-${{ github.run_id }}
# Use a placeholder key that will never match for the exact key,
# forcing GitHub to use restore-keys to find the best available cache
key: distrib-placeholder-${{ github.run_id }}
restore-keys: |
distrib-

- name: Build Package (based on changed files)
# We don't want to stop the build on errors.
Expand Down
Loading