Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/gui-build-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: GUI Build Test

on:
pull_request:
workflow_dispatch:

permissions:
contents: read
jobs:
test-gui-build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Build the GUI Docker image
run: sudo docker build -t arch-iso-gui -f Dockerfile.gui .

- name: Run the GUI container
run: sudo docker run --rm --privileged -d -p 8080:8080 --name arch-iso-gui-test -v $(pwd):/workdir arch-iso-gui

- name: Wait for the server to start
run: sleep 15

- name: Trigger ISO build and wait for completion
# This step triggers the build via the API and waits for the "BUILD_SUCCESS" message.
# The build can take a long time, so a generous timeout is set.
run: |
curl -N --max-time 7200 http://localhost:8080/build | tee build.log
grep -q "BUILD_SUCCESS" build.log

- name: Verify ISO file was created
run: sudo docker exec arch-iso-gui-test test -f /workdir/out/Arch.iso

- name: Test ISO download endpoint
run: curl -f -I http://localhost:8080/download | grep -q 'Content-Disposition: attachment; filename=Arch.iso'

- name: Stop the container
if: always()
run: sudo docker stop arch-iso-gui-test
40 changes: 40 additions & 0 deletions Dockerfile.gui
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Use the same builder as the original Dockerfile
FROM archlinux:latest AS builder

# Set up parallel downloads and other optimizations
COPY pacman.conf /etc/pacman.conf

# Update system and install necessary packages
RUN pacman -Syu --noconfirm && \
pacman -S --noconfirm --needed \
git \
archiso \
grub \
base-devel \
python-flask \
&& pacman -Scc --noconfirm

# Set the working directory
WORKDIR /build

# Copy only necessary files for package installation
COPY packages.x86_64 bootstrap_packages.x86_64 profiledef.sh ./

# Create a new final image
FROM builder AS final

# Set the working directory
WORKDIR /workdir

# Copy the rest of the files
COPY . .

# Use an entrypoint script for better flexibility
COPY ./scripts/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Expose the port for the web GUI
EXPOSE 8080

# Set the entrypoint to run the Flask application
ENTRYPOINT ["python", "app.py"]
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,55 @@ To install Docker, follow the instructions for your operating system:

Once the process completes, the ISO will be available in the `out/` directory within your local folder as `Arch.iso`.

---

## How to Build the ISO with a GUI

For a more user-friendly experience, you can use a Docker container that provides a web-based graphical user interface (GUI) to build the ISO.

### Prerequisites

Ensure you have Docker installed and running on your system.

### Steps to Build with the GUI

1. **Clone the repository**:

```bash
git clone https://github.com/Githubguy132010/Arch-Linux-without-the-beeps.git
cd Arch-Linux-without-the-beeps
```

2. **Build the GUI Docker Image**:

Build the Docker image for the GUI application.

```bash
docker build -t arch-iso-gui -f Dockerfile.gui .
```

3. **Run the GUI Container**:

Run the container, mapping port 8080 to your host system.

```bash
docker run --rm --privileged -p 8080:8080 -v $(pwd):/workdir arch-iso-gui
```

4. **Access the GUI**:

Open your web browser and navigate to `http://localhost:8080`.

5. **Build the ISO**:

Click the "Build ISO" button to start the build process. The logs will be displayed in real-time on the page.

6. **Download the ISO**:

Once the build is complete, a download link for `Arch.iso` will appear.

---

## How to Use GitHub Actions (Automated Workflow)

This repository also includes a GitHub Actions workflow for building and releasing the ISO automatically on GitHub.
Expand Down
45 changes: 45 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import os
import subprocess
from flask import Flask, render_template, Response, send_from_directory

app = Flask(__name__)
ISO_DIR = "/workdir/out"
ISO_NAME = "Arch.iso"
ISO_PATH = os.path.join(ISO_DIR, ISO_NAME)

@app.route('/')
def index():
return render_template('index.html')

@app.route('/build')
def build():
def generate():
# Ensure the output directory exists
os.makedirs(ISO_DIR, exist_ok=True)

# Command to execute the build script
command = ["/entrypoint.sh", "build", "out", "work"]

process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1, universal_newlines=True)

for line in process.stdout:
yield f"data: {line}\n\n"

process.wait()

if process.returncode == 0:
yield "data: BUILD_SUCCESS\n\n"
else:
yield "data: BUILD_FAILED\n\n"

return Response(generate(), mimetype='text/event-stream')

@app.route('/download')
def download():
if os.path.exists(ISO_PATH):
return send_from_directory(directory=ISO_DIR, path=ISO_NAME, as_attachment=True)
else:
return "ISO not found.", 404

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
60 changes: 60 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Arch ISO Builder</title>
<style>
body { font-family: sans-serif; margin: 2em; }
#log { white-space: pre-wrap; background-color: #f4f4f4; border: 1px solid #ddd; padding: 1em; height: 400px; overflow-y: scroll; }
#buildBtn { padding: 0.5em 1em; font-size: 1em; }
#downloadLinkContainer { margin-top: 1em; }
</style>
</head>
<body>
<h1>Arch Linux ISO Builder</h1>
<button id="buildBtn">Build ISO</button>
<h2>Build Log</h2>
<pre id="log"></pre>
<div id="downloadLinkContainer"></div>

<script>
const buildBtn = document.getElementById('buildBtn');
const log = document.getElementById('log');
const downloadLinkContainer = document.getElementById('downloadLinkContainer');

buildBtn.addEventListener('click', () => {
buildBtn.disabled = true;
log.textContent = 'Starting build...\n';
downloadLinkContainer.innerHTML = '';

const eventSource = new EventSource('/build');

eventSource.onmessage = function(event) {
if (event.data === 'BUILD_SUCCESS') {
log.textContent += '\nBuild finished successfully!\n';
const downloadLink = document.createElement('a');
downloadLink.href = '/download';
downloadLink.textContent = 'Download ISO';
downloadLinkContainer.appendChild(downloadLink);
eventSource.close();
buildBtn.disabled = false;
} else if (event.data === 'BUILD_FAILED') {
log.textContent += '\nBuild failed!\n';
eventSource.close();
buildBtn.disabled = false;
} else {
log.textContent += event.data + '\n';
log.scrollTop = log.scrollHeight;
}
};

eventSource.onerror = function() {
log.textContent += '\nError connecting to the server.\n';
eventSource.close();
buildBtn.disabled = false;
};
});
</script>
</body>
</html>