Skip to content

Merge pull request #12 from Gozjaro/create-pipeline #15

Merge pull request #12 from Gozjaro/create-pipeline

Merge pull request #12 from Gozjaro/create-pipeline #15

Workflow file for this run

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 }}