Merge pull request #13 from Gozjaro/fix-source-urls #17
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 Gozjaro Live ISO | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| build_mode: | |
| description: 'Build mode' | |
| type: choice | |
| default: source | |
| options: | |
| - source | |
| - binary | |
| gozpak_repos: | |
| description: 'Gozpak repository URL (only for binary mode)' | |
| type: string | |
| default: '' | |
| push: | |
| branches: [main, master] | |
| paths: | |
| - 'stages/**' | |
| - 'config/**' | |
| - 'lib/**' | |
| - 'build.sh' | |
| - '.github/workflows/build-iso.yml' | |
| permissions: | |
| contents: write | |
| env: | |
| LFS: /mnt/lfs | |
| LFS_SIZE: 50G | |
| MAKEFLAGS: "-j$(nproc)" | |
| jobs: | |
| build-iso: | |
| runs-on: [self-hosted, Linux, X64] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine build mode | |
| run: | | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| BUILD_MODE="${{ github.event.inputs.build_mode || 'source' }}" | |
| else | |
| BUILD_MODE="source" | |
| fi | |
| echo "BUILD_MODE=$BUILD_MODE" >> $GITHUB_ENV | |
| echo "==> Build mode: $BUILD_MODE" | |
| - name: Setup LFS directory | |
| run: | | |
| set -euo pipefail | |
| LFS="${{ env.LFS }}" | |
| # Check current user and privileges | |
| echo "Running as: $(whoami) (UID: $(id -u))" | |
| # Function to run commands with sudo if needed | |
| run_cmd() { | |
| if [ "$(id -u)" = "0" ]; then | |
| "$@" | |
| else | |
| sudo "$@" | |
| fi | |
| } | |
| # Create LFS directory if it doesn't exist | |
| run_cmd mkdir -p "$LFS" | |
| # Verify we can write to LFS | |
| run_cmd touch "$LFS/.write_test" && run_cmd rm "$LFS/.write_test" || \ | |
| die "Cannot write to $LFS - ensure the volume is mounted with write permissions" | |
| # Check if LFS image exists (for loopback mode) | |
| IMAGE="$LFS/lfs.img" | |
| if [[ -f "$IMAGE" ]]; then | |
| echo "Using existing LFS image: $IMAGE" | |
| else | |
| # Try to create loopback image | |
| echo "Attempting to create loopback image..." | |
| if run_cmd truncate -s "${{ env.LFS_SIZE }}" "$IMAGE" 2>/dev/null && \ | |
| run_cmd mkfs.ext4 -F -L lfs "$IMAGE" 2>/dev/null && \ | |
| run_cmd mount -o loop "$IMAGE" "$LFS" 2>/dev/null; then | |
| echo "Loopback image created and mounted successfully." | |
| else | |
| echo "WARNING: Could not create loopback image." | |
| echo "The LFS directory must be pre-formatted and mounted on the host." | |
| echo "See README for runner setup instructions." | |
| fi | |
| fi | |
| # Verify mount | |
| df -h "$LFS" | |
| echo "LFS partition ready at $LFS" | |
| - name: Host prerequisite check | |
| run: | | |
| set -euo pipefail | |
| # Check for actual command names, not package names | |
| REQUIRED_TOOLS=( | |
| # Build tools | |
| gcc g++ make bison flex patch | |
| # Compression | |
| gzip bzip2 xz wget curl | |
| # Core utils (common commands) | |
| grep sed awk sort tr | |
| tar cpio mkfs.vfat xorriso | |
| # SquashFS | |
| mksquashfs unsquashfs | |
| # Disk tools (commands from util-linux, dosfstools, mtools) | |
| lsblk mount fdisk sfdisk | |
| # Binutils | |
| ld as | |
| # Diff tools | |
| diff cmp | |
| # Find tools | |
| find xargs | |
| # Text/info tools | |
| gawk info m4 perl python3 texi2any | |
| # ISO/EFI tools | |
| mformat mlabel mkdosfs | |
| ) | |
| MISSING=() | |
| for tool in "${REQUIRED_TOOLS[@]}"; do | |
| if ! command -v "$tool" &>/dev/null; then | |
| MISSING+=("$tool") | |
| fi | |
| done | |
| if [[ ${#MISSING[@]} -gt 0 ]]; then | |
| echo "::error::Missing required tools: ${MISSING[*]}" | |
| echo "" | |
| echo "Install missing tools with:" | |
| echo " Ubuntu/Debian: sudo apt install -y gcc g++ make bison flex patch gzip bzip2 xz-utils wget curl grep sed gawk tar cpio xorriso squashfs-tools dosfstools mtools binutils diffutils findutils texinfo" | |
| echo " Fedora: sudo dnf install -y gcc gcc-c++ make bison flex patch gzip bzip2 xz wget curl grep gawk tar cpio xorriso squashfs-util dosfstools mtools binutils diffutils findutils texinfo" | |
| exit 1 | |
| fi | |
| echo "All host prerequisites satisfied:" | |
| echo " Kernel: $(uname -r) ($(uname -m))" | |
| echo " CPUs: $(nproc)" | |
| echo " Memory: $(free -h | awk '/^Mem:/{print $2}')" | |
| echo " Disk: $(df -h '${{ env.LFS }}' | awk 'NR==2{print $4}')" | |
| - name: Fix coreutils and shell aliases | |
| run: | | |
| set -euo pipefail | |
| # Check if sort is from GNU coreutils or uutils | |
| SORT_VER=$(sort --version 2>&1 || true) | |
| echo "sort version: $SORT_VER" | |
| if echo "$SORT_VER" | grep -qi "uutils"; then | |
| echo "::warning::uutils coreutils detected. Fixing symlinks..." | |
| # The system has GNU coreutils but symlinks were overwritten by cargo | |
| # Remove broken symlinks and reinstall coreutils to restore them | |
| sudo rm -f /usr/bin/sort /usr/bin/cut /usr/bin/date /usr/bin/echo /usr/bin/env | |
| sudo apt-get update -qq | |
| sudo apt-get install -y -qq coreutils bash grep findutils | |
| # If dpkg didn't restore, manually fix sort | |
| if sort --version 2>&1 | grep -qi "uutils"; then | |
| echo "Manually fixing sort symlink..." | |
| sudo rm -f /usr/bin/sort | |
| # GNU coreutils multi-call binary can handle it | |
| sudo ln -sf /usr/bin/coreutils /usr/bin/sort | |
| fi | |
| fi | |
| # Ensure sh points to bash | |
| if [ -L /bin/sh ]; then | |
| TARGET=$(readlink -f /bin/sh) | |
| if echo "$TARGET" | grep -qi bash; then | |
| echo "sh is already linked to bash: $TARGET" | |
| else | |
| echo "Changing sh symlink to point to bash" | |
| sudo ln -sf /bin/bash /bin/sh | |
| fi | |
| elif [ ! -e /bin/sh ]; then | |
| echo "Creating sh symlink to bash" | |
| sudo ln -sf /bin/bash /bin/sh | |
| fi | |
| # Verify fixes | |
| echo "sort version: $(sort --version | head -1)" | |
| echo "sh points to: $(readlink -f /bin/sh)" | |
| alias sh 2>/dev/null || echo "sh is not aliased" | |
| - name: Run full build (source mode) | |
| if: env.BUILD_MODE == 'source' | |
| run: | | |
| set -euo pipefail | |
| cd "${{ github.workspace }}" | |
| echo "==> Starting Gozjaro LFS build (source mode)" | |
| echo " LFS: ${{ env.LFS }}" | |
| echo " Jobs: ${{ env.MAKEFLAGS }}" | |
| echo " Started: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| # Use sudo - the build requires root privileges | |
| sudo "./build.sh" all | |
| echo "==> Build completed: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| - name: Run full build (binary mode) | |
| if: env.BUILD_MODE == 'binary' | |
| run: | | |
| set -euo pipefail | |
| cd "${{ github.workspace }}" | |
| GOZPAK_REPOS="${{ github.event.inputs.gozpak_repos || '' }}" | |
| if [[ -z "$GOZPAK_REPOS" ]]; then | |
| echo "::error::Binary mode requires GOZPAK_REPOS to be set" | |
| exit 1 | |
| fi | |
| echo "==> Starting Gozjaro LFS build (binary mode)" | |
| echo " LFS: ${{ env.LFS }}" | |
| echo " Jobs: ${{ env.MAKEFLAGS }}" | |
| echo " Started: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| sudo GOZPAK_REPOS="$GOZPAK_REPOS" "./build.sh" --mode binary all | |
| echo "==> Build completed: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| - name: Collect build logs | |
| if: always() | |
| run: | | |
| set -euo pipefail | |
| LOG_DIR="${{ env.LFS }}/var/gozjaro/log" | |
| if [[ -d "$LOG_DIR" ]]; then | |
| echo "=== Build Log Summary ===" | |
| ls -lh "$LOG_DIR"/*.log 2>/dev/null | tail -20 | |
| echo "" | |
| echo "=== Final Stage Log ===" | |
| FINAL_LOG=$(ls -t "$LOG_DIR"/*.log 2>/dev/null | head -1) | |
| if [[ -n "$FINAL_LOG" ]]; then | |
| tail -50 "$FINAL_LOG" | |
| fi | |
| else | |
| echo "No build logs found at $LOG_DIR" | |
| fi | |
| - name: Upload ISO artifact | |
| uses: actions/upload-artifact@v4 | |
| if: success() | |
| with: | |
| name: gozjaro-live-${{ github.sha }} | |
| path: | | |
| ${{ env.LFS }}/gozjaro-*-live.iso | |
| ${{ env.LFS }}/gozjaro-*-live.iso.* | |
| retention-days: 14 | |
| if-no-files-found: error | |
| - name: Publish to GitHub Release | |
| if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && (github.ref_name == 'main' || github.ref_name == 'master')) | |
| run: | | |
| set -euo pipefail | |
| ISO_DIR="${{ env.LFS }}" | |
| shopt -s nullglob | |
| isos=("$ISO_DIR"/gozjaro-*-live.iso) | |
| shopt -u nullglob | |
| if [[ ${#isos[@]} -eq 0 ]]; then | |
| echo "::warning::No ISO found to publish" | |
| exit 0 | |
| fi | |
| ISO="${isos[-1]}" | |
| ISO_FILE=$(basename "$ISO") | |
| echo "Publishing: $ISO_FILE" | |
| # Derive release tag | |
| TAG=$(printf '%s' "$ISO_FILE" | sed 's/^gozjaro-/v/' | sed 's/-live\.iso$//') | |
| # Create or update release | |
| gh release create "$TAG" \ | |
| --title "Gozjaro Linux $TAG" \ | |
| --generate-notes \ | |
| --draft \ | |
| "$ISO" | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |