Bluefin Contributor's Guide
This guide provides detailed instructions for contributing to Bluefin, the Fedora Atomic-based developer workstation. Whether you're fixing bugs, adding features, or improving documentation, this guide will help you contribute effectively using the workflows established by the Bluefin maintainer team.
Overview
Repository: @ublue-os/bluefin
License: Apache 2.0
Maintainers: 4 core maintainers (@castrojo, @p5, @m2Giles, @tulilirockz)
Daily Activity: 8-12 commits/day (including automated updates)
Review Time: Manual PRs reviewed within 24-48 hours
Understanding Bluefin's Architecture
Image-Based Development
Bluefin uses OCI container images as the distribution mechanism. Every commit to the repository triggers builds that create bootable OS images. This architecture means:
- Changes are atomic: Updates apply all-or-nothing
- Built-in rollback: Previous deployments remain available
- Container-based builds: All images built via GitHub Actions
- Multi-variant support: Base, DX (developer), nvidia, and gts (LTS) variants
Build System
Bluefin images are built using:
- Containerfile: Defines the base image layers and build arguments
- Build scripts: Located in
build_files/
directory, organized by stage - GitHub Actions: Automated workflows in
.github/workflows/
- Renovate Bot: Automated dependency updates (60% of all commits)
Release Channels
Channel | Purpose | Update Frequency | Fedora Version |
---|---|---|---|
latest | Daily builds | Multiple times per day | 42 (current) |
stable | Weekly builds | Weekly | 42 |
gts | Long-term support | As needed | 41 (LTS) |
Getting Started
Prerequisites
Required Knowledge:
- Git workflow basics
- Container concepts (Podman/Docker)
- Bash scripting fundamentals
- GitHub Actions basics (for CI/CD changes)
Required Tools:
- Git (version 2.x or higher)
- Text editor (VS Code, vim, etc.)
- GitHub account with 2FA enabled
- Podman or Docker (for local builds)
Optional but Recommended:
- Bluefin installation (for testing)
- Access to @ublue-os Discord or discussion forum
Fork and Clone
-
Fork the repository on GitHub to your account:
# Navigate to https://github.com/ublue-os/bluefin
# Click "Fork" in the upper right -
Clone your fork:
git clone https://github.com/YOUR_USERNAME/bluefin.git
cd bluefin -
Add upstream remote:
git remote add upstream https://github.com/ublue-os/bluefin.git
git fetch upstream -
Verify your setup:
git remote -v
# Should show:
# origin https://github.com/YOUR_USERNAME/bluefin.git (fetch)
# origin https://github.com/YOUR_USERNAME/bluefin.git (push)
# upstream https://github.com/ublue-os/bluefin.git (fetch)
# upstream https://github.com/ublue-os/bluefin.git (push)
Contribution Workflow
Finding Work
Help Wanted Issues The easiest way to start is with labeled issues:
# View help wanted issues
open "https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Aublue-os+archived%3Afalse+label%3A%22help+wanted%22"
Common Contribution Areas:
- 🐛 Bug fixes: Issues labeled
bug
- 📦 Package additions: Issues labeled
enhancement
- 📝 Documentation: Issues labeled
documentation
- 🔧 Build improvements: Issues labeled
just
orgithub_actions
- 🎨 DX features: Issues labeled
dx
Branching Strategy
-
Always branch from main:
git checkout main
git pull upstream main -
Create a descriptive feature branch:
# For a bug fix
git checkout -b fix/cockpit-startup-crash
# For a feature
git checkout -b feat/add-bazaar-integration
# For documentation
git checkout -b docs/improve-local-build-guide
# For chores/maintenance
git checkout -b chore/update-copr-repos -
Branch naming conventions:
fix/
: Bug fixesfeat/
: New featuresdocs/
: Documentation changeschore/
: Maintenance tasksrefactor/
: Code refactoring
Making Changes
File Structure Overview
bluefin/
├── .github/
│ └── workflows/ # GitHub Actions CI/CD
│ ├── build-image-*.yml # Image build workflows
│ ├── reusable-build.yml # Shared build logic
│ └── clean.yml # Cleanup workflows
├── build_files/
│ ├── base/ # Base image build scripts
│ ├── shared/ # Shared utilities and scripts
│ └── dx/ # Developer edition scripts
├── system_files/
│ └── shared/ # Files copied into the image
├── flatpaks/ # Flatpak app lists
├── just/ # Just recipes (ujust commands)
├── iso_files/ # ISO-specific configurations
├── packages.json # Package manifest
└── Containerfile # Main image definition
Common Change Types
1. Adding a Package
Edit packages.json
:
vim packages.json
Add your package to the appropriate array:
{
"all": {
"include": {
"rpm": ["existing-package", "your-new-package"]
}
}
}
3. Adding a Just Recipe
Create or edit a file in just/
:
vim just/60-custom.just
Add your recipe:
# Install custom development tool
install-custom-tool:
#!/usr/bin/env bash
set -euxo pipefail
echo "Installing custom tool..."
toolbox run sudo dnf install -y custom-tool
4. Modifying Build Scripts
Build scripts are numbered by execution order. Common scripts:
04-packages.sh
: Package installation05-override-install.sh
: RPM overrides07-base-image-changes.sh
: System modifications17-cleanup.sh
: Cleanup operations
Always test your changes with a local build (see Testing section).
5. Adding Flatpaks
Edit the appropriate flatpak list file:
# For all Bluefin variants
edit flatpaks/bluefin-list.txt
# For DX variant only
edit flatpaks/bluefin-dx-list.txt
Add Flatpak IDs (one per line):
com.example.NewApp
Commit Message Format
Bluefin uses Conventional Commits enforced by CI:
Format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat
: New featurefix
: Bug fixdocs
: Documentation changeschore
: Maintenance tasksrefactor
: Code refactoringtest
: Testing additions/changesstyle
: Code style changesperf
: Performance improvements
Examples from Actual Bluefin Commits:
# Simple fix
git commit -m "fix: remove cockpit and brew setup functions"
# Feature addition
git commit -m "feat: add bazaar flatpak to default installation"
# Chore with scope
git commit -m "chore(deps): update ghcr.io/ublue-os/silverblue-main:latest docker digest to 9168d7d"
# Documentation
git commit -m "docs: explain hat wobble"
# Multi-line with explanation
git commit -m "fix: Remove unused terminal and VFIO configurations
These configurations were causing conflicts with default GNOME settings
and are no longer needed with the updated kernel modules."
Commit Message Tips:
- Keep subject line under 72 characters
- Use imperative mood ("add" not "added" or "adds")
- Don't end subject line with a period
- Provide context in the body for complex changes
- Reference issues with
Fixes #123
orCloses #456
Making the Commit
# Stage your changes
git add path/to/modified/file.sh
# Or stage all changes
git add .
# Review what you're committing
git diff --cached
# Commit with message
git commit -m "feat(just): add custom development tool installer"
# Or use an editor for multi-line commits
git commit
Pushing Changes
# Push to your fork
git push origin feat/add-bazaar-integration
# If you need to force push after amending (use with caution)
git push origin feat/add-bazaar-integration --force-with-lease
Testing Your Changes
Local Build Testing
Option 1: Full Container Build (Recommended for maintainers)
# Build the base image
podman build -t bluefin-test:latest .
# Build with specific arguments
podman build \
--build-arg FEDORA_MAJOR_VERSION=42 \
--build-arg IMAGE_NAME=bluefin \
-t bluefin-test:latest \
.
Option 2: Script Testing (Faster for script changes)
# Test a specific build script
podman run --rm -it \
-v "$(pwd)/build_files:/build_files:ro" \
ghcr.io/ublue-os/silverblue-main:42 \
bash /build_files/base/04-packages.sh
Option 3: GitHub Actions Build (Use PR builds)
When you open a PR, GitHub Actions automatically builds your changes. Check the Actions tab for:
- Build logs
- Success/failure status
- Build artifacts
Testing on Your System
Using PR Images:
Every PR generates a test image. You can rebase to it:
# Find the PR number (e.g., #3322)
# Rebase to the PR image
sudo bootc switch ghcr.io/ublue-os/bluefin:pr-3322
# Reboot to test
sudo systemctl reboot
# If it works, leave feedback on the PR
# If it doesn't work, revert to stable
sudo bootc switch ghcr.io/ublue-os/bluefin:stable
sudo systemctl reboot
Testing Just Recipes:
# List available recipes
ujust
# Test your new recipe
ujust install-custom-tool
# Check for errors in the output
Linting and Validation
Shell Script Linting:
# Install shellcheck if not present
brew install shellcheck
# Lint shell scripts
shellcheck build_files/base/*.sh
Container Linting:
# Use hadolint for Containerfile
podman run --rm -i hadolint/hadolint < Containerfile
JSON Validation:
# Validate packages.json
jq empty packages.json && echo "Valid JSON" || echo "Invalid JSON"
Opening a Pull Request
Pre-PR Checklist
- Code follows existing patterns in the repository
- Commit messages use Conventional Commits format
- Changes are tested (locally or via understanding of impact)
- Documentation updated if needed
- No unrelated changes included
- Branch is up-to-date with upstream main
Creating the PR
-
Push your branch (if not already done):
git push origin your-branch-name
-
Open PR on GitHub:
- Navigate to https://github.com/ublue-os/bluefin
- Click "Pull requests" → "New pull request"
- Click "compare across forks"
- Select your fork and branch
- Click "Create pull request"
-
Fill out PR description:
## Description
Brief description of what this PR does.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Code refactoring
- [ ] Build/CI improvement
## Testing Done
- Local build: Yes/No
- Tested on running system: Yes/No
- Just recipes tested: Yes/No
## Related Issues
Fixes #123
PR Review Process
What Happens Next:
- Automated checks run: CI builds your changes
- Size label applied: PR size labeled automatically (XS, S, M, L, XL)
- Maintainer review: Usually within 24-48 hours
- Feedback addressed: Make changes if requested
- Approval and merge: Once approved, maintainers merge
During Review:
If changes are requested:
# Make the requested changes
vim path/to/file
# Commit the changes
git add path/to/file
git commit -m "fix: address review feedback on error handling"
# Push to update the PR
git push origin your-branch-name
After Merge:
# Switch back to main
git checkout main
# Pull the latest changes
git pull upstream main
# Update your fork
git push origin main
# Delete your feature branch
git branch -d your-branch-name
git push origin --delete your-branch-name
Advanced Workflows
Working with Renovate Bot
Understanding Renovate:
- Renovate creates PRs for dependency updates automatically
- Updates include: base images, GitHub Actions, container digests
- Auto-merge is enabled for low-risk updates
- Accounts for 60% of all commits
Common Renovate PRs:
chore(deps): update ghcr.io/ublue-os/silverblue-main:latest docker digest to abc123
chore(deps): update softprops/action-gh-release digest to def456
When Renovate Conflicts with Your PR:
# Rebase on latest main
git checkout your-branch
git fetch upstream
git rebase upstream/main
# Resolve conflicts if any
git mergetool # or manually edit files
# Continue rebase
git rebase --continue
# Force push (your PR, your branch)
git push origin your-branch --force-with-lease
Multi-Commit PRs
For larger features:
# Create logical commits as you work
git add file1.sh
git commit -m "feat: add base functionality"
git add file2.sh
git commit -m "feat: add error handling"
git add file3.sh
git commit -m "docs: document new feature"
# Push all commits
git push origin your-branch
Amending Commits
# Stage additional changes
git add forgotten-file.sh
# Amend the last commit
git commit --amend
# Or amend without changing message
git commit --amend --no-edit
# Force push with safety
git push origin your-branch --force-with-lease
Cherry-Picking Changes
# Cherry-pick a commit from another branch
git cherry-pick abc123def
# Cherry-pick multiple commits
git cherry-pick abc123..def456
# Resolve conflicts if needed
git cherry-pick --continue
Working with Upstream Changes
# Fetch upstream changes regularly
git fetch upstream
# Update main branch
git checkout main
git merge upstream/main
# Rebase feature branch
git checkout your-feature
git rebase main
# Or merge main into feature
git merge main
Contribution Areas by Expertise
For Cloud Native/DevOps Engineers
Container Build Optimization:
- Improve Containerfile layer caching
- Optimize build scripts for speed
- Reduce image size
CI/CD Improvements:
- Optimize GitHub Actions workflows
- Add build parallelization
- Improve artifact handling
Example Tasks:
- Refactor
reusable-build.yml
for better caching - Add build-time validation tests
- Implement workflow failure notifications
For Package Maintainers
Package Management:
- Submit packages to @ublue-os/packages
- Maintain COPR repositories
- Update package manifests
UDEV Rules:
- Submit hardware enablement rules
- Test on various hardware
- Document hardware requirements
Example Tasks:
- Add new hardware support to packages.json
- Update COPR repository definitions
- Submit udev rules for new devices
For Shell Script Developers
Build Script Improvements:
- Enhance error handling
- Add progress indicators
- Improve script modularity
Just Recipe Development:
- Create new ujust commands
- Improve existing recipes
- Add user-friendly aliases
Example Tasks:
- Refactor build scripts for clarity
- Add validation to just recipes
- Improve error messages
For Documentation Writers
Documentation Needs:
- Hardware compatibility guides
- Custom image building tutorials
- Troubleshooting documentation
- Installation guides
Documentation Standards:
- Use clear, concise language
- Avoid terms like "simply" or "easy" (justsimply.dev)
- Include practical examples
- Link to related documentation
Example Tasks:
- Document hardware-specific issues
- Create video tutorials
- Update installation instructions
- Write troubleshooting guides
For Frontend/UX Developers
User Experience:
- Improve GNOME shell extensions
- Customize desktop defaults
- UI/UX enhancements
Testing:
- Test desktop responsiveness
- Validate accessibility features
- Report UX issues
Example Tasks:
- Test GNOME extensions compatibility
- Propose UX improvements
- Create user feedback surveys
Troubleshooting Guide
Build Failures
Problem: Build fails with package conflict
Error: package foo conflicts with bar
Solution:
- Check if package is already included elsewhere
- Add exclusion to packages.json
- Check COPR repository compatibility
Problem: Git error during build
fatal: unable to access 'https://github.com/': Could not resolve host
Solution:
- Check network connectivity in build environment
- Verify GitHub Actions has network access
- Check if rate-limited by GitHub
Local Testing Issues
Problem: Podman build fails with permission error
Error: writing blob: adding layer with blob: permissions denied
Solution:
# Run with appropriate permissions
sudo podman build -t test .
# Or configure rootless podman
podman system migrate
Problem: Out of disk space during build
Error: no space left on device
Solution:
# Clean up podman storage
podman system prune -a
# Check disk space
df -h
PR Issues
Problem: CI check failing - Conventional Commit validation
❌ Commit message does not follow Conventional Commits format
Solution:
# Amend the commit message
git commit --amend
# Update the PR
git push origin your-branch --force-with-lease
Problem: Merge conflict with main
CONFLICT (content): Merge conflict in packages.json
Solution:
# Fetch latest upstream
git fetch upstream
# Rebase on main
git rebase upstream/main
# Resolve conflicts manually
vim packages.json
# Mark as resolved
git add packages.json
git rebase --continue
# Force push
git push origin your-branch --force-with-lease
Community Interaction
Communication Channels
GitHub Issues:
- Primary venue for bug reports and feature requests
- Use issue templates when available
- Search existing issues before creating new ones
Discord:
- Real-time chat for quick questions
- Discord: Check the documentation for the server link
- Remember: Discord is for chat, not permanent documentation
Discussion Forum:
- community.projectbluefin.io
- Long-form discussions
- Support questions
- Community feedback
Communication Best Practices
DO:
- ✅ Ask questions in issues for permanent record
- ✅ Search before asking
- ✅ Provide context and details
- ✅ Be patient with maintainer response times
- ✅ Help others when you can
- ✅ Thank contributors
DON'T:
- ❌ Use Discord for bug reports (file issues instead)
- ❌ Expect immediate responses
- ❌ Ping maintainers directly unless urgent
- ❌ Ask the same question in multiple channels
- ❌ Post "me too" comments without additional info
Code of Conduct
All contributors must follow the Universal Blue Code of Conduct.
Key Points:
- Be respectful and inclusive
- Welcome newcomers
- Focus on constructive feedback
- Report inappropriate behavior to
jorge.castro@gmail.com
Issue Capture Discipline
From the contributing guide philosophy:
The "Issue Capture" Pattern:
- Use Discord for rapid iteration - Debug quickly in chat
- Capture to text editor - Copy important findings as you go
- File an issue - Create permanent record of solution
- Edit and improve - Clean up the issue description later
Why This Matters:
- Solves the problem once for everyone
- Creates searchable documentation
- Prevents asking the same question twice
- Builds institutional knowledge
Example Flow:
Discord: "Hey, package X is failing to install"
↓ (quick back-and-forth debugging)
↓ (copy findings to text editor)
↓
GitHub Issue: "Package X fails on Fedora 42 due to Y dependency"
- Symptoms
- Root cause
- Solution
- Related links
Contributing to Infrastructure
GitHub Actions Workflows
Workflow Structure:
build-image-*.yml
: Per-channel build triggersreusable-build.yml
: Shared build logicclean.yml
: Artifact cleanupgenerate-release.yml
: Release notes
Making Workflow Changes:
# Edit workflow file
vim .github/workflows/build-image-stable.yml
# Validate syntax locally
# Use GitHub's workflow validator or:
yamllint .github/workflows/build-image-stable.yml
# Commit
git add .github/workflows/build-image-stable.yml
git commit -m "chore(ci): improve stable build caching"
# Test in your fork first
git push origin your-branch
# Open PR from fork to see if it works
Common Workflow Patterns:
# Conditional execution
- name: Build only on main
if: github.ref == 'refs/heads/main'
run: ./build.sh
# Matrix builds
strategy:
matrix:
variant: [bluefin, bluefin-dx]
fedora: [41, 42]
Build Script Development
Script Organization:
00-09
: Early stage (kernel, repos, packages)10-16
: Mid stage (configuration, additions)17-19
: Late stage (cleanup, initramfs)
Script Template:
#!/usr/bin/bash
set -eoux pipefail
echo "::group:: Your Script Name"
# Your logic here
# Use $FEDORA_MAJOR_VERSION for version-specific logic
# Use $IMAGE_NAME for image-specific logic
echo "::endgroup::"
Testing Scripts:
# Direct execution (for simple scripts)
bash -x build_files/base/04-packages.sh
# Container execution (more realistic)
podman run --rm -it \
-v "$(pwd):/workspace:ro" \
-e FEDORA_MAJOR_VERSION=42 \
ghcr.io/ublue-os/silverblue-main:42 \
bash /workspace/build_files/base/04-packages.sh
Release Process
Understanding Releases
Bluefin uses continuous delivery:
- Daily builds: Automatic, no manual release
- Version format:
42.20251012.1
(Fedora.YYYYMMDD.build) - Multiple builds per day: Various channels updated independently
Release Channels
stable (Weekly):
# Rebase to stable
sudo bootc switch ghcr.io/ublue-os/bluefin:stable
latest (Daily):
# Rebase to latest
sudo bootc switch ghcr.io/ublue-os/bluefin:latest
gts (LTS):
# Rebase to GTS (Long Term Support)
sudo bootc switch ghcr.io/ublue-os/bluefin:gts
Pinning Package Versions
Sometimes upstream Fedora has a regression requiring a temporary pin.
Add a Pin:
Edit the appropriate Containerfile section:
# Revert to older version of ostree to fix Flatpak installations
RUN rpm-ostree override replace \
https://bodhi.fedoraproject.org/updates/FEDORA-2023-cab8a89753
Document the Pin:
# Add comment explaining:
# - What's pinned
# - Why it's pinned
# - Link to upstream bug
# - When to remove (after fix is released)
Remove a Pin:
Wait 24-48 hours after Fedora releases a fix (for rebuild propagation), then:
# Remove the override
git diff Containerfile
# Confirm the pin is removed
git commit -m "chore: remove ostree pin after upstream fix"
Fedora Upstream Reporting
When to Report Upstream
If you find a bug that:
- Exists in vanilla Fedora Silverblue/Kinoite
- Is not caused by Bluefin modifications
- Affects the base Fedora Atomic system
How to Report Upstream
-
Reproduce on vanilla Fedora (if possible):
# Boot vanilla Fedora Silverblue
# Test if the issue occurs there -
Report to Fedora:
- Upstream tracker: fedora-silverblue/issue-tracker
- Include: Fedora version, steps to reproduce, logs
-
Link in Bluefin Issue:
- Cross-reference the upstream issue
- Track upstream progress
- Help test fixes
Maintainer Notes
Becoming a Maintainer
Contributing regularly and demonstrating expertise may lead to maintainer status. Qualities valued:
- Consistent quality contributions
- Good communication
- Helpful to other contributors
- Understands project goals
- Reliable and responsive
Current Maintainer Structure:
- Lead: @castrojo (infrastructure, project direction)
- Core: @p5, @m2Giles, @tulilirockz (features, maintenance, testing)
Lazy Consensus Model
Bluefin follows Apache Lazy Consensus:
- Assume consensus unless objections raised
- Allow time for feedback (account for timezones/holidays)
- Opinionated decisions encouraged
- Post issues for major changes requiring feedback
Additional Resources
Related Repositories
- @ublue-os/main - Base Universal Blue images
- @ublue-os/packages - Package specifications
- @ublue-os/akmods - Kernel modules
- @ublue-os/bluefin-docs - Documentation site
Documentation
Tooling
Community
Contribution Statistics
As of October 2025, Bluefin sees:
- 8-12 commits per day (including automation)
- 60% automated (Renovate bot updates)
- 35% core maintainers (manual contributions)
- 5% community (external contributors)
- 24-48 hour review time for manual PRs
- 84 open issues (actively triaged)
The project welcomes all skill levels and contribution types. Start small, learn the workflows, and grow your involvement over time.
Final Tips
- Start small: Begin with documentation or simple package additions
- Ask questions: Don't hesitate to ask for clarification
- Test thoroughly: Use local builds or PR images
- Be patient: Reviews take time; maintainers balance multiple priorities
- Learn from others: Read merged PRs to understand patterns
- Follow conventions: Stick to established patterns in the codebase
- Document your work: Help future contributors with clear explanations
Remember: Every maintainer started as a first-time contributor. Welcome to the Bluefin community!