Build ISO #168
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build ISO | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: '0 0 * * *' # Run the workflow every day at midnight | |
| push: | |
| branches: | |
| - main | |
| - dev | |
| paths-ignore: | |
| - '**.md' | |
| - '.gitignore' | |
| # Add permissions needed for creating and managing releases | |
| permissions: | |
| contents: write | |
| packages: read | |
| issues: read | |
| pull-requests: read | |
| env: | |
| DOCKER_BUILDKIT: 1 | |
| ISO_FILENAME: Arch.iso | |
| WORKSPACE: ${{ github.workspace }} | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 120 # Set a timeout to prevent hung builds | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Set up environment variables | |
| id: env | |
| run: | | |
| echo "DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV | |
| echo "VERSION=$(date +'%Y.%m.%d')" >> $GITHUB_ENV | |
| - name: Set up Arch Linux Container | |
| run: | | |
| docker run --privileged --name arch-container -d \ | |
| -v ${WORKSPACE}:/workdir \ | |
| -v /tmp/pacman-cache:/var/cache/pacman/pkg \ | |
| archlinux:latest sleep infinity | |
| - name: Initialize Container | |
| run: | | |
| docker exec arch-container bash -c " | |
| set -euo pipefail | |
| # Update package database and system | |
| pacman -Syu --noconfirm | |
| # Install required packages | |
| pacman -S --noconfirm --needed \ | |
| git \ | |
| archiso \ | |
| grub \ | |
| curl \ | |
| jq \ | |
| gnupg \ | |
| make \ | |
| sudo | |
| # Verify installation | |
| command -v mkarchiso >/dev/null 2>&1 || { | |
| echo '::error::mkarchiso not found' | |
| exit 1 | |
| } | |
| " | |
| - name: Build ISO | |
| id: build | |
| run: | | |
| docker exec arch-container bash -c " | |
| set -euo pipefail | |
| cd /workdir | |
| # Cleanup any previous builds | |
| rm -rf workdir/ out/ | |
| mkdir -p out/ | |
| # Build the ISO with verbose output | |
| mkarchiso -v -w workdir/ -o out/ . 2>&1 | tee build.log || { | |
| echo '::error::ISO build failed!' | |
| tail -n 50 build.log | |
| exit 1 | |
| } | |
| # Verify ISO was created | |
| [ -f out/*.iso ] || { | |
| echo '::error::ISO file not found after build' | |
| exit 1 | |
| } | |
| " | |
| - name: Generate Checksums | |
| run: | | |
| docker exec arch-container bash -c " | |
| set -euo pipefail | |
| cd /workdir/out | |
| # Generate checksums | |
| for iso in *.iso; do | |
| sha256sum \"\$iso\" > \"\${iso}.sha256sum\" | |
| sha512sum \"\$iso\" > \"\${iso}.sha512sum\" | |
| done | |
| " | |
| - name: Rename and Move ISO | |
| run: | | |
| docker exec arch-container bash -c " | |
| set -euo pipefail | |
| cd /workdir/out | |
| for f in *.iso; do | |
| newname=\"arch-linux-no-beeps-${{ env.VERSION }}.iso\" | |
| mv \"\$f\" \"\$newname\" | |
| mv \"\$f.sha256sum\" \"\$newname.sha256sum\" | |
| mv \"\$f.sha512sum\" \"\$newname.sha512sum\" | |
| done | |
| " | |
| - name: Generate Release Notes | |
| id: release_notes | |
| run: | | |
| # Create a temporary file for release notes | |
| TEMP_RELEASE_NOTES=$(mktemp) | |
| # Generate header for release notes | |
| echo "🚀 Arch Linux ISO without system beeps (build ${{ env.DATE }})" > $TEMP_RELEASE_NOTES | |
| echo "" >> $TEMP_RELEASE_NOTES | |
| # Get release notes from GitHub action | |
| gh api \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| /repos/${GITHUB_REPOSITORY}/releases/generate-notes \ | |
| -F tag_name="v${{ env.VERSION }}" \ | |
| -F target_commitish="${GITHUB_SHA}" \ | |
| -F previous_tag_name="$(git describe --tags --abbrev=0 2>/dev/null || echo '')" \ | |
| | jq -r '.body' >> $TEMP_RELEASE_NOTES | |
| # Add standard information | |
| { | |
| echo "" | |
| echo "### Download" | |
| echo "- Download the ISO and verify checksums before use" | |
| echo "" | |
| echo "### Checksums" | |
| echo "SHA256 and SHA512 checksums are available in the uploaded files." | |
| } >> $TEMP_RELEASE_NOTES | |
| # Set the release notes in GITHUB_ENV | |
| echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV | |
| cat $TEMP_RELEASE_NOTES >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| # Cleanup | |
| rm -f $TEMP_RELEASE_NOTES | |
| - name: Create Release | |
| id: create_release | |
| uses: softprops/action-gh-release@v2 | |
| if: github.ref == 'refs/heads/main' | |
| env: | |
| FAIL_COMMENT_NAME: "Create Release" | |
| FAIL_COMMENT_MESSAGE: "An error occurred during the release creation process." | |
| FAIL_COMMENT_CONTEXT: "GitHub Actions Workflow" | |
| FAIL_COMMENT_DETAILS: "Check the logs for more details." | |
| with: | |
| tag_name: v${{ env.VERSION }} | |
| name: "Arch Linux No Beeps v${{ env.VERSION }}" | |
| body: ${{ env.RELEASE_NOTES }} | |
| draft: false | |
| prerelease: false | |
| files: | | |
| ${{ env.WORKSPACE }}/out/*.iso | |
| ${{ env.WORKSPACE }}/out/*.sha*sum | |
| - name: Set up GitHub CLI | |
| run: | | |
| type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y) | |
| curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ | |
| && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ | |
| && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ | |
| && sudo apt update \ | |
| && sudo apt install gh -y | |
| - name: Delete old releases | |
| # This step runs after the GitHub CLI setup and release creation | |
| if: github.ref == 'refs/heads/main' && success() | |
| env: | |
| # Don't set GITHUB_TOKEN here as it conflicts with gh auth | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set +e # Don't exit on error | |
| echo "::group::Release Cleanup" | |
| # Get current release tag we're creating | |
| current_tag="v${{ env.VERSION }}" | |
| echo "ℹ️ Current release tag: $current_tag" | |
| # GitHub CLI uses GH_TOKEN environment variable automatically | |
| # No need to explicitly authenticate | |
| # List all releases | |
| echo "ℹ️ Listing existing releases..." | |
| # Use simple list format first to check if releases exist | |
| if ! release_count=$(gh release list | wc -l); then | |
| echo "::warning::Failed to list releases. Skipping cleanup." | |
| echo "::endgroup::" | |
| exit 0 | |
| fi | |
| if [ "$release_count" -eq 0 ]; then | |
| echo "ℹ️ No existing releases found. Nothing to clean up." | |
| echo "::endgroup::" | |
| exit 0 | |
| fi | |
| echo "ℹ️ Found $release_count releases in total" | |
| # Get detailed release info with JSON | |
| if ! releases=$(gh release list --limit 100 --json tagName,createdAt 2>/dev/null); then | |
| echo "::warning::Unable to get detailed release information. Skipping cleanup." | |
| echo "::endgroup::" | |
| exit 0 | |
| fi | |
| # Check if jq command is available | |
| if ! command -v jq &> /dev/null; then | |
| echo "::warning::jq command not found. Installing jq..." | |
| sudo apt-get update && sudo apt-get install -y jq | |
| fi | |
| # Parse releases, handling potential JSON parsing errors | |
| if ! old_releases=($(echo "$releases" | jq -r 'sort_by(.createdAt) | .[].tagName' 2>/dev/null)); then | |
| echo "::warning::Failed to parse release information. Skipping cleanup." | |
| echo "::endgroup::" | |
| exit 0 | |
| fi | |
| # Number of releases to keep (0 means delete all old releases) | |
| keep=0 | |
| count=0 | |
| total=${#old_releases[@]} | |
| echo "ℹ️ Found $total releases after parsing" | |
| # Delete all releases except the most recent 'keep' number and current release | |
| for tag in "${old_releases[@]}"; do | |
| # Skip the current release | |
| if [[ "$tag" == "$current_tag" ]]; then | |
| echo "ℹ️ Skipping current release: $tag" | |
| continue | |
| fi | |
| ((count++)) | |
| if ((count > keep)); then | |
| echo "🗑️ Attempting to delete release: $tag" | |
| # Try to delete the release with a timeout | |
| if timeout 30s gh release delete "$tag" --yes; then | |
| echo "✅ Successfully deleted release: $tag" | |
| else | |
| deletion_status=$? | |
| echo "::warning::Failed to delete release $tag (exit code: $deletion_status) - continuing with next release" | |
| fi | |
| # Small delay to avoid rate limiting | |
| sleep 1 | |
| else | |
| echo "🔒 Keeping release: $tag (within keep limit)" | |
| fi | |
| done | |
| echo "🏁 Release cleanup completed" | |
| echo "::endgroup::" | |
| # Always return success to avoid workflow failures | |
| exit 0 | |