mirror of
				https://github.com/factoriotools/factorio-docker.git
				synced 2025-11-04 02:39:06 +01:00 
			
		
		
		
	refactor: Replace build system with unified solution
- Remove old build.py and build-rootless.py wrapper scripts - Rename build-unified.py to build.py as the main build script - Delete BUILD_MIGRATION.md (no longer needed) - Update CI workflow to use new build.py syntax - Update documentation in CLAUDE.md and README-ROOTLESS.md The new build system provides all functionality in a single script: - Default: builds regular images - --rootless: builds only rootless images - --both: builds both regular and rootless images - --multiarch and --push-tags: work as before This creates a cleaner, more maintainable build system. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/docker-build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/docker-build.yml
									
									
									
									
										vendored
									
									
								
							@@ -26,4 +26,4 @@ jobs:
 | 
			
		||||
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
 | 
			
		||||
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
 | 
			
		||||
        run: |
 | 
			
		||||
          ./build-unified.py --push-tags --multiarch --both
 | 
			
		||||
          ./build.py --push-tags --multiarch --both
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
# Build System Migration Guide
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
The build system has been unified into a single script (`build-unified.py`) that can build both regular and rootless Docker images. This replaces the separate `build.py` and `build-rootless.py` scripts.
 | 
			
		||||
 | 
			
		||||
## New Unified Build Script
 | 
			
		||||
 | 
			
		||||
### Usage
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Build only regular images (default behavior)
 | 
			
		||||
./build-unified.py
 | 
			
		||||
 | 
			
		||||
# Build only rootless images
 | 
			
		||||
./build-unified.py --rootless
 | 
			
		||||
 | 
			
		||||
# Build both regular and rootless images
 | 
			
		||||
./build-unified.py --both
 | 
			
		||||
 | 
			
		||||
# Build with multi-architecture support
 | 
			
		||||
./build-unified.py --multiarch --both
 | 
			
		||||
 | 
			
		||||
# Build and push to Docker Hub
 | 
			
		||||
./build-unified.py --push-tags --multiarch --both
 | 
			
		||||
 | 
			
		||||
# Build only stable/latest versions (useful for rootless)
 | 
			
		||||
./build-unified.py --rootless --only-stable-latest --push-tags --multiarch
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Options
 | 
			
		||||
 | 
			
		||||
- `--push-tags`: Push images to Docker Hub (requires DOCKER_USERNAME and DOCKER_PASSWORD env vars)
 | 
			
		||||
- `--multiarch`: Build multi-architecture images (linux/amd64 and linux/arm64)
 | 
			
		||||
- `--rootless`: Build only rootless images
 | 
			
		||||
- `--both`: Build both regular and rootless images
 | 
			
		||||
- `--only-stable-latest`: Build only versions tagged as 'stable' or 'latest'
 | 
			
		||||
 | 
			
		||||
## Migration Path
 | 
			
		||||
 | 
			
		||||
### For CI/CD
 | 
			
		||||
 | 
			
		||||
The GitHub Actions workflow has been updated to use:
 | 
			
		||||
