Docker Build #1
Workflow file for this run
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: Docker Build | |
| on: | |
| push: | |
| # Only build on tags, not branches | |
| branches-ignore: ['**'] # Explicitly ignore all branches | |
| tags: | |
| - 'build-*' # Tags for builds only (no release) | |
| - 'v*' # Tags for builds with releases (e.g., v1.0.0) | |
| pull_request: | |
| branches: [master, main] | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| workflow_dispatch: | |
| inputs: | |
| build_type: | |
| description: 'Build type (minimal, standard, full)' | |
| required: true | |
| default: 'standard' | |
| type: choice | |
| options: | |
| - minimal | |
| - standard | |
| - full | |
| jobs: | |
| # Job to determine which builds to run based on trigger type | |
| setup: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.set-matrix.outputs.matrix }} | |
| release: ${{ steps.check-release.outputs.should_release }} | |
| steps: | |
| - id: check-release | |
| run: | | |
| # Check if this is a release tag (starts with 'v') | |
| if [[ "${{ github.ref }}" == refs/tags/v* ]]; then | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "should_release=false" >> $GITHUB_OUTPUT | |
| fi | |
| - id: set-matrix | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| # For manual triggers, only build the selected type | |
| echo "matrix={\"include\":[{\"name\":\"${{ github.event.inputs.build_type }}\",\"build_args\":\"--profile=${{ github.event.inputs.build_type }} --compression-tool=upx\"}]}" >> $GITHUB_OUTPUT | |
| else | |
| # For automatic triggers, build all types with UPX compression | |
| echo "matrix={\"include\":[{\"name\":\"minimal\",\"build_args\":\"--profile=minimal --compression-tool=upx\"},{\"name\":\"standard\",\"build_args\":\"--profile=standard --compression-tool=upx\"},{\"name\":\"full\",\"build_args\":\"--profile=full --compression-tool=upx\"}]}" >> $GITHUB_OUTPUT | |
| fi | |
| # Build job using Docker with the same setup as local builds | |
| build: | |
| needs: setup | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: ${{fromJson(needs.setup.outputs.matrix)}} | |
| fail-fast: false | |
| name: Build OneFileLinux (${{ matrix.name }}) | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y build-essential gcc g++ make autoconf automake libtool libelf-dev upx-ucl unzip zstd xz-utils ccache uuid-dev libuuid1 libblkid-dev libtirpc-dev | |
| # Verify Docker is installed and running (GitHub Actions has Docker pre-installed) | |
| docker --version | |
| # Set up Docker Compose (either install it or create wrapper for docker compose plugin) | |
| if ! command -v docker-compose &> /dev/null; then | |
| echo "docker-compose command not found, setting up alternatives..." | |
| # First try to use docker compose plugin if available | |
| if docker compose version &> /dev/null; then | |
| echo "Docker Compose plugin is available, creating wrapper script" | |
| echo '#!/bin/bash | |
| docker compose "$@"' > /tmp/docker-compose | |
| chmod +x /tmp/docker-compose | |
| sudo mv /tmp/docker-compose /usr/local/bin/docker-compose | |
| else | |
| # If plugin not available, install docker-compose binary | |
| echo "Installing docker-compose from GitHub releases" | |
| sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose | |
| sudo chmod +x /usr/local/bin/docker-compose | |
| fi | |
| fi | |
| # Verify docker-compose is now available | |
| docker-compose --version || echo "Warning: docker-compose not available, will use docker compose plugin directly" | |
| # Create output directories with appropriate permissions and ensure docker can write to them | |
| mkdir -p build/output output | |
| sudo chown -R $(id -u):$(id -g) build output | |
| sudo chmod -R 777 build output | |
| # Create a .build_progress file with correct permissions if it doesn't exist | |
| touch build/.build_progress | |
| chmod 666 build/.build_progress | |
| # Make all scripts executable | |
| chmod -R +x build/*.sh docker/*.sh | |
| find build/tools -name "*.sh" -exec chmod +x {} \; 2>/dev/null || true | |
| - name: Cache Alpine kernel configs | |
| uses: actions/cache@v4 | |
| with: | |
| path: build/zfiles/kernel-configs | |
| key: alpine-kernel-config-${{ hashFiles('build/80_common.sh') }} | |
| restore-keys: | | |
| alpine-kernel-config- | |
| - name: Set up ccache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.ccache | |
| key: ccache-${{ runner.os }}-${{ matrix.name }}-${{ github.sha }} | |
| restore-keys: | | |
| ccache-${{ runner.os }}-${{ matrix.name }}- | |
| ccache-${{ runner.os }}- | |
| # Create custom env file for GitHub Actions using the same docker-compose setup as local | |
| - name: Configure build environment | |
| run: | | |
| # Create .env file with GitHub-specific settings | |
| cat > docker/.env << EOF | |
| # GitHub Actions build environment | |
| # Generated at $(date) | |
| # Build arguments from matrix | |
| BUILD_ARGS=${{ matrix.build_args }} | |
| # Resource allocations appropriate for GitHub runners | |
| DOCKER_MEMORY=7g | |
| DOCKER_CPUS=2 | |
| # User ID mapping - use the runner's UID/GID | |
| HOST_UID=$(id -u) | |
| HOST_GID=$(id -g) | |
| # GitHub-specific settings | |
| GITHUB_ACTIONS=true | |
| # Run as root to avoid permission issues | |
| RUN_AS_ROOT=true | |
| RUN_AS_USER=root | |
| # Use default password 'onefilelinux' instead of generating a random one | |
| GENERATE_RANDOM_PASSWORD=false | |
| ROOT_PASSWORD=onefilelinux | |
| # Debug settings | |
| DEBUG_FEATURE_FLAGS=true | |
| EOF | |
| # Also prepare build directory for Docker entrypoint | |
| mkdir -p build/.onefilelinux | |
| touch build/.onefilelinux/host_uid_gid | |
| echo "$(id -u):$(id -g)" > build/.onefilelinux/host_uid_gid | |
| chmod 666 build/.onefilelinux/host_uid_gid | |
| # Create ccache directory with proper permissions | |
| mkdir -p ~/.ccache | |
| sudo chmod -R 777 ~/.ccache | |
| # Copy any existing kernel configs to the expected location | |
| mkdir -p build/zfiles/kernel-configs/features | |
| chmod -R 777 build/zfiles/kernel-configs | |
| # Run the build using the same docker-compose setup as local builds | |
| - name: Build OneFileLinux using Docker | |
| env: | |
| BUILD_ARGS: ${{ matrix.build_args }} | |
| GENERATE_RANDOM_PASSWORD: "false" | |
| ROOT_PASSWORD: "onefilelinux" | |
| run: | | |
| cd docker | |
| # Show configuration | |
| echo "Building with arguments: $BUILD_ARGS" | |
| cat .env | |
| # Set environment variables for Docker | |
| export HOST_UID=$(id -u) | |
| export HOST_GID=$(id -g) | |
| echo "Setting HOST_UID=$HOST_UID and HOST_GID=$HOST_GID in environment" | |
| # Use the local docker-compose setup for builds | |
| # Try both docker-compose and docker compose commands | |
| if command -v docker-compose &> /dev/null; then | |
| echo "Using docker-compose command" | |
| docker-compose up --build | |
| COMPOSE_EXIT_CODE=$? | |
| else | |
| echo "Using docker compose plugin directly" | |
| docker compose up --build | |
| COMPOSE_EXIT_CODE=$? | |
| fi | |
| # Check the exit code | |
| if [ $COMPOSE_EXIT_CODE -ne 0 ]; then | |
| echo "Docker build failed with exit code: $COMPOSE_EXIT_CODE" | |
| if command -v docker-compose &> /dev/null; then | |
| docker-compose logs | |
| else | |
| docker compose logs | |
| fi | |
| exit 1 | |
| fi | |
| # Show output directory | |
| echo "Build output files:" | |
| ls -la ../output/ | |
| # If we need to apply any GitHub-specific fixes to output files, do it here | |
| - name: Check for build artifacts | |
| id: check_files | |
| run: | | |
| # Find all EFI files in the output directory | |
| echo "Searching for build artifacts in ./output/" | |
| ls -la ./output/ || true | |
| # Find EFI files (including those with custom names) | |
| EFI_FILES=$(find ./output/ -name "*.efi" | sort) | |
| if [ -n "$EFI_FILES" ]; then | |
| echo "efi_file=true" >> $GITHUB_OUTPUT | |
| # Check if we have a profile-specific EFI first | |
| PROFILE_EFI="./output/OneFileLinux-${{ matrix.name }}.efi" | |
| GENERIC_EFI="./output/OneFileLinux.efi" | |
| # Look for custom profile names (contain 'custom' in the name) | |
| CUSTOM_EFI=$(echo "$EFI_FILES" | grep -i "custom" | head -1) | |
| # Prioritize files in this order: Profile-specific > Custom > Generic | |
| if [ -f "$PROFILE_EFI" ]; then | |
| PRIMARY_EFI="$PROFILE_EFI" | |
| echo "efi_path=$PROFILE_EFI" >> $GITHUB_OUTPUT | |
| echo "Found profile-specific EFI file: $PROFILE_EFI" | |
| elif [ -n "$CUSTOM_EFI" ] && [ -f "$CUSTOM_EFI" ]; then | |
| PRIMARY_EFI="$CUSTOM_EFI" | |
| echo "efi_path=$CUSTOM_EFI" >> $GITHUB_OUTPUT | |
| echo "Found custom profile EFI file: $CUSTOM_EFI" | |
| elif [ -f "$GENERIC_EFI" ]; then | |
| PRIMARY_EFI="$GENERIC_EFI" | |
| echo "efi_path=$GENERIC_EFI" >> $GITHUB_OUTPUT | |
| echo "Found generic EFI file: $GENERIC_EFI" | |
| # Copy it to the profile-specific name for consistent artifacts | |
| cp "$GENERIC_EFI" "$PROFILE_EFI" | |
| echo "Copied to: $PROFILE_EFI" | |
| else | |
| # If none of the expected names are found, use the first EFI file | |
| PRIMARY_EFI=$(echo "$EFI_FILES" | head -1) | |
| echo "efi_path=$PRIMARY_EFI" >> $GITHUB_OUTPUT | |
| echo "Found alternative EFI file: $PRIMARY_EFI" | |
| fi | |
| # Show information about the primary EFI file | |
| du -h "$PRIMARY_EFI" | |
| # List all EFI files found (for comprehensive logging) | |
| echo "All EFI files found:" | |
| for efi in $EFI_FILES; do | |
| file_size=$(du -h "$efi" | cut -f1) | |
| echo "- $efi (Size: $file_size)" | |
| done | |
| else | |
| echo "efi_file=false" >> $GITHUB_OUTPUT | |
| echo "Build failed to produce any EFI file" | |
| ls -la ./output/ | |
| exit 1 | |
| fi | |
| # Display timing data if available | |
| if [ -f "./build/build_timing.log" ]; then | |
| echo "Build Timing Data:" | |
| cat ./build/build_timing.log | |
| fi | |
| - name: Upload build artifact | |
| if: steps.check_files.outputs.efi_file == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: OneFileLinux-${{ matrix.name }} | |
| # Upload all EFI files to ensure custom profiles are included | |
| path: | | |
| ./output/*.efi | |
| if-no-files-found: error | |
| - name: Upload build timing log | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-timing-log-${{ matrix.name }} | |
| path: ./build/build_timing.log | |
| if-no-files-found: warn | |
| # Release job - now conditional on the tag pattern only | |
| release: | |
| name: Package and Release | |
| needs: [setup, build] | |
| # Only run release job for 'v*' tags | |
| if: needs.setup.outputs.release == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./artifacts | |
| - name: Create release package | |
| run: | | |
| mkdir -p release | |
| # Copy all EFI files from each artifact directory to the release directory | |
| echo "Examining artifact directories:" | |
| ls -la ./artifacts/ | |
| # Loop through all artifact directories | |
| for artifact_dir in ./artifacts/OneFileLinux-*/; do | |
| if [ -d "$artifact_dir" ]; then | |
| echo "Processing artifact directory: $artifact_dir" | |
| ls -la "$artifact_dir" | |
| # Get the artifact name (last part of the directory path) | |
| artifact_name=$(basename "$artifact_dir") | |
| # Find all EFI files in the artifact directory | |
| for efi_file in "$artifact_dir"/*.efi; do | |
| if [ -f "$efi_file" ]; then | |
| # Use the original filename if it's profile-specific (contains a hyphen) | |
| # Otherwise rename it based on the artifact name | |
| efi_basename=$(basename "$efi_file") | |
| if [[ "$efi_basename" == *"-"* ]]; then | |
| # Already has a profile in the name, keep it | |
| cp "$efi_file" "./release/" | |
| echo "Copied $efi_file to ./release/$efi_basename (keeping original name)" | |
| else | |
| # Standard OneFileLinux.efi file, rename based on artifact | |
| profile_name=${artifact_name#OneFileLinux-} | |
| cp "$efi_file" "./release/OneFileLinux-$profile_name.efi" | |
| echo "Copied $efi_file to ./release/OneFileLinux-$profile_name.efi" | |
| fi | |
| fi | |
| done | |
| fi | |
| done | |
| # Handle special case for custom builds that might have a different naming pattern | |
| for artifact_dir in ./artifacts/OneFileLinux-custom*/; do | |
| if [ -d "$artifact_dir" ]; then | |
| echo "Processing custom artifact directory: $artifact_dir" | |
| # Copy all EFI files as-is | |
| for efi_file in "$artifact_dir"/*.efi; do | |
| if [ -f "$efi_file" ]; then | |
| cp "$efi_file" "./release/" | |
| echo "Copied custom build file: $efi_file" | |
| fi | |
| done | |
| fi | |
| done | |
| # Check what EFI files we have | |
| echo "Release files:" | |
| ls -la ./release/ | |
| # Create zip with all EFI files | |
| cd release | |
| zip -r OneFileLinux-release.zip *.efi | |
| - name: Upload release package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: OneFileLinux-release | |
| path: ./release/OneFileLinux-release.zip | |
| # Create GitHub Release for v* tags | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: ./release/OneFileLinux-release.zip | |
| name: "OneFileLinux ${{ github.ref_name }}" | |
| draft: false | |
| prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') || contains(github.ref, '-alpha') }} | |
| generate_release_notes: true |