Skip to content

Build ISO

Build ISO #168

Workflow file for this run

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