Files

208 lines
9.6 KiB
YAML

name: Build Full Installer ISO/DMG image
on:
workflow_dispatch:
inputs:
macos_version:
description: "Choose a macOS version to build."
required: true
type: choice
options:
- ''
- 'Tahoe'
- 'Sequoia'
- 'Sonoma'
- 'Ventura'
- 'Monterey'
- 'Big Sur'
- 'Catalina'
- 'Mojave'
- 'High Sierra'
- 'Sierra'
- 'El Capitan'
- 'Yosemite'
- 'Mavericks'
- 'Mountain Lion'
- 'Lion'
image_format:
description: "Choose 'iso' for virtual machines, 'dmg' for flash to USB drive."
required: true
type: choice
options:
- ''
- 'iso'
- 'dmg'
jobs:
preflight:
if: ${{ inputs.macos_version != '' && inputs.image_format != '' }}
runs-on: ubuntu-slim
timeout-minutes: 5
outputs:
_build: ${{ steps.check.outputs._build }}
steps:
- name: Preflight
id: check
run: |
# Third time's the charm
if [ ${{ github.run_attempt }} -ge 3 ]; then
echo "_build=true" >> $GITHUB_OUTPUT
exit 0
fi
FOUND=false
PAGE=1
while [ $PAGE -le 50 ]; do
DATA=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/LongQT-sea/macos-iso-builder/stargazers?per_page=100&page=${PAGE}")
echo "$DATA" | jq -e --arg user "$GITHUB_ACTOR" 'any(.[]; .login == $user)' > /dev/null && FOUND=true && break
[ "$(echo "$DATA" | grep -c '"login"')" -lt 100 ] && break
PAGE=$((PAGE + 1))
done
if [ "$FOUND" = "false" ]; then
if [ ${{ github.run_attempt }} -eq 1 ]; then
echo "## Before you build — check if someone already did it for you :point_down:" >> $GITHUB_STEP_SUMMARY
echo "Browse the **[Recent Forks List](https://github.com/LongQT-sea/macos-iso-builder/releases/latest)** — someone may have already built the macOS version you need." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> [!TIP]" >> $GITHUB_STEP_SUMMARY
echo "> Too lazy to browse? Click **Re-run all jobs** and I'll search recent forks for you automatically. :mag:" >> $GITHUB_STEP_SUMMARY
echo "> Otherwise, star :star: [LongQT-sea/macos-iso-builder](https://github.com/LongQT-sea/macos-iso-builder) to go straight to build next time." >> $GITHUB_STEP_SUMMARY
echo "> <br>![star](https://raw.githubusercontent.com/LongQT-sea/macos-iso-builder/main/.github/star.jpg)" >> $GITHUB_STEP_SUMMARY
else
VERSION_NORMALIZED=$(echo "${{ inputs.macos_version }}" | tr ' ' '_')
FORMAT="${{ inputs.image_format }}"
FOUND_RUN_URL=""
FOUND_ARTIFACT_NAME=""
PAST_15_DAYS=$(date -u -d '15 days ago' +%Y-%m-%dT%H:%M:%SZ)
PAGE=1
while true; do
FORKS=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/LongQT-sea/macos-iso-builder/forks?sort=newest&per_page=100&page=${PAGE}")
[ "$(echo "$FORKS" | jq 'length')" -eq 0 ] && break
RECENT=$(echo "$FORKS" | jq -r --arg date "$PAST_15_DAYS" \
'.[] | select(.created_at > $date) | .full_name')
[ -z "$RECENT" ] && break
while IFS= read -r fork_full_name; do
[ -z "$fork_full_name" ] && continue
RUN_ID=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${fork_full_name}/actions/runs?status=success&per_page=10" \
| jq -r --arg date "$PAST_15_DAYS" '
.workflow_runs[]
| select(.name == "Build Full Installer ISO/DMG image")
| select(.created_at > $date)
| .id' | head -1)
[ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ] && continue
MATCH=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${fork_full_name}/actions/runs/${RUN_ID}/artifacts" \
| jq -r --arg v "macOS_${VERSION_NORMALIZED}" --arg f "$FORMAT" '
.artifacts[]
| select(.name | startswith($v) and (endswith($f) or endswith($f + ".img")))
| select(.expired == false)
| .name' | head -1)
if [ -n "$MATCH" ] && [ "$MATCH" != "null" ]; then
FOUND_RUN_URL="https://github.com/${fork_full_name}/actions/runs/${RUN_ID}"
FOUND_ARTIFACT_NAME="$MATCH"
break 2
fi
done < <(echo "$RECENT")
PAGE=$((PAGE + 1))
done
if [ -n "$FOUND_RUN_URL" ]; then
echo "## Found **${FOUND_ARTIFACT_NAME}** in a recent fork" >> $GITHUB_STEP_SUMMARY
echo "**[${FOUND_RUN_URL}](${FOUND_RUN_URL})**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "1. Open the link above" >> $GITHUB_STEP_SUMMARY
echo "2. Scroll down to the **Artifacts** section" >> $GITHUB_STEP_SUMMARY
echo "3. Click **${FOUND_ARTIFACT_NAME}** to download" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> [!TIP]" >> $GITHUB_STEP_SUMMARY
echo "> Want to build your own latest version? Star :star: [LongQT-sea/macos-iso-builder](https://github.com/LongQT-sea/macos-iso-builder) to skip this search and go straight to build next time." >> $GITHUB_STEP_SUMMARY
echo "> <br>![star](https://raw.githubusercontent.com/LongQT-sea/macos-iso-builder/main/.github/star.jpg)" >> $GITHUB_STEP_SUMMARY
else
echo "## No recent builds found in forks." >> $GITHUB_STEP_SUMMARY
echo "Star :star: [LongQT-sea/macos-iso-builder](https://github.com/LongQT-sea/macos-iso-builder) to skip this search and go straight to build next time." >> $GITHUB_STEP_SUMMARY
echo "<br>![star](https://raw.githubusercontent.com/LongQT-sea/macos-iso-builder/main/.github/star.jpg)" >> $GITHUB_STEP_SUMMARY
echo "_build=true" >> $GITHUB_OUTPUT
fi
fi
exit 0
fi
echo "_build=true" >> $GITHUB_OUTPUT
build-macos-image:
needs: preflight
if: needs.preflight.outputs._build == 'true'
runs-on: macos-15-intel
timeout-minutes: 80
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: System Information
run: |
echo "Runner OS: $(sw_vers -productName) $(sw_vers -productVersion)"
echo "Architecture: $(uname -m)"
echo ""
df -h $(mktemp)
echo ""
echo "RAM: $(top -l 1 | grep PhysMem)"
echo ""
echo "CPU: $(sysctl -n machdep.cpu.brand_string)"
- name: Create macOS image
id: create_image
run: |
./mkmaciso "${{ inputs.macos_version }}" "${{ inputs.image_format }}"
if [ "${{ inputs.image_format }}" == "iso" ]; then
echo "image_name=$(basename *.iso)" >> $GITHUB_OUTPUT
else
echo "image_name=$(basename *.dmg.img)" >> $GITHUB_OUTPUT
fi
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
path: ${{ steps.create_image.outputs.image_name }}
compression-level: 0
retention-days: 15
archive: false
- name: Summary
if: always()
run: |
if [ "${{ steps.create_image.outcome }}" == "failure" ]; then
echo "## Download macOS failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> This runner may have network issues. Please **re-run the workflow** to try a different runner." >> $GITHUB_STEP_SUMMARY
elif [ "${{ job.status }}" == "success" ]; then
if [ "${{ inputs.image_format }}" == "iso" ]; then
echo "## Successfully built $(basename *.iso)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> [!Important]" >> $GITHUB_STEP_SUMMARY
echo "> This ISO image is intended for creating macOS virtual machines on Proxmox VE, QEMU, VMware, and VirtualBox." >> $GITHUB_STEP_SUMMARY
else
echo "## Successfully built $(basename *.dmg.img)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> [!Important]" >> $GITHUB_STEP_SUMMARY
echo '> This DMG image is intended for flashing to USB drive using [Rufus](https://rufus.ie/en/#download) *(Windows)* or `dd` *(Linux)*.' >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "> [!TIP]" >> $GITHUB_STEP_SUMMARY
echo "> Enable [Cloudflare WARP](https://one.one.one.one/) for faster download from GitHub artifact." >> $GITHUB_STEP_SUMMARY
fi