|
| 1 | +name: 'Install apt dependencies' |
| 2 | +description: 'Install apt packages with retry logic and caching' |
| 3 | +inputs: |
| 4 | + packages: |
| 5 | + description: 'Space-separated list of apt packages to install' |
| 6 | + required: true |
| 7 | + retries: |
| 8 | + description: 'Number of retry attempts' |
| 9 | + required: false |
| 10 | + default: '3' |
| 11 | + retry-delay: |
| 12 | + description: 'Initial delay between retries (seconds, doubles each attempt)' |
| 13 | + required: false |
| 14 | + default: '5' |
| 15 | + no-install-recommends: |
| 16 | + description: 'Pass --no-install-recommends to apt-get install' |
| 17 | + required: false |
| 18 | + default: 'false' |
| 19 | + cache: |
| 20 | + description: 'Cache apt archives (disable for dynamic package names)' |
| 21 | + required: false |
| 22 | + default: 'true' |
| 23 | +runs: |
| 24 | + using: 'composite' |
| 25 | + steps: |
| 26 | + - name: Compute cache key |
| 27 | + if: inputs.cache == 'true' |
| 28 | + id: cache-key |
| 29 | + shell: bash |
| 30 | + run: | |
| 31 | + SORTED_PKGS=$(echo "${{ inputs.packages }}" | tr ' ' '\n' | sort -u | tr '\n' ' ') |
| 32 | + PKG_HASH=$(echo "$SORTED_PKGS" | sha256sum | cut -d' ' -f1 | head -c 16) |
| 33 | + OS_VERSION=$(lsb_release -rs 2>/dev/null || echo "unknown") |
| 34 | + echo "key=apt-deps-${{ runner.os }}-${{ runner.arch }}-${OS_VERSION}-${PKG_HASH}" >> $GITHUB_OUTPUT |
| 35 | + echo "restore-key=apt-deps-${{ runner.os }}-${{ runner.arch }}-${OS_VERSION}-" >> $GITHUB_OUTPUT |
| 36 | +
|
| 37 | + - name: Restore apt cache |
| 38 | + if: inputs.cache == 'true' |
| 39 | + id: apt-cache |
| 40 | + uses: actions/cache/restore@v4 |
| 41 | + with: |
| 42 | + path: ~/apt-cache |
| 43 | + key: ${{ steps.cache-key.outputs.key }} |
| 44 | + restore-keys: ${{ steps.cache-key.outputs.restore-key }} |
| 45 | + |
| 46 | + - name: Pre-seed apt archives from cache |
| 47 | + if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit == 'true' |
| 48 | + shell: bash |
| 49 | + run: | |
| 50 | + if [ -d ~/apt-cache ] && ls ~/apt-cache/*.deb >/dev/null 2>&1; then |
| 51 | + sudo cp ~/apt-cache/*.deb /var/cache/apt/archives/ |
| 52 | + echo "Restored $(ls ~/apt-cache/*.deb | wc -l) cached .deb files" |
| 53 | + fi |
| 54 | +
|
| 55 | + - name: Install packages |
| 56 | + shell: bash |
| 57 | + run: | |
| 58 | + export DEBIAN_FRONTEND=noninteractive |
| 59 | + RETRIES=${{ inputs.retries }} |
| 60 | + DELAY=${{ inputs.retry-delay }} |
| 61 | + NO_REC="" |
| 62 | + if [ "${{ inputs.no-install-recommends }}" = "true" ]; then |
| 63 | + NO_REC="--no-install-recommends" |
| 64 | + fi |
| 65 | + for i in $(seq 1 $RETRIES); do |
| 66 | + if sudo apt-get update -q && \ |
| 67 | + sudo apt-get install -y $NO_REC ${{ inputs.packages }}; then |
| 68 | + exit 0 |
| 69 | + fi |
| 70 | + if [ "$i" -eq "$RETRIES" ]; then |
| 71 | + echo "::error::apt-get failed after $RETRIES attempts" |
| 72 | + exit 1 |
| 73 | + fi |
| 74 | + echo "::warning::apt-get failed (attempt $i/$RETRIES), retrying in ${DELAY}s..." |
| 75 | + sleep $DELAY |
| 76 | + DELAY=$((DELAY * 2)) |
| 77 | + done |
| 78 | +
|
| 79 | + - name: Collect .deb files for cache |
| 80 | + if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit != 'true' |
| 81 | + shell: bash |
| 82 | + run: | |
| 83 | + mkdir -p ~/apt-cache |
| 84 | + cp /var/cache/apt/archives/*.deb ~/apt-cache/ 2>/dev/null || true |
| 85 | + echo "Cached $(ls ~/apt-cache/*.deb 2>/dev/null | wc -l) .deb files" |
| 86 | +
|
| 87 | + - name: Save apt cache |
| 88 | + if: inputs.cache == 'true' && steps.apt-cache.outputs.cache-hit != 'true' |
| 89 | + uses: actions/cache/save@v4 |
| 90 | + with: |
| 91 | + path: ~/apt-cache |
| 92 | + key: ${{ steps.cache-key.outputs.key }} |
0 commit comments