From bf6a044f932b1a1bbeaf73004491c37e7f1cd13c Mon Sep 17 00:00:00 2001 From: humocs-man <251756307+humocs-man@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:29:29 +0200 Subject: [PATCH] Delete AGENTS.md --- AGENTS.md | 1108 ----------------------------------------------------- 1 file changed, 1108 deletions(-) delete mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 6c5908d..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,1108 +0,0 @@ -# Copilot Instructions for finpilot bootc Image Template - -## CRITICAL: GitHub API Usage - -**ALWAYS use GitHub API for external references:** -- When researching other repositories (e.g., projectbluefin/distroless, ublue-os/bluefin) -- When checking Containerfiles, build scripts, or configuration files -- Use the `github-mcp-server-get_file_contents` tool instead of curl/wget -- This ensures consistent, authenticated access and better error handling - -## CRITICAL: Pre-Commit Checklist - -**Execute before EVERY commit:** -1. **Conventional Commits** - ALL commits MUST follow conventional commit format (see below) -2. **Shellcheck** - `shellcheck *.sh` on all modified shell files -3. **YAML validation** - `python3 -c "import yaml; yaml.safe_load(open('file.yml'))"` on all modified YAML -4. **Justfile syntax** - `just --list` to verify -5. **Confirm with user** - Always confirm before committing and pushing - -**Never commit files with syntax errors.** - -### REQUIRED: Conventional Commit Format - -**ALL commits MUST use conventional commits format** - -``` -[optional scope]: -``` - -## CRITICAL: Template Initialization - -**When this repository is used as a template, you MUST:** - -### 1. Rename ALL instances of `finpilot` - -**Source of truth**: `Containerfile` line 9: `# Name: finpilot` - -**Files to update:** -- `Containerfile` (line 9) -- `Justfile` (line 1) -- `README.md` (line 1) -- `artifacthub-repo.yml` (line 5) -- `custom/ujust/README.md` (~line 175) -- `.github/workflows/ghcr-pruner.yml` (line 22) - -### 2. Create "What's Different" section in README - -**CRITICAL**: Add this section near the top of README.md (after the title/intro, before detailed docs): - -```markdown -## What Makes this Raptor Different? - -Here are the changes from [Base Image Name]. This image is based on [Bluefin/Bazzite/Aurora/etc] and includes these customizations: - -### Added Packages (Build-time) -- **System packages**: tmux, micro, mosh - [brief explanation of why] - -### Added Applications (Runtime) -- **CLI Tools (Homebrew)**: neovim, helix - [brief explanation] -- **GUI Apps (Flatpak)**: Spotify, Thunderbird - [brief explanation] - -### Removed/Disabled -- List anything removed from base image - -### Configuration Changes -- Any systemd services enabled/disabled -- Desktop environment changes -- Other notable modifications - -*Last updated: [date]* -``` - -**Maintenance requirement**: -- **ALWAYS update this section when you modify packages or configuration** -- Keep descriptions brief and user-focused (explain "why", not just "what") -- Write for typical Linux users, not developers -- Update the "Last updated" date with each change - -### 3. Verify copilot instructions are present - -Confirm `.github/copilot-instructions.md` exists in the new repository. This file should be automatically copied when using this as a GitHub template. - -### 4. Explain signing is optional - -Signing is DISABLED by default. First builds succeed immediately. Enable later for production (see README). - -**These 4 steps are REQUIRED for every new template instance.** - ---- - -## Repository Structure - -``` -├── Containerfile # Main build definition (multi-stage build with OCI imports) -├── Justfile # Local build automation (image name, build commands) -├── build/ # Build-time scripts (10-build.sh, 20-chrome.sh, etc.) -│ ├── 10-build.sh # Main build script (copy custom files, install packages) -│ ├── 20-*.sh.example # Example third-party repos (rename to use) -│ ├── 30-*.sh.example # Example desktop replacement (rename to use) -│ ├── copr-helpers.sh # Helper functions for COPR repositories -│ └── README.md # Build scripts documentation -├── custom/ # User customizations (NOT in container, installed at runtime/first boot) -│ ├── brew/ # Homebrew Brewfiles (CLI tools, dev tools) -│ │ ├── default.Brewfile # General CLI tools -│ │ ├── development.Brewfile # Dev environments -│ │ ├── fonts.Brewfile # Font packages -│ │ └── README.md # Homebrew documentation -│ ├── flatpaks/ # Flatpak preinstall (GUI apps, post-first-boot) -│ │ ├── default.preinstall # Default GUI apps (INI format) -│ │ └── README.md # Flatpak documentation -│ └── ujust/ # User commands (shortcuts to Brewfiles, system tasks) -│ ├── custom-apps.just # App installation shortcuts -│ ├── custom-system.just # System maintenance commands -│ └── README.md # ujust documentation -├── iso/ # Local testing only (no CI/CD) -│ ├── disk.toml # VM/disk image config (QCOW2/RAW) -│ ├── iso.toml # ISO installer config (bootc switch URL) -│ └── rclone/ # Upload configs (Cloudflare R2, AWS S3, etc.) -├── .github/ # GitHub configuration and CI/CD -│ ├── workflows/ # GitHub Actions workflows -│ │ ├── build.yml # Builds :stable on main -│ │ ├── clean.yml # Deletes images >90 days old -│ │ ├── renovate.yml # Renovate bot updates (6h interval) -│ │ ├── validate-*.yml # Pre-merge validation checks -│ │ └── ... -│ ├── copilot-instructions.md # THIS FILE - Instructions for Copilot -│ ├── SETUP_CHECKLIST.md # Quick setup checklist for users -│ ├── commit-convention.md # Conventional commits guide -│ └── renovate.json5 # Renovate configuration -├── .pre-commit-config.yaml # Pre-commit hooks (optional local use) -└── .gitignore # Prevents committing secrets (cosign.key, etc.) -``` - ---- - -## Core Principles - -### Multi-Stage Build Architecture -This template follows the **Bluefin architecture pattern** from @projectbluefin/distroless: - -**Architecture Layers:** -1. **Context Stage (ctx)** - Combines resources from multiple sources: - - Local build scripts (`/build`) - - Local custom files (`/custom`) - - **@projectbluefin/common** - Desktop configuration shared with Aurora (`/oci/common`) - - **@projectbluefin/branding** - Branding assets (`/oci/branding`) - - **@ublue-os/artwork** - Artwork shared with Aurora and Bazzite (`/oci/artwork`) - - **@ublue-os/brew** - Homebrew integration (`/oci/brew`) - -2. **Base Image Options:** - - `ghcr.io/ublue-os/silverblue-main:42` (Fedora-based, default) - - `quay.io/centos-bootc/centos-bootc:stream10` (CentOS-based) - -**OCI Container Resources:** -- Resources from OCI containers are copied to **distinct subdirectories** (`/oci/*`) to avoid file conflicts -- Renovate automatically updates `:latest` tags to **SHA digests** for reproducibility -- All OCI resources are mounted at build-time via the `ctx` stage - -**Reference:** See [Bluefin Contributing Guide](https://docs.projectbluefin.io/contributing/) for architecture diagram - -### Build-time vs Runtime -- **Build-time** (`build/`): Baked into container. Use `dnf5 install`. Services, configs, system packages. -- **Runtime** (`custom/`): User installs after deployment. Use Brewfiles, Flatpaks. CLI tools, GUI apps, dev environments. - -### Bluefin Convention Compliance -**ALWAYS follow @ublue-os/bluefin patterns. Confirm before deviating.** -- Use `dnf5` exclusively (never `dnf`, `yum`, `rpm-ostree`) -- Always `-y` flag for non-interactive -- COPRs: enable → install → **DISABLE** (critical, prevents repo persistence) -- Use `copr_install_isolated` function pattern -- Numbered scripts: `10-build.sh`, `20-chrome.sh`, `30-cosmic.sh` -- Check @bootc-dev for container best practices - -### Branch Strategy -- **main** = Production releases ONLY. Never push directly. Builds `:stable` images. -- **Conventional Commits** = REQUIRED. `feat:`, `fix:`, `chore:`, etc. -- **Workflows** = All validation happens on PRs. Merging to main triggers stable builds. - -### Validation Workflows -The repository includes automated validation on pull requests: -- **validate-shellcheck.yml** - Runs shellcheck on all `build/*.sh` scripts -- **validate-brewfiles.yml** - Validates Homebrew Brewfile syntax -- **validate-flatpaks.yml** - Checks Flatpak app IDs exist on Flathub -- **validate-justfiles.yml** - Validates just file syntax -- **validate-renovate.yml** - Validates Renovate configuration - -**When adding files**: These validations run automatically on PRs. Fix any errors before merge. - ---- - -## Where to Add Packages - -This section provides clear guidance on where to add different types of packages. - -### System Packages (dnf5 - Build-time) - -**Location**: `build/10-build.sh` - -System packages are installed at build-time and baked into the container image. Use `dnf5` exclusively. - -**Example**: -```bash -# In build/10-build.sh -dnf5 install -y vim git htop neovim tmux -``` - -**When to use**: -- System utilities and services -- Dependencies required for other build-time operations -- Packages that need to be available immediately on first boot -- Services that need to be enabled with `systemctl enable` - -**Important**: -- Always use `dnf5` (never `dnf`, `yum`, or `rpm-ostree`) -- Always add `-y` flag for non-interactive installs -- For COPR repositories, use `copr_install_isolated` pattern and disable after use -- For third-party repos, see example scripts: `build/20-onepassword.sh.example` - -**Script Naming Convention**: -- `10-build.sh` - Main build script (always runs first) -- `20-*.sh` - Additional scripts (run in numerical order) -- `30-*.sh` - Desktop environment changes -- `.example` suffix - Rename to `.sh` to activate - -### Homebrew Packages (Brew - Runtime) - -**Location**: `custom/brew/*.Brewfile` - -Homebrew packages are installed by users after deployment. Best for CLI tools and development environments. - -**Files**: -- `custom/brew/default.Brewfile` - General purpose CLI tools -- `custom/brew/development.Brewfile` - Development tools and environments -- `custom/brew/fonts.Brewfile` - Font packages -- Create custom `*.Brewfile` as needed - -**Example**: -```ruby -# In custom/brew/default.Brewfile -brew "bat" # cat with syntax highlighting -brew "eza" # Modern replacement for ls -brew "ripgrep" # Faster grep -brew "fd" # Simple alternative to find -``` - -**When to use**: -- CLI tools and utilities -- Development tools (node, python, go, etc.) -- User-specific tools that don't need to be in the base image -- Tools that update frequently - -**Important**: -- Brewfiles use Ruby syntax -- Users install via `ujust` commands (e.g., `ujust install-default-apps`) -- Not installed in ISO/container - users install after deployment - -### Flatpak Applications (GUI Apps - Runtime) - -**Location**: `custom/flatpaks/*.preinstall` - -Flatpak applications are GUI apps installed after first boot. Use INI format. - -**Files**: -- `custom/flatpaks/default.preinstall` - Default GUI applications -- Create custom `*.preinstall` files as needed - -**Example**: -```ini -# In custom/flatpaks/default.preinstall -[Flatpak Preinstall org.mozilla.firefox] -Branch=stable - -[Flatpak Preinstall com.visualstudio.code] -Branch=stable - -[Flatpak Preinstall org.gnome.Calculator] -Branch=stable -``` - -**When to use**: -- GUI applications -- Desktop apps (browsers, editors, media players) -- Apps that users expect to have immediately available -- Apps from Flathub (https://flathub.org/) - -**Important**: -- Installed post-first-boot (not in ISO/container) -- Requires internet connection -- Find app IDs at https://flathub.org/ -- Use INI format with `[Flatpak Preinstall APP_ID]` sections -- Always specify `Branch=stable` (or another branch) - ---- - -## Quick Reference: Common User Requests - -| Request | Action | Location | -|---------|--------|----------| -| Add package (build-time) | `dnf5 install -y pkg` | `build/10-build.sh` | -| Add package (runtime) | `brew "pkg"` | `custom/brew/default.Brewfile` | -| Add GUI app | `[Flatpak Preinstall org.app.id]` | `custom/flatpaks/default.preinstall` | -| Add user command | Create shortcut (NO dnf5) | `custom/ujust/*.just` | -| Add third-party repo | Use example scripts | `build/20-*.sh.example` (rename) | -| Replace desktop | Use example script | `build/30-cosmic-desktop.sh.example` | -| Switch base image | Update FROM line | `Containerfile` line 38 | -| Add OCI containers | Uncomment COPY --from= lines | `Containerfile` lines 13-18 (ctx stage) | -| Test locally | `just build && just build-qcow2 && just run-vm-qcow2` | Terminal | -| Deploy (production) | `sudo bootc switch ghcr.io/user/repo:stable` | Terminal | -| Enable service | `systemctl enable service.name` | `build/10-build.sh` | -| Add COPR | enable → install → **DISABLE** | `build/10-build.sh` | -| Validate changes | Automatic on PR | `.github/workflows/validate-*.yml` | - ---- - -## Detailed Workflows - -### 1. Multi-Stage Build Architecture - -**File**: `Containerfile` - -This template uses a **multi-stage build** following the @projectbluefin/distroless pattern. - -**Stage 1: Context (ctx) - Line 39** -Combines resources from multiple OCI containers: -```dockerfile -FROM scratch AS ctx - -COPY build /build -COPY custom /custom -# Import from OCI containers - Renovate updates :latest to SHA-256 digests -COPY --from=ghcr.io/ublue-os/base-main:latest /system_files /oci/base -COPY --from=ghcr.io/projectbluefin/common:latest /system_files /oci/common -COPY --from=ghcr.io/projectbluefin/branding:latest /system_files /oci/branding -COPY --from=ghcr.io/ublue-os/artwork:latest /system_files /oci/artwork -COPY --from=ghcr.io/ublue-os/brew:latest /system_files /oci/brew -``` - -**Stage 2: Base Image - Line 52** -```dockerfile -FROM ghcr.io/ublue-os/silverblue-main:latest # Default (Fedora-based) -# OR -FROM quay.io/centos-bootc/centos-bootc:stream10 # CentOS-based -``` - -**Common alternative base images**: -```dockerfile -FROM ghcr.io/ublue-os/bluefin:stable # Dev, GNOME, `:stable` or `:gts` -FROM ghcr.io/ublue-os/bazzite:stable # Gaming, Steam Deck -FROM ghcr.io/ublue-os/aurora:stable # KDE Plasma -FROM quay.io/fedora/fedora-bootc:42 # Upstream Fedora -``` - -**Tags**: `:stable` (recommended), `:latest` (bleeding edge), `-nvidia` variants available - -**Renovate**: Base image SHA and OCI container tags are auto-updated by Renovate bot every 6 hours (see `.github/renovate.json5`) - -**OCI Container Resources:** -- **@ublue-os/base-main** - Base system configuration -- **@projectbluefin/common** - Desktop configuration shared with Aurora -- **@projectbluefin/branding** - Branding assets -- **@ublue-os/artwork** - Artwork shared with Aurora and Bazzite -- **@ublue-os/brew** - Homebrew integration - -**File Locations in Build Scripts:** -- Local build scripts: `/ctx/build/` -- Local custom files: `/ctx/custom/` -- Base files: `/ctx/oci/base/` -- Common files: `/ctx/oci/common/` -- Branding files: `/ctx/oci/branding/` -- Artwork files: `/ctx/oci/artwork/` -- Brew files: `/ctx/oci/brew/` - -### 2. OCI Containers for Additional System Files - -**File**: `Containerfile` (ctx stage, lines 6-18) - -Following the `@projectbluefin/distroless` pattern, you can layer in additional system files from OCI containers. These are commented out by default in the template. - -**Available OCI Containers**: -```dockerfile -# Artwork and Branding from projectbluefin/common -COPY --from=ghcr.io/projectbluefin/common:latest /system_files/bluefin /files/bluefin -COPY --from=ghcr.io/projectbluefin/common:latest /system_files/shared /files/shared - -# Homebrew system files from ublue-os/brew -COPY --from=ghcr.io/ublue-os/brew:latest /system_files /files/brew -``` - -**What's included**: -- `projectbluefin/common:latest` - Bluefin wallpapers, themes, branding assets, ujust completions, udev rules -- `ublue-os/brew:latest` - Homebrew system integration files - -**When to use**: -- You want Bluefin-specific artwork and wallpapers in your custom image -- You want additional system integration beyond what the base image provides -- You're building a Bluefin derivative and want to maintain brand consistency - -**Important**: -- These are **commented out by default** as template examples -- Uncomment only if you specifically want these additional system files -- The files are copied into the `ctx` stage and made available to your build scripts -- To use the files in your build, you'll need to copy them from `/ctx/files/*` to appropriate system locations in your build scripts - -### 3. Build Scripts (`build/`) - -**Pattern**: Numbered files (`10-build.sh`, `20-chrome.sh`, `30-cosmic.sh`) run in order. - -**Example - `build/10-build.sh`**: -```bash -#!/usr/bin/env bash -set -euo pipefail - -# Install packages -dnf5 install -y vim git htop neovim - -# Enable services -systemctl enable podman.socket - -# Download binaries -curl -L https://example.com/tool -o /usr/local/bin/tool -chmod +x /usr/local/bin/tool -``` - -**Example - COPR pattern** (see `build/20-onepassword.sh`): -```bash -#!/usr/bin/env bash -set -euo pipefail - -source /ctx/copr-install-functions.sh - -# Chrome -dnf config-manager addrepo --from-repofile=https://dl.google.com/linux/linux_signing_key.pub -dnf5 install -y google-chrome-stable - -# 1Password via COPR (isolated) -copr_install_isolated username/repo package-name -``` - -**Example - Desktop swap** (see `build/30-cosmic.sh`): -```bash -#!/usr/bin/env bash -set -euo pipefail - -# Remove GNOME, install COSMIC -dnf5 group remove -y "GNOME Desktop Environment" -dnf5 copr enable -y ryanabx/cosmic-epoch -dnf5 install -y cosmic-desktop -dnf5 copr disable -y ryanabx/cosmic-epoch -systemctl set-default graphical.target -``` - -**CRITICAL**: Use `copr_install_isolated` function. Always disable COPRs. - -**Example scripts**: See `build/20-onepassword.sh.example` and `build/30-cosmic-desktop.sh.example` for complete working examples. - -### 4. Homebrew (`custom/brew/`) - -**Files**: `*.Brewfile` (Ruby syntax) - -**Example - `custom/brew/default.Brewfile`**: -```ruby -# CLI tools -brew "bat" # Better cat -brew "eza" # Better ls -brew "ripgrep" # Better grep -brew "fd" # Better find - -# Dev tools -tap "homebrew/cask" -brew "node" -brew "python" -``` - -**Users install via**: `ujust install-default-apps` (create shortcut in `custom/ujust/`) - -### 5. ujust Commands (`custom/ujust/`) - -**Files**: `*.just` (all auto-consolidated) - -**Example - `custom/ujust/apps.just`**: -```just -[group('Apps')] -install-default-apps: - #!/usr/bin/env bash - brew bundle --file /usr/share/ublue-os/homebrew/default.Brewfile - -[group('Apps')] -install-dev-tools: - #!/usr/bin/env bash - brew bundle --file /usr/share/ublue-os/homebrew/development.Brewfile -``` - -**RULES**: -- **NEVER** use `dnf5` in ujust - only Brewfile/Flatpak shortcuts -- Use `[group('Category')]` for organization -- All `.just` files merged during build - -### 6. Flatpaks (`custom/flatpaks/`) - -**Files**: `*.preinstall` (INI format, installed after first boot) - -**Example - `custom/flatpaks/default.preinstall`**: -```ini -[Flatpak Preinstall org.mozilla.firefox] -Branch=stable - -[Flatpak Preinstall org.gnome.Calculator] -Branch=stable - -[Flatpak Preinstall com.visualstudio.code] -Branch=stable -``` - -**Important**: Not in ISO/container. Installed post-first-boot. Requires internet. Find IDs at https://flathub.org/ - -### 7. ISO/Disk Images (`iso/`) - -**For local testing only. No CI/CD.** - -**Files**: -- `iso/disk.toml` - VM images (QCOW2/RAW): `just build-qcow2` -- `iso/iso.toml` - Installer ISO: `just build-iso` - -**CRITICAL** - Update bootc switch URL in `iso/iso.toml`: -```toml -[customizations.installer.kickstart] -contents = """ -%post -bootc switch --mutate-in-place --transport registry ghcr.io/USERNAME/REPO:stable -%end -""" -``` - -**Upload**: Use `iso/rclone/` configs (Cloudflare R2, AWS S3, Backblaze B2, SFTP) - -### 8. Release Workflow - -**Branches**: -- `main` - Production only. Builds `:stable` images. Never push directly. - -**Workflows**: -- `build.yml` - Builds `:stable` on main -- `renovate.yml` - Monitors base image updates (every 6 hours) -- `clean.yml` - Deletes images >90 days (weekly) -- `validate-*.yml` - Pre-merge validation (shellcheck, Brewfile, Flatpak, etc.) - -**Image Tags**: -- `:stable` - Latest stable release from main branch -- `:stable.YYYYMMDD` - Datestamped stable release -- `:YYYYMMDD` - Date only -- `:pr-123` - Pull request builds (for testing) -- `:sha-abc123` - Git commit SHA (short) - -**Renovate Bot**: -- Automatically updates base image SHAs in `Containerfile` -- Runs every 6 hours (configured in `.github/renovate.json5`) -- Creates PRs for updates - review and merge to keep images current - -### 8. Understanding the Multi-Stage Build Architecture - -This template implements a **multi-stage build pattern** following @projectbluefin/distroless. - -**Why Multi-Stage?** -- **Modularity**: Combine resources from multiple OCI containers -- **Reusability**: Share common components across different images -- **Maintainability**: Update shared components independently -- **Reproducibility**: Renovate updates OCI container tags to SHA digests - -**Stage Breakdown:** - -**Stage 1: Context (ctx)** -```dockerfile -FROM scratch AS ctx -COPY build /build # Local build scripts -COPY custom /custom # Local customizations -COPY --from=ghcr.io/projectbluefin/common:latest /system_files /oci/common -COPY --from=ghcr.io/projectbluefin/branding:latest /system_files /oci/branding -COPY --from=ghcr.io/ublue-os/artwork:latest /system_files /oci/artwork -COPY --from=ghcr.io/ublue-os/brew:latest /system_files /oci/brew -``` - -This stage combines: -- **Local resources** (build scripts, custom files) -- **OCI container resources** from upstream projects -- Resources are copied to **distinct subdirectories** to avoid conflicts - -**Stage 2: Final Image** -```dockerfile -FROM ghcr.io/ublue-os/silverblue-main:42 - -RUN --mount=type=bind,from=ctx,source=/,target=/ctx \ - /ctx/build/10-build.sh -``` - -The final stage: -- Starts from base image -- Mounts the `ctx` stage at `/ctx` -- Runs build scripts with access to all resources - -**Accessing OCI Resources in Build Scripts:** - -Build scripts can access files from OCI containers: -```bash -#!/usr/bin/env bash -# Example: Copy branding files -cp -r /ctx/oci/branding/* /usr/share/branding/ - -# Example: Copy common desktop config -cp /ctx/oci/common/config.yaml /etc/myapp/ - -# Example: Use brew files -cp /ctx/oci/brew/*.sh /usr/local/bin/ -``` - -**Renovate Integration:** -- Renovate monitors OCI container tags (`:latest`) -- Automatically updates to SHA digests for reproducibility -- Example: `:latest` → `@sha256:abc123...` -- Ensures builds are reproducible and verifiable - -**Reference:** See [Bluefin Contributing Guide](https://docs.projectbluefin.io/contributing/) for architecture diagram - -### 9. Image Signing (Optional, Recommended for Production) - -**Default**: DISABLED (commented out in workflows) to allow first builds. -```bash -# Generate keys -COSIGN_PASSWORD="" cosign generate-key-pair -# Creates: cosign.key (SECRET), cosign.pub (COMMIT) - -# Add to GitHub -# Settings → Secrets and Variables → Actions → New secret -# Name: SIGNING_SECRET -# Value: - -# Uncomment signing sections in: -# - .github/workflows/build.yml -# - .github/workflows/build-testing.yml -``` - -**NEVER commit `cosign.key`**. Already in `.gitignore`. - ---- - -## Critical Rules (Enforced) - -1. **ALWAYS** use Conventional Commits format for ALL commits (required for Release Please) - - Format: `[scope]: ` - - Valid types: `feat:`, `fix:`, `docs:`, `chore:`, `build:`, `ci:`, `refactor:`, `test:` - - Breaking changes: Add `!` or `BREAKING CHANGE:` in footer - - See `.github/commit-convention.md` for examples -2. **NEVER** commit `cosign.key` to repository -3. **ALWAYS** disable COPRs after use (`copr_install_isolated` function) -4. **ALWAYS** use `dnf5` exclusively (never `dnf`, `yum`, `rpm-ostree`) -5. **ALWAYS** use `-y` flag for non-interactive installs -6. **NEVER** use `dnf5` in ujust files - only Brewfile/Flatpak shortcuts -7. **ALWAYS** work on testing branch for development -8. **ALWAYS** let Release Please handle testing→main merges -9. **NEVER** push directly to main (only via Release Please) -10. **ALWAYS** confirm with user before deviating from @ublue-os/bluefin patterns -11. **ALWAYS** run shellcheck/YAML validation before committing -12. **ALWAYS** update bootc switch URL in `iso/iso.toml` to match user's repo -13. **ALWAYS** follow numbered script convention: `10-*.sh`, `20-*.sh`, `30-*.sh` -14. **ALWAYS** check example scripts before creating new patterns (`.example` files in `build/`) -15. **ALWAYS** validate that new Flatpak IDs exist on Flathub before adding -16. **NEVER** modify validation workflows without understanding impact on PR checks ---- - -## Troubleshooting - -| Symptom | Cause | Solution | -|---------|-------|----------| -| Build fails: "permission denied" | Signing misconfigured | Verify signing commented out OR `SIGNING_SECRET` set | -| Build fails: "package not found" | Typo or unavailable | Check spelling, verify on RPMfusion, add COPR if needed | -| Build fails: "base image not found" | Invalid FROM line | Check syntax in `Containerfile` line 24 | -| Build fails: "shellcheck error" | Script syntax error | Run `shellcheck build/*.sh` locally, fix errors | -| PR validation fails: Brewfile | Invalid Brewfile syntax | Check Ruby syntax, ensure packages exist | -| PR validation fails: Flatpak | Invalid app ID | Verify app ID exists on https://flathub.org/ | -| PR validation fails: justfile | Invalid just syntax | Run `just --list` locally to test | -| Changes not in production | Wrong workflow | Push to main (via PR) to trigger stable builds | -| ISO missing customizations | Wrong bootc URL | Update `iso/iso.toml` bootc switch URL to match repo | -| COPR packages missing after boot | COPR not disabled | COPRs persist if not disabled - use `copr_install_isolated` | -| ujust commands not working | Wrong install location | Files must be in `custom/ujust/` and copied to `/usr/share/ublue-os/just/` | -| Flatpaks not installed | Expected behavior | Flatpaks install post-first-boot, not in ISO/container | -| Local build fails | Wrong environment | Must run on bootc-based system or have podman installed | -| Renovate not creating PRs | Configuration issue | Check `.github/renovate.json5` syntax | -| Third-party repo not working | Repo file persists | Remove repo file at end of script (see examples) | - ---- - -## Common Patterns & Examples - -### Pattern 1: Adding Third-Party RPM Repositories - -**Use case**: Installing Google Chrome, 1Password, VS Code, etc. - -**Example**: See `build/20-onepassword.sh.example` - -**Steps**: -1. Add GPG key (if required) -2. Create repo file in `/etc/yum.repos.d/` -3. Install packages with `dnf5 install -y` -4. **CRITICAL**: Remove repo file at end - -```bash -# Add repo -cat > /etc/yum.repos.d/google-chrome.repo << 'EOF' -[google-chrome] -name=google-chrome -baseurl=https://dl.google.com/linux/chrome/rpm/stable/x86_64 -enabled=1 -gpgcheck=1 -gpgkey=https://dl.google.com/linux/linux_signing_key.pub -EOF - -# Install -dnf5 install -y google-chrome-stable - -# Clean up (required!) -rm -f /etc/yum.repos.d/google-chrome.repo -``` - -### Pattern 2: Using COPR Repositories - -**Use case**: Installing packages from Fedora COPR (community repos) - -**Example**: See `build/copr-helpers.sh` and `build/30-cosmic-desktop.sh.example` - -**Always use `copr_install_isolated` function**: -```bash -source /ctx/build/copr-helpers.sh - -# Install from COPR (isolated - auto-disables after install) -copr_install_isolated "ublue-os/staging" package-name - -# Install multiple packages -copr_install_isolated "ryanabx/cosmic-epoch" \ - cosmic-session \ - cosmic-greeter \ - cosmic-comp -``` - -### Pattern 3: Replacing Desktop Environment - -**Use case**: Swap GNOME for KDE, COSMIC, etc. - -**Example**: See `build/30-cosmic-desktop.sh.example` - -**Steps**: -1. Remove old desktop: `dnf5 remove -y gnome-shell ...` -2. Install new desktop: `copr_install_isolated ...` -3. Configure display manager: `systemctl enable ...` -4. Set default session - -### Pattern 4: Enabling System Services - -**Location**: `build/10-build.sh` - -```bash -# Enable service -systemctl enable podman.socket - -# Mask unwanted service -systemctl mask unwanted-service - -# Set default target -systemctl set-default graphical.target -``` - -### Pattern 5: Creating Custom ujust Commands - -**Location**: `custom/ujust/*.just` - -**Example structure**: -```just -# vim: set ft=make : - -# Install development tools -[group('Apps')] -install-dev-tools: - #!/usr/bin/env bash - echo "Installing development tools..." - brew bundle --file /usr/share/ublue-os/homebrew/development.Brewfile - -# Custom system command -[group('System')] -my-custom-command: - #!/usr/bin/env bash - echo "Running custom command..." - # Your logic here (NO dnf5!) -``` - -### Pattern 6: Local Testing Workflow - -**Complete local testing cycle**: -```bash -# 1. Build container image -just build - -# 2. Build QCOW2 disk image -just build-qcow2 - -# 3. Run in VM -just run-vm-qcow2 - -# Or combine all steps -just build && just build-qcow2 && just run-vm-qcow2 -``` - -**Alternative**: Build ISO for installation testing -```bash -just build -just build-iso -just run-vm-iso -``` - -### Pattern 7: Pre-commit Validation (Optional) - -**Setup pre-commit hooks locally**: -```bash -# Install pre-commit -pip install pre-commit - -# Install hooks -pre-commit install - -# Run manually -pre-commit run --all-files -``` - -**Note**: Pre-commit config exists (`.pre-commit-config.yaml`) but is optional. CI validation runs automatically on PRs. - ---- - -## Advanced Topics - -### /opt Immutability -Some packages (Chrome, Docker Desktop) write to `/opt`. On Fedora, it's symlinked to `/var/opt` (mutable). To make immutable: - -Uncomment `Containerfile` line 20: -```dockerfile -RUN rm /opt && mkdir /opt -``` - -### Multi-Architecture -- Local `just` commands support your platform -- Most UBlue images support amd64/arm64 -- Add `-arm64` suffix if needed: `bluefin-arm64:stable` -- Cross-platform builds require additional setup - -### Custom Build Functions -See `build/copr-install-functions.sh` for reusable patterns: -- `copr_install_isolated` - Enable COPR, install packages, disable COPR -- Follow @ublue-os/bluefin conventions exactly - - - ---- - -## Understanding the Build Process - -### Container Build Flow - -1. **Base Image** - Pulls base image specified in `Containerfile` FROM line -2. **Context Stage** - Mounts `build/` and `custom/` directories -3. **Build Scripts** - Runs scripts in `build/` directory in numerical order: - - `10-build.sh` - Always runs first (copies custom files, installs packages) - - `20-*.sh` - Additional scripts (if present and not .example) - - `30-*.sh` - More scripts (if present and not .example) -4. **Container Lint** - Validates final image with `bootc container lint` -5. **Push to Registry** - Uploads to GitHub Container Registry (ghcr.io) - -### What Gets Included in the Image - -**Build-time (baked into image)**: -- System packages from `dnf5 install` -- Enabled systemd services -- Custom files copied from `/ctx/custom/` to standard locations: - - Brewfiles → `/usr/share/ublue-os/homebrew/` - - ujust files → `/usr/share/ublue-os/just/60-custom.just` - - Flatpak preinstall → `/etc/flatpak/preinstall.d/` - -**Runtime (installed after deployment)**: -- Homebrew packages (user runs `ujust install-*`) -- Flatpak applications (installed on first boot, requires internet) - -### Local vs CI Builds - -**Local builds** (with `just build`): -- Uses your local podman -- Faster for testing -- No signing -- No automatic push to registry - -**CI builds** (GitHub Actions): -- Uses GitHub runners -- Automatic on push/PR -- Includes validation steps -- Can include signing -- Automatic push to ghcr.io - -### Image Layers and Caching - -**Efficient layering**: -- Each `RUN` command creates a new layer -- Layers are cached between builds -- Changes near end of Containerfile = faster rebuilds -- Use `--mount=type=cache` for package managers - -**Best practices**: -- Group related `dnf5 install` commands together -- Don't install and remove in same layer -- Clean up in same RUN command as install - ---- - -## Image Tags Reference - -**Main branch** (production releases): -- `stable` - Latest stable release (recommended) -- `stable.20250129` - Datestamped stable release -- `20250129` - Date only -- `v1.0.0` - Version from Release Please - -**PR builds**: -- `pr-123` - Pull request number -- `sha-abc123` - Git commit SHA (short) - ---- - -## File Modification Priority - -When user requests customization, check in this order: - -1. **`build/10-build.sh`** (50%) - Build-time packages, services, system configs -2. **`custom/brew/`** (20%) - Runtime CLI tools, dev environments -3. **`custom/ujust/`** (15%) - User convenience commands -4. **`custom/flatpaks/`** (5%) - GUI applications -5. **`Containerfile`** (5%) - Base image, /opt config, advanced builds -6. **`Justfile`** (2%) - Image name, build parameters -7. **`iso/*.toml`** (2%) - ISO/disk customization for testing -8. **`.github/workflows/`** (1%) - Metadata, triggers, workflow config - -### Files to AVOID Modifying - -**Do NOT modify unless specifically requested or necessary**: -- `.github/renovate.json5` - Renovate configuration (auto-updates) -- `.github/workflows/validate-*.yml` - Validation workflows -- `.gitignore` - Prevents committing secrets -- `build/copr-helpers.sh` - Helper functions (stable patterns) -- `LICENSE` - Repository license -- `cosign.pub` - Public signing key (regenerate if changing keys) - -**Modify with extreme caution**: -- `.github/workflows/build.yml` - Core build workflow -- `.github/workflows/clean.yml` - Image cleanup -- `Justfile` - Local build automation (users rely on these commands) - ---- - -## Debugging Tips - -### Local Debugging - -**Build failures**: -```bash -# Build with verbose output -podman build --log-level=debug . - -# Check build script syntax -shellcheck build/*.sh - -# Test specific script in container -podman run --rm -it ghcr.io/ublue-os/bluefin:stable bash -# Then run your script commands manually -``` - -**Brewfile issues**: -```bash -# Validate Brewfile syntax -brew bundle check --file custom/brew/default.Brewfile - -# List what would be installed -brew bundle list --file custom/brew/default.Brewfile -``` - -**Just file issues**: -```bash -# Check syntax -just --list - -# Check specific file -just --unstable --fmt --check -f custom/ujust/custom-apps.just - -# Run specific command with debug -just --verbose install-default-apps -``` - -### CI Debugging - -**Check workflow logs**: -1. Go to Actions tab in GitHub -2. Click on failed workflow run -3. Expand failed step -4. Look for error messages - -**Common CI failures**: -- Shellcheck errors: Fix script syntax -- Brewfile validation: Check package names exist -- Flatpak validation: Verify app IDs on Flathub -- Image pull failures: Check base image SHA/tag - -**Test PR before merge**: -```bash -# PR builds are tagged as :pr-NUMBER -podman pull ghcr.io/YOUR_USERNAME/YOUR_REPO:pr-123 -podman run --rm -it ghcr.io/YOUR_USERNAME/YOUR_REPO:pr-123 bash -``` - -### Runtime Debugging - -**After deployment**: -```bash -# Check system info -bootc status - -# Check running services -systemctl list-units --failed - -# Check logs -journalctl -b -p err - -# Check ujust commands available -ujust --list - -# Check Brewfiles location -ls -la /usr/share/ublue-os/homebrew/ - -# Check Flatpak preinstall -ls -la /etc/flatpak/preinstall.d/ -``` - -**Flatpak debugging**: -```bash -# Check Flatpak remotes -flatpak remotes - -# Check installed Flatpaks -flatpak list - -# Install Flatpak manually -flatpak install -y flathub org.mozilla.firefox -``` - -**Homebrew debugging**: -```bash -# Check Homebrew status -brew doctor - -# Check Brewfile -cat /usr/share/ublue-os/homebrew/default.Brewfile - -# Install manually -brew install package-name -``` - ---- - -## Resources & Documentation - -- **Bluefin patterns**: https://github.com/ublue-os/bluefin -- **bootc documentation**: https://github.com/containers/bootc -- **Conventional Commits**: https://www.conventionalcommits.org/ -- **RPMfusion packages**: https://mirrors.rpmfusion.org/ -- **Flatpak IDs**: https://flathub.org/ -- **Homebrew**: https://brew.sh/ -- **Universal Blue**: https://universal-blue.org/ -- **Renovate**: https://docs.renovatebot.com/ -- **GitHub Actions**: https://docs.github.com/en/actions -- **Podman**: https://podman.io/ -- **Justfile**: https://just.systems/ - ---- - -## Other Rules that are Important to the Maintainers - -- Ensure that [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/#specification) are used and enforced for every commit and pull request title. -- Always be surgical with the least amount of code, the project strives to be easy to maintain. - -## Attribution Requirements - -AI agents must disclose what tool and model they are using in the "Assisted-by" commit footer: - -```text -Assisted-by: [Model Name] via [Tool Name] -``` - -Example: - -```text -Assisted-by: Claude 3.5 Sonnet via GitHub Copilot -``` - ---- - -**Last Updated**: 2025-11-14 -**Template Version**: finpilot (Enhanced with comprehensive Copilot instructions) -**Maintainer**: Universal Blue Community