```yaml
 | 
			
		||||
./build-unified.py --push-tags --multiarch --both
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### For Local Development
 | 
			
		||||
 | 
			
		||||
Replace old commands with new ones:
 | 
			
		||||
 | 
			
		||||
| Old Command | New Command |
 | 
			
		||||
|-------------|-------------|
 | 
			
		||||
| `./build.py` | `./build-unified.py` |
 | 
			
		||||
| `./build.py --multiarch` | `./build-unified.py --multiarch` |
 | 
			
		||||
| `./build-rootless.py` | `./build-unified.py --rootless` |
 | 
			
		||||
| `./build.py && ./build-rootless.py` | `./build-unified.py --both` |
 | 
			
		||||
 | 
			
		||||
## Backwards Compatibility
 | 
			
		||||
 | 
			
		||||
The original `build.py` and `build-rootless.py` scripts are now wrappers that call the unified script with appropriate arguments to maintain backwards compatibility.
 | 
			
		||||
							
								
								
									
										20
									
								
								CLAUDE.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								CLAUDE.md
									
									
									
									
									
								
							@@ -11,8 +11,9 @@ This is a Docker image for running a Factorio headless server. It provides autom
 | 
			
		||||
### Key Components
 | 
			
		||||
 | 
			
		||||
1. **Docker Image Build System**
 | 
			
		||||
   - `build.py` - Python script that builds Docker images from `buildinfo.json`
 | 
			
		||||
   - `build.py` - Unified Python script that builds both regular and rootless Docker images from `buildinfo.json`
 | 
			
		||||
   - `docker/Dockerfile` - Main Dockerfile that creates the Factorio server image
 | 
			
		||||
   - `docker/Dockerfile.rootless` - Dockerfile for rootless variant (runs as UID 1000)
 | 
			
		||||
   - `buildinfo.json` - Contains version info, SHA256 checksums, and tags for all supported versions
 | 
			
		||||
   - Supports multi-architecture builds (linux/amd64, linux/arm64) using Docker buildx
 | 
			
		||||
 | 
			
		||||
@@ -38,11 +39,20 @@ This is a Docker image for running a Factorio headless server. It provides autom
 | 
			
		||||
### Building Images
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Build a single architecture image locally
 | 
			
		||||
# Build regular images locally (single architecture)
 | 
			
		||||
python3 build.py
 | 
			
		||||
 | 
			
		||||
# Build and push multi-architecture images
 | 
			
		||||
# Build rootless images only
 | 
			
		||||
python3 build.py --rootless
 | 
			
		||||
 | 
			
		||||
# Build both regular and rootless images
 | 
			
		||||
python3 build.py --both
 | 
			
		||||
 | 
			
		||||
# Build and push multi-architecture images (regular only)
 | 
			
		||||
python3 build.py --multiarch --push-tags
 | 
			
		||||
 | 
			
		||||
# Build and push both regular and rootless multi-architecture images
 | 
			
		||||
python3 build.py --multiarch --push-tags --both
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Running the Container
 | 
			
		||||
@@ -109,6 +119,8 @@ Version updates are automated via GitHub Actions that run `update.sh` periodical
 | 
			
		||||
## Testing Changes
 | 
			
		||||
 | 
			
		||||
1. Modify `buildinfo.json` to test specific versions
 | 
			
		||||
2. Run `python3 build.py` to build locally
 | 
			
		||||
2. Run `python3 build.py` to build regular images locally
 | 
			
		||||
   - Use `python3 build.py --rootless` for rootless images
 | 
			
		||||
   - Use `python3 build.py --both` to build both variants
 | 
			
		||||
3. Test the container with your local data volume
 | 
			
		||||
4. For production changes, ensure `update.sh` handles version transitions correctly
 | 
			
		||||
@@ -120,11 +120,14 @@ docker run -d \
 | 
			
		||||
To build rootless images locally:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Build for current architecture
 | 
			
		||||
python3 build-rootless.py
 | 
			
		||||
# Build rootless images for current architecture
 | 
			
		||||
python3 build.py --rootless
 | 
			
		||||
 | 
			
		||||
# Build and push multi-arch images
 | 
			
		||||
python3 build-rootless.py --multiarch --push-tags
 | 
			
		||||
# Build and push multi-arch rootless images
 | 
			
		||||
python3 build.py --rootless --multiarch --push-tags
 | 
			
		||||
 | 
			
		||||
# Build both regular and rootless images
 | 
			
		||||
python3 build.py --both --multiarch --push-tags
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Why Use Rootless Images?
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
"""
 | 
			
		||||
Legacy wrapper script for backwards compatibility.
 | 
			
		||||
This script now calls build-unified.py to build rootless images.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import subprocess
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
# Convert arguments and pass to unified script with --rootless flag
 | 
			
		||||
args = ["./build-unified.py", "--rootless", "--only-stable-latest"]
 | 
			
		||||
args.extend(sys.argv[1:])
 | 
			
		||||
 | 
			
		||||
# Execute the unified build script
 | 
			
		||||
sys.exit(subprocess.call(args))
 | 
			
		||||
							
								
								
									
										157
									
								
								build-unified.py
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								build-unified.py
									
									
									
									
									
								
							@@ -1,157 +0,0 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import json
 | 
			
		||||
import subprocess
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
import tempfile
 | 
			
		||||
import argparse
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PLATFORMS = [
 | 
			
		||||
    "linux/arm64",
 | 
			
		||||
    "linux/amd64",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_builder(build_dir, builder_name, platform):
 | 
			
		||||
    check_exists_command = ["docker", "buildx", "inspect", builder_name]
 | 
			
		||||
    if subprocess.run(check_exists_command, stderr=subprocess.DEVNULL).returncode != 0:
 | 
			
		||||
        create_command = ["docker", "buildx", "create", "--platform", platform, "--name", builder_name]
 | 
			
		||||
        try:
 | 
			
		||||
            subprocess.run(create_command, cwd=build_dir, check=True)
 | 
			
		||||
        except subprocess.CalledProcessError:
 | 
			
		||||
            print("Creating builder failed")
 | 
			
		||||
            exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_and_push_multiarch(build_dir, build_args, push, builder_suffix=""):
 | 
			
		||||
    builder_name = f"factoriotools{builder_suffix}-multiarch"
 | 
			
		||||
    platform = ",".join(PLATFORMS)
 | 
			
		||||
    create_builder(build_dir, builder_name, platform)
 | 
			
		||||
    build_command = ["docker", "buildx", "build", "--platform", platform, "--builder", builder_name] + build_args
 | 
			
		||||
    if push:
 | 
			
		||||
        build_command.append("--push")
 | 
			
		||||
    try:
 | 
			
		||||
        subprocess.run(build_command, cwd=build_dir, check=True)
 | 
			
		||||
    except subprocess.CalledProcessError:
 | 
			
		||||
        print(f"Build and push of {builder_suffix or 'regular'} image failed")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_singlearch(build_dir, build_args, image_type="regular"):
 | 
			
		||||
    build_command = ["docker", "build"] + build_args
 | 
			
		||||
    try:
 | 
			
		||||
        subprocess.run(build_command, cwd=build_dir, check=True)
 | 
			
		||||
    except subprocess.CalledProcessError:
 | 
			
		||||
        print(f"Build of {image_type} image failed")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def push_singlearch(tags):
 | 
			
		||||
    for tag in tags:
 | 
			
		||||
        try:
 | 
			
		||||
            subprocess.run(["docker", "push", f"factoriotools/factorio:{tag}"],
 | 
			
		||||
                            check=True)
 | 
			
		||||
        except subprocess.CalledProcessError:
 | 
			
		||||
            print("Docker push failed")
 | 
			
		||||
            exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_and_push(sha256, version, tags, push, multiarch, dockerfile="Dockerfile", builder_suffix=""):
 | 
			
		||||
    build_dir = tempfile.mktemp()
 | 
			
		||||
    shutil.copytree("docker", build_dir)
 | 
			
		||||
    build_args = ["-f", dockerfile, "--build-arg", f"VERSION={version}", "--build-arg", f"SHA256={sha256}", "."]
 | 
			
		||||
    for tag in tags:
 | 
			
		||||
        build_args.extend(["-t", f"factoriotools/factorio:{tag}"])
 | 
			
		||||
    
 | 
			
		||||
    image_type = "rootless" if "rootless" in dockerfile.lower() else "regular"
 | 
			
		||||
    
 | 
			
		||||
    if multiarch:
 | 
			
		||||
        build_and_push_multiarch(build_dir, build_args, push, builder_suffix)
 | 
			
		||||
    else:
 | 
			
		||||
        build_singlearch(build_dir, build_args, image_type)
 | 
			
		||||
        if push:
 | 
			
		||||
            push_singlearch(tags)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def login():
 | 
			
		||||
    try:
 | 
			
		||||
        username = os.environ["DOCKER_USERNAME"]
 | 
			
		||||
        password = os.environ["DOCKER_PASSWORD"]
 | 
			
		||||
        subprocess.run(["docker", "login", "-u", username, "-p", password], check=True)
 | 
			
		||||
    except KeyError:
 | 
			
		||||
        print("Username and password need to be given")
 | 
			
		||||
        exit(1)
 | 
			
		||||
    except subprocess.CalledProcessError:
 | 
			
		||||
        print("Docker login failed")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_rootless_tags(original_tags):
 | 
			
		||||
    """Generate rootless-specific tags from original tags"""
 | 
			
		||||
    return [f"{tag}-rootless" for tag in original_tags]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Build Factorio Docker images')
 | 
			
		||||
    parser.add_argument('--push-tags', action='store_true', help='Push images to Docker Hub')
 | 
			
		||||
    parser.add_argument('--multiarch', action='store_true', help='Build multi-architecture images')
 | 
			
		||||
    parser.add_argument('--rootless', action='store_true', help='Build only rootless images')
 | 
			
		||||
    parser.add_argument('--both', action='store_true', help='Build both regular and rootless images')
 | 
			
		||||
    parser.add_argument('--only-stable-latest', action='store_true', 
 | 
			
		||||
                        help='Build only stable and latest versions (for rootless by default)')
 | 
			
		||||
    
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
    
 | 
			
		||||
    # Default behavior: build regular images unless specified otherwise
 | 
			
		||||
    build_regular = not args.rootless or args.both
 | 
			
		||||
    build_rootless = args.rootless or args.both
 | 
			
		||||
    
 | 
			
		||||
    with open(os.path.join(os.path.dirname(__file__), "buildinfo.json")) as file_handle:
 | 
			
		||||
        builddata = json.load(file_handle)
 | 
			
		||||
 | 
			
		||||
    if args.push_tags:
 | 
			
		||||
        login()
 | 
			
		||||
 | 
			
		||||
    # Filter versions if needed
 | 
			
		||||
    versions_to_build = []
 | 
			
		||||
    for version, buildinfo in sorted(builddata.items(), key=lambda item: item[0], reverse=True):
 | 
			
		||||
        if args.only_stable_latest or (build_rootless and not build_regular):
 | 
			
		||||
            # For rootless-only builds, default to stable/latest only
 | 
			
		||||
            if "stable" in buildinfo["tags"] or "latest" in buildinfo["tags"]:
 | 
			
		||||
                versions_to_build.append((version, buildinfo))
 | 
			
		||||
        else:
 | 
			
		||||
            versions_to_build.append((version, buildinfo))
 | 
			
		||||
    
 | 
			
		||||
    # Build regular images
 | 
			
		||||
    if build_regular:
 | 
			
		||||
        print("Building regular images...")
 | 
			
		||||
        for version, buildinfo in versions_to_build:
 | 
			
		||||
            sha256 = buildinfo["sha256"]
 | 
			
		||||
            tags = buildinfo["tags"]
 | 
			
		||||
            build_and_push(sha256, version, tags, args.push_tags, args.multiarch)
 | 
			
		||||
    
 | 
			
		||||
    # Build rootless images
 | 
			
		||||
    if build_rootless:
 | 
			
		||||
        print("Building rootless images...")
 | 
			
		||||
        # For rootless, only build stable and latest unless building both
 | 
			
		||||
        rootless_versions = []
 | 
			
		||||
        if not build_regular or args.only_stable_latest:
 | 
			
		||||
            for version, buildinfo in builddata.items():
 | 
			
		||||
                if "stable" in buildinfo["tags"] or "latest" in buildinfo["tags"]:
 | 
			
		||||
                    rootless_versions.append((version, buildinfo))
 | 
			
		||||
        else:
 | 
			
		||||
            rootless_versions = versions_to_build
 | 
			
		||||
            
 | 
			
		||||
        for version, buildinfo in rootless_versions:
 | 
			
		||||
            sha256 = buildinfo["sha256"]
 | 
			
		||||
            original_tags = buildinfo["tags"]
 | 
			
		||||
            rootless_tags = generate_rootless_tags(original_tags)
 | 
			
		||||
            build_and_push(sha256, version, rootless_tags, args.push_tags, args.multiarch, 
 | 
			
		||||
                         dockerfile="Dockerfile.rootless", builder_suffix="-rootless")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										160
									
								
								build.py
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								build.py
									
									
									
									
									
								
							@@ -1,15 +1,157 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
"""
 | 
			
		||||
Legacy wrapper script for backwards compatibility.
 | 
			
		||||
This script now calls build-unified.py to build regular images.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import json
 | 
			
		||||
import subprocess
 | 
			
		||||
import shutil
 | 
			
		||||
import sys
 | 
			
		||||
import tempfile
 | 
			
		||||
import argparse
 | 
			
		||||
 | 
			
		||||
# Convert arguments and pass to unified script
 | 
			
		||||
args = ["./build-unified.py"]
 | 
			
		||||
args.extend(sys.argv[1:])
 | 
			
		||||
 | 
			
		||||
# Execute the unified build script
 | 
			
		||||
sys.exit(subprocess.call(args))
 | 
			
		||||
PLATFORMS = [
 | 
			
		||||
    "linux/arm64",
 | 
			
		||||
    "linux/amd64",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_builder(build_dir, builder_name, platform):
 | 
			
		||||
    check_exists_command = ["docker", "buildx", "inspect", builder_name]
 | 
			
		||||
    if subprocess.run(check_exists_command, stderr=subprocess.DEVNULL).returncode != 0:
 | 
			
		||||
        create_command = ["docker", "buildx", "create", "--platform", platform, "--name", builder_name]
 | 
			
		||||
        try:
 | 
			
		||||
            subprocess.run(create_command, cwd=build_dir, check=True)
 | 
			
		||||
        except subprocess.CalledProcessError:
 | 
			
		||||
            print("Creating builder failed")
 | 
			
		||||
            exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_and_push_multiarch(build_dir, build_args, push, builder_suffix=""):
 | 
			
		||||
    builder_name = f"factoriotools{builder_suffix}-multiarch"
 | 
			
		||||
    platform = ",".join(PLATFORMS)
 | 
			
		||||
    create_builder(build_dir, builder_name, platform)
 | 
			
		||||
    build_command = ["docker", "buildx", "build", "--platform", platform, "--builder", builder_name] + build_args
 | 
			
		||||
    if push:
 | 
			
		||||
        build_command.append("--push")
 | 
			
		||||
    try:
 | 
			
		||||
        subprocess.run(build_command, cwd=build_dir, check=True)
 | 
			
		||||
    except subprocess.CalledProcessError:
 | 
			
		||||
        print(f"Build and push of {builder_suffix or 'regular'} image failed")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_singlearch(build_dir, build_args, image_type="regular"):
 | 
			
		||||
    build_command = ["docker", "build"] + build_args
 | 
			
		||||
    try:
 | 
			
		||||
        subprocess.run(build_command, cwd=build_dir, check=True)
 | 
			
		||||
    except subprocess.CalledProcessError:
 | 
			
		||||
        print(f"Build of {image_type} image failed")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def push_singlearch(tags):
 | 
			
		||||
    for tag in tags:
 | 
			
		||||
        try:
 | 
			
		||||
            subprocess.run(["docker", "push", f"factoriotools/factorio:{tag}"],
 | 
			
		||||
                            check=True)
 | 
			
		||||
        except subprocess.CalledProcessError:
 | 
			
		||||
            print("Docker push failed")
 | 
			
		||||
            exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_and_push(sha256, version, tags, push, multiarch, dockerfile="Dockerfile", builder_suffix=""):
 | 
			
		||||
    build_dir = tempfile.mktemp()
 | 
			
		||||
    shutil.copytree("docker", build_dir)
 | 
			
		||||
    build_args = ["-f", dockerfile, "--build-arg", f"VERSION={version}", "--build-arg", f"SHA256={sha256}", "."]
 | 
			
		||||
    for tag in tags:
 | 
			
		||||
        build_args.extend(["-t", f"factoriotools/factorio:{tag}"])
 | 
			
		||||
    
 | 
			
		||||
    image_type = "rootless" if "rootless" in dockerfile.lower() else "regular"
 | 
			
		||||
    
 | 
			
		||||
    if multiarch:
 | 
			
		||||
        build_and_push_multiarch(build_dir, build_args, push, builder_suffix)
 | 
			
		||||
    else:
 | 
			
		||||
        build_singlearch(build_dir, build_args, image_type)
 | 
			
		||||
        if push:
 | 
			
		||||
            push_singlearch(tags)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def login():
 | 
			
		||||
    try:
 | 
			
		||||
        username = os.environ["DOCKER_USERNAME"]
 | 
			
		||||
        password = os.environ["DOCKER_PASSWORD"]
 | 
			
		||||
        subprocess.run(["docker", "login", "-u", username, "-p", password], check=True)
 | 
			
		||||
    except KeyError:
 | 
			
		||||
        print("Username and password need to be given")
 | 
			
		||||
        exit(1)
 | 
			
		||||
    except subprocess.CalledProcessError:
 | 
			
		||||
        print("Docker login failed")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_rootless_tags(original_tags):
 | 
			
		||||
    """Generate rootless-specific tags from original tags"""
 | 
			
		||||
    return [f"{tag}-rootless" for tag in original_tags]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Build Factorio Docker images')
 | 
			
		||||
    parser.add_argument('--push-tags', action='store_true', help='Push images to Docker Hub')
 | 
			
		||||
    parser.add_argument('--multiarch', action='store_true', help='Build multi-architecture images')
 | 
			
		||||
    parser.add_argument('--rootless', action='store_true', help='Build only rootless images')
 | 
			
		||||
    parser.add_argument('--both', action='store_true', help='Build both regular and rootless images')
 | 
			
		||||
    parser.add_argument('--only-stable-latest', action='store_true', 
 | 
			
		||||
                        help='Build only stable and latest versions (for rootless by default)')
 | 
			
		||||
    
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
    
 | 
			
		||||
    # Default behavior: build regular images unless specified otherwise
 | 
			
		||||
    build_regular = not args.rootless or args.both
 | 
			
		||||
    build_rootless = args.rootless or args.both
 | 
			
		||||
    
 | 
			
		||||
    with open(os.path.join(os.path.dirname(__file__), "buildinfo.json")) as file_handle:
 | 
			
		||||
        builddata = json.load(file_handle)
 | 
			
		||||
 | 
			
		||||
    if args.push_tags:
 | 
			
		||||
        login()
 | 
			
		||||
 | 
			
		||||
    # Filter versions if needed
 | 
			
		||||
    versions_to_build = []
 | 
			
		||||
    for version, buildinfo in sorted(builddata.items(), key=lambda item: item[0], reverse=True):
 | 
			
		||||
        if args.only_stable_latest or (build_rootless and not build_regular):
 | 
			
		||||
            # For rootless-only builds, default to stable/latest only
 | 
			
		||||
            if "stable" in buildinfo["tags"] or "latest" in buildinfo["tags"]:
 | 
			
		||||
                versions_to_build.append((version, buildinfo))
 | 
			
		||||
        else:
 | 
			
		||||
            versions_to_build.append((version, buildinfo))
 | 
			
		||||
    
 | 
			
		||||
    # Build regular images
 | 
			
		||||
    if build_regular:
 | 
			
		||||
        print("Building regular images...")
 | 
			
		||||
        for version, buildinfo in versions_to_build:
 | 
			
		||||
            sha256 = buildinfo["sha256"]
 | 
			
		||||
            tags = buildinfo["tags"]
 | 
			
		||||
            build_and_push(sha256, version, tags, args.push_tags, args.multiarch)
 | 
			
		||||
    
 | 
			
		||||
    # Build rootless images
 | 
			
		||||
    if build_rootless:
 | 
			
		||||
        print("Building rootless images...")
 | 
			
		||||
        # For rootless, only build stable and latest unless building both
 | 
			
		||||
        rootless_versions = []
 | 
			
		||||
        if not build_regular or args.only_stable_latest:
 | 
			
		||||
            for version, buildinfo in builddata.items():
 | 
			
		||||
                if "stable" in buildinfo["tags"] or "latest" in buildinfo["tags"]:
 | 
			
		||||
                    rootless_versions.append((version, buildinfo))
 | 
			
		||||
        else:
 | 
			
		||||
            rootless_versions = versions_to_build
 | 
			
		||||
            
 | 
			
		||||
        for version, buildinfo in rootless_versions:
 | 
			
		||||
            sha256 = buildinfo["sha256"]
 | 
			
		||||
            original_tags = buildinfo["tags"]
 | 
			
		||||
            rootless_tags = generate_rootless_tags(original_tags)
 | 
			
		||||
            build_and_push(sha256, version, rootless_tags, args.push_tags, args.multiarch, 
 | 
			
		||||
                         dockerfile="Dockerfile.rootless", builder_suffix="-rootless")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
		Reference in New Issue
	
	Block a user