docs: add changelog, contributor guide, release process, and runner setup
- CHANGELOG.md: Keep-a-Changelog format, [26.0-alpha] entry covering everything shipped so far (installer webapp, drive scoring, base archinstall config, wireframes, competitor analysis, wizard flow spec) - CONTRIBUTING.md: dev setup, conventional commit format, code style - RELEASING.md: calendar versioning rules (YY.N-stage, no "v" prefix) and the release workflow (bump changelog, commit, tag, push, create Forgejo Release) - docs/runner-setup.md: install + register a forgejo-runner so the upcoming CI workflow actually executes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
decab35fbf
commit
7759574481
4 changed files with 301 additions and 0 deletions
35
CHANGELOG.md
Normal file
35
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to Homebase will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
This project uses calendar versioning: `YY.N-stage` (e.g. `26.0-alpha` = 2026, release 0, alpha stage).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [26.0-alpha] - 2026-04-13
|
||||
|
||||
First tagged snapshot. Pre-alpha — the installer does not yet boot, but the design is locked and the prototype components are shaped.
|
||||
|
||||
### Added
|
||||
|
||||
- **Installer webapp prototype** (`webinstaller/`) — Flask app with 3-step wizard (hostname → drive → overview), serves drive list via `drives.py::list_scored_devices()`.
|
||||
- **Drive scoring module** (`webinstaller/drives.py`) — scores attached disks by type (NVMe/SSD/HDD), SMART health (`smartctl -H`), and size. Consumed by the installer and usable as a CLI.
|
||||
- **Base archinstall configuration** (`archinstall/user_configuration.json`) — systemd-boot, ext4, Docker + Compose preinstalled, server profile, SSH. Credentials template at `archinstall/user_credentials.example.json` (real credentials gitignored).
|
||||
- **Installer wireframes** (`docs/installer-wireframes.md`) — Robert's hand-drawn 4-screen UX sketches.
|
||||
- **Competitor analysis** (`docs/competitors.md`) — CasaOS, Umbrel, YunoHost reviewed across install flow, hardware detection, app store UX, reverse proxy/SSL, user complaints. Key finding: device-aware wizard + managed gateway are uncontested differentiators.
|
||||
- **Wizard flow spec** (`docs/wizard-flow.md`) — 8-screen first-boot flow extending Robert's wireframe with YunoHost-style domain/SSL/diagnostic/confirm screens. Locked tech picks with rejected alternatives.
|
||||
- **Project README** — vision, principles, architecture, key decisions, landscape, roadmap.
|
||||
|
||||
### Decisions locked
|
||||
|
||||
- **Reverse proxy:** Caddy (auto Let's Encrypt, simplest config)
|
||||
- **Identity provider:** Authentik (bundled SSO, every app auto-wired at install)
|
||||
- **Managed gateway DNS:** NS delegation to `ns1.homebase.cloud` / `ns2.homebase.cloud` (wildcard cert via Let's Encrypt DNS-01)
|
||||
- **Local HTTPS:** Local CA installed by user once (no browser warnings on `*.proksi.local`)
|
||||
- **Base OS:** Arch (rolling, Debian remains fallback)
|
||||
- **Containers:** Docker + Compose
|
||||
- **License:** AGPL-3.0
|
||||
|
||||
[Unreleased]: https://forgejo.sourcegate.online/daniel/homebase/compare/26.0-alpha...HEAD
|
||||
[26.0-alpha]: https://forgejo.sourcegate.online/daniel/homebase/releases/tag/26.0-alpha
|
||||
80
CONTRIBUTING.md
Normal file
80
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# Contributing to Homebase
|
||||
|
||||
Two-person project right now (Daniel + Robert). This doc exists so the conventions don't get lost as the team grows.
|
||||
|
||||
## Dev setup
|
||||
|
||||
```bash
|
||||
git clone https://forgejo.sourcegate.online/daniel/homebase.git
|
||||
cd homebase
|
||||
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
# Flask installer
|
||||
pip install -r webinstaller/requirements.txt
|
||||
python webinstaller/app.py # serves on http://localhost:5000
|
||||
|
||||
# Dev tooling (lint + tests)
|
||||
pip install -e ".[dev]"
|
||||
ruff check .
|
||||
pytest
|
||||
```
|
||||
|
||||
Required system tools (used by `webinstaller/drives.py`):
|
||||
|
||||
- `lsblk` (util-linux)
|
||||
- `smartctl` (smartmontools) — `sudo pacman -S smartmontools` / `sudo apt install smartmontools`
|
||||
|
||||
## Commit messages
|
||||
|
||||
We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). Every commit subject line starts with a type:
|
||||
|
||||
| Type | When |
|
||||
|------|------|
|
||||
| `feat:` | New user-visible feature |
|
||||
| `fix:` | Bug fix |
|
||||
| `docs:` | Documentation only |
|
||||
| `ci:` | CI config, Forgejo Actions, runner setup |
|
||||
| `build:` | Packaging, `pyproject.toml`, dependency changes |
|
||||
| `refactor:` | Code restructuring with no behavior change |
|
||||
| `test:` | Adding or fixing tests |
|
||||
| `chore:` | Everything else (e.g. `.gitignore`, version bumps) |
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
feat: add S5 domain picker to installer wizard
|
||||
fix: handle empty lsblk output in drives.parse_size_gb
|
||||
docs: document NS delegation flow for managed gateway
|
||||
ci: add ruff format check to Forgejo Actions workflow
|
||||
```
|
||||
|
||||
Keep the subject line under 72 characters. Use the body to explain *why* — the code already says *what*.
|
||||
|
||||
## Code style
|
||||
|
||||
- **Python:** ruff handles lint + format. Config in `pyproject.toml`. Run `ruff check . && ruff format .` before committing.
|
||||
- **Markdown:** wrap at a sensible width (no hard line-length rule). Every external link you add to a doc must resolve (the markdown-link-check CI job will catch it if it doesn't).
|
||||
- **No comments that explain *what*** — the code says that. Only comment the *why* when it's non-obvious.
|
||||
|
||||
## PR / push workflow
|
||||
|
||||
While the team is two people, pushing to `main` is fine for small changes. For anything larger than ~50 lines or that touches architecture, open a PR and get the other person to look at it.
|
||||
|
||||
## Tests
|
||||
|
||||
Tests live in `tests/`. Pure functions get unit tests; anything that shells out to `lsblk` / `smartctl` is out of scope (those need hands-on testing on real hardware).
|
||||
|
||||
```bash
|
||||
pytest # all tests
|
||||
pytest tests/test_drives.py -v
|
||||
```
|
||||
|
||||
## Releases
|
||||
|
||||
See [RELEASING.md](RELEASING.md).
|
||||
|
||||
## License
|
||||
|
||||
AGPL-3.0 (see `LICENSE`). By contributing you agree your contributions are licensed the same way.
|
||||
73
RELEASING.md
Normal file
73
RELEASING.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Releasing
|
||||
|
||||
Homebase uses calendar versioning: **`YY.N-stage`** — e.g. `26.0-alpha` is 2026, release 0, alpha stage. No `v` prefix.
|
||||
|
||||
- `YY` — last two digits of the current year
|
||||
- `N` — incrementing release number within the year, starting at 0 (next one in 2026 is `26.1-alpha`, then `26.2-alpha`…)
|
||||
- `-alpha` — drop it when the installer boots end-to-end and wipe-and-reinstall is safe
|
||||
|
||||
When the year rolls over, the next release becomes `27.0-alpha` regardless of how many `26.x` releases shipped.
|
||||
|
||||
## Cadence
|
||||
|
||||
Tag per meaningful milestone, not on a calendar. A milestone is: ISO boots, a wizard screen works end-to-end, managed gateway serves its first real domain, etc. If a week goes by with no tag, that's fine — no tag is better than a noisy one.
|
||||
|
||||
## Release steps
|
||||
|
||||
1. **Move `[Unreleased]` in `CHANGELOG.md` to a new version heading.**
|
||||
```markdown
|
||||
## [Unreleased]
|
||||
|
||||
## [26.1-alpha] - 2026-05-20
|
||||
### Added
|
||||
- ...
|
||||
```
|
||||
Add a `[26.1-alpha]` link definition at the bottom:
|
||||
```markdown
|
||||
[26.1-alpha]: https://forgejo.sourcegate.online/daniel/homebase/releases/tag/26.1-alpha
|
||||
```
|
||||
Update the `[Unreleased]` compare link to point at the new tag.
|
||||
|
||||
2. **Commit the changelog.**
|
||||
```bash
|
||||
git add CHANGELOG.md
|
||||
git commit -m "chore: release 26.1-alpha"
|
||||
```
|
||||
|
||||
3. **Tag the commit.**
|
||||
```bash
|
||||
git tag -a 26.1-alpha -m "Release 26.1-alpha"
|
||||
```
|
||||
|
||||
4. **Push the tag and main.**
|
||||
```bash
|
||||
git push origin main
|
||||
git push origin 26.1-alpha
|
||||
```
|
||||
|
||||
5. **Create a Forgejo Release** at `https://forgejo.sourcegate.online/daniel/homebase/releases/new`:
|
||||
- Tag: `26.1-alpha` (already exists)
|
||||
- Title: `26.1-alpha`
|
||||
- Body: paste the changelog section for this version
|
||||
- Tick **Pre-release** for anything still `-alpha` or `-beta`
|
||||
|
||||
6. **Verify CI passed on the tag.** The Forgejo Actions run against the tagged commit should be green before you announce the release anywhere.
|
||||
|
||||
## First-time: find the current version
|
||||
|
||||
```bash
|
||||
git describe --tags --abbrev=0
|
||||
```
|
||||
|
||||
If the project is fresh and `git describe` fails, the next release is `26.0-alpha`.
|
||||
|
||||
## If the tag is wrong
|
||||
|
||||
Don't move published tags. Delete the release + tag, fix the problem, bump to the next number.
|
||||
|
||||
```bash
|
||||
git tag -d 26.1-alpha
|
||||
git push origin :refs/tags/26.1-alpha
|
||||
# ... fix ...
|
||||
git tag -a 26.2-alpha ...
|
||||
```
|
||||
113
docs/runner-setup.md
Normal file
113
docs/runner-setup.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Forgejo Runner Setup
|
||||
|
||||
How to stand up a `forgejo-runner` so the CI workflow in `.forgejo/workflows/ci.yml` actually executes on every push.
|
||||
|
||||
The runner is a long-running daemon that polls the Forgejo instance for queued jobs and runs them in Docker containers.
|
||||
|
||||
## Choosing a host
|
||||
|
||||
| Option | Good for | Trade-off |
|
||||
|--------|----------|-----------|
|
||||
| **Dedicated VPS** | Production-ish CI that runs even when you're offline | Costs a few €/month; one more machine to maintain |
|
||||
| **Home server / NAS** | Free; plenty of capacity | CI blocked if home network / power drops |
|
||||
| **Local dev machine** | Quick to set up, fast runs | CI only works while the machine is on |
|
||||
|
||||
Recommendation for now: **home server or a cheap VPS**. Don't use a laptop that suspends.
|
||||
|
||||
## Install
|
||||
|
||||
Pick either the binary or the Docker container path. Docker is easier to upgrade.
|
||||
|
||||
### Path A: Docker Compose (recommended)
|
||||
|
||||
On the chosen host, create `~/forgejo-runner/compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
runner:
|
||||
image: code.forgejo.org/forgejo/runner:6
|
||||
container_name: forgejo-runner
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- CONFIG_FILE=/data/config.yml
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- docker-in-docker
|
||||
command: /bin/sh -c "sleep 5; forgejo-runner daemon"
|
||||
|
||||
docker-in-docker:
|
||||
image: docker:dind
|
||||
container_name: forgejo-runner-dind
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
environment:
|
||||
- DOCKER_TLS_CERTDIR=
|
||||
command: dockerd -H tcp://0.0.0.0:2375 --tls=false
|
||||
```
|
||||
|
||||
### Path B: Binary
|
||||
|
||||
Download the latest release from https://code.forgejo.org/forgejo/runner/releases and drop it somewhere in `$PATH`:
|
||||
|
||||
```bash
|
||||
wget https://code.forgejo.org/forgejo/runner/releases/download/v6.0.0/forgejo-runner-6.0.0-linux-amd64
|
||||
chmod +x forgejo-runner-6.0.0-linux-amd64
|
||||
sudo mv forgejo-runner-6.0.0-linux-amd64 /usr/local/bin/forgejo-runner
|
||||
```
|
||||
|
||||
## Register
|
||||
|
||||
1. In the Forgejo web UI: go to **Site Administration → Actions → Runners → Create new Runner**. Copy the registration token. (For a repo-scoped runner instead, use **Repo Settings → Actions → Runners**.)
|
||||
|
||||
2. Register from the runner host:
|
||||
|
||||
```bash
|
||||
forgejo-runner register \
|
||||
--instance https://forgejo.sourcegate.online \
|
||||
--token <TOKEN> \
|
||||
--name homebase-runner-1 \
|
||||
--labels docker,ubuntu-latest,self-hosted \
|
||||
--no-interactive
|
||||
```
|
||||
|
||||
This writes `.runner` (registration file) and `config.yml` into the current directory.
|
||||
|
||||
3. Start the daemon (Docker: `docker compose up -d`; binary: `forgejo-runner daemon`).
|
||||
|
||||
4. Verify the runner shows up as **Idle** in Forgejo's admin Runners page.
|
||||
|
||||
## First CI run
|
||||
|
||||
Push any commit; the Actions tab on the repo should show the workflow running. If nothing happens:
|
||||
|
||||
- Confirm the runner is online (Forgejo admin → Actions → Runners).
|
||||
- Check the workflow has labels that match the runner (`runs-on: ubuntu-latest` needs a runner registered with that label).
|
||||
- Check the runner logs: `docker logs forgejo-runner` or the systemd journal.
|
||||
|
||||
## Systemd unit (for the binary path)
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Forgejo Actions Runner
|
||||
After=docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/forgejo-runner daemon
|
||||
WorkingDirectory=/var/lib/forgejo-runner
|
||||
User=forgejo-runner
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Save as `/etc/systemd/system/forgejo-runner.service`, then `sudo systemctl enable --now forgejo-runner`.
|
||||
|
||||
## Security notes
|
||||
|
||||
- The runner mounts `/var/run/docker.sock` which gives it root-equivalent access to the host. Run it on a machine you trust and nothing sensitive.
|
||||
- Registration tokens are one-shot; a stolen token can't re-register after the runner is live.
|
||||
- Prefer repo-scoped runners over instance-wide if you're sharing the runner with other repos you don't control.
|
||||
Loading…
Add table
Reference in a new issue