--- title: "Contribute" description: "Help make Federated CoreDesktop better: suggest software, send a pull request, and learn how changes reach existing machines through migrations." sections: - type: hero compact: true eyebrow: "MIT licensed ยท Pull requests welcome" title: "Help make CoreDesktop better." subhead: "Want to help? Awesome! We welcome any and all help. Suggest missing titles or services, or contribute a PR and we're off to a better CoreDesktop." visual: false ctas: - label: "Open the repository" url: "https://gitea.federated.computer/Federated_Computer/coredesktop" style: primary - label: "Report an issue" url: "https://gitea.federated.computer/Federated_Computer/coredesktop/issues" style: ghost - type: steps kicker: "Ways to help" headline: "Pick one." items: - title: "Suggest software" body: "Missing a title or service you use every day? [Open an issue](https://gitea.federated.computer/Federated_Computer/coredesktop/issues) and say why. Found a bug? Report it there too." - title: "Send a pull request" body: "Packages live in `packages.conf`, Flatpaks in `install-flatpaks.sh`, update steps in `updates.d/` and setup in `configure.d/`. Every push is checked with [shellcheck](https://www.shellcheck.net); run `make check` first, which runs shellcheck and the bats tests. The [developer tools](#coredesktop-dev) make this easier." - title: "Build a sibling" body: "Have something that's only for you or your team? Make it a [sibling project](/siblings/) instead." - type: text id: coredesktop-dev kicker: "Developer tools" headline: "Install coredesktop-dev." body: | [coredesktop-dev](https://gitea.federated.computer/Federated_Computer/Coredesktop-Dev) has the tools for working on CoreDesktop itself. Only contributors need them, so it's a [sibling project](/siblings/) rather than part of CoreDesktop. Install it with: ``` sibling add https://gitea.federated.computer/Federated_Computer/Coredesktop-Dev.git ``` It asks where your working copy of CoreDesktop is (default `~/Projects/coredesktop`) and offers to clone it there. It installs shellcheck, bats, tea (Gitea's CLI), QEMU and xorriso, and `update` keeps it current from then on. To change the working copy, run `sibling add` again. **Why it exists: your machine has two copies of CoreDesktop.** The *deployed* copy in `~/.local/share/coredesktop` is what the machine runs and what `update` pulls (fast-forward only). The *working* copy, e.g. `~/Projects/coredesktop`, is where you make changes. Never edit the deployed copy: one changed tracked file stops `update` from pulling. coredesktop-dev lets you test the working copy without touching the deployed one. - type: table id: coredesktop-dev-commands kicker: "coredesktop-dev" headline: "The commands." lede: "Each takes `--help`. In a Flatpak, such as an editor's built-in terminal, coredesktop-dev runs itself on the host with `flatpak-spawn --host`." headers: ["Command", "What it does"] rows: - ["`coredesktop-dev doctor`", "Checks the tools, the working copy, and that the deployed copy can still update"] - ["`coredesktop-dev check [--fast]`", "Runs `make lint` and `make test` in the working copy, plus shellcheck on scripts you haven't committed yet (`make lint` only sees tracked files). `--fast` runs shellcheck only"] - ["`coredesktop-dev try [--keep] [cmd...]`", "Runs the working copy's code as if it were installed, in a throwaway home with its own D-Bus session and no display, e.g. `coredesktop-dev try configure --list`. sudo, yay, pacman and systemctl still change this machine"] - ["`coredesktop-dev deployed [status|restore]`", "Shows the deployed copy's state, or undoes local changes to it (after asking)"] - ["`coredesktop-dev hooks [status|install|remove]`", "A pre-push hook in the working copy that runs `check` first. `git push --no-verify` skips it"] - ["`coredesktop-dev smoketest ...`", "Tests install and update on throwaway virtual machines ([below](#smoketests))"] - type: table id: testing kicker: "Testing" headline: "Four kinds of tests." lede: "CI only runs shellcheck (`make lint` in `.gitea/workflows/shellcheck.yml`), so run the bats tests and smoketests yourself before sending a PR." headers: ["Test", "What it checks", "How to run it", "Documented in"] rows: - ["Lint", "Every tracked bash script, with [shellcheck](https://www.shellcheck.net) at warning level. Settings in `.shellcheckrc`", "`make lint`, or `coredesktop-dev check --fast` to include untracked scripts", "[README.md](https://gitea.federated.computer/Federated_Computer/coredesktop/src/branch/main/README.md#contributing)"] - ["Unit tests", "The logic of the scripts, with [bats](https://github.com/bats-core/bats-core) tests in `tests/*.bats`. Each test gets its own `HOME` and a fake `bin` folder at the front of `PATH`, where the `stub` helper fakes commands like pacman, yay and sudo", "`make check` (lint, then `make test`), or `coredesktop-dev check`", "[tests/test_helper.bash](https://gitea.federated.computer/Federated_Computer/coredesktop/src/branch/main/tests/test_helper.bash)"] - ["Smoketests", "`install.sh` and `update` end to end, on a real Arch + GNOME virtual machine: what fakes can't check", "`coredesktop-dev smoketest run`", "[smoketest/README.md](https://gitea.federated.computer/Federated_Computer/coredesktop/src/branch/main/smoketest/README.md)"] - ["Sibling projects", "A sibling's install and update, in a throwaway home with `sibling add` pointed at a local clone", "By hand, as the guide shows", "[skills/sibling-project-format.md](https://gitea.federated.computer/Federated_Computer/coredesktop/src/branch/main/skills/sibling-project-format.md#testing)"] - type: callout text: "**Tests must not start session services.** A throwaway `HOME` doesn't isolate you from the live GNOME session: `/run/user/` is shared. A test that replaced the keyring daemon once left the real keyring locked and hung Bitwarden. Anything that starts session daemons needs its own `XDG_RUNTIME_DIR`, no display and `dbus-run-session`, which is what `coredesktop-dev try` sets up. And remember that sudo, yay, pacman and systemctl ignore `HOME`: test those with stubs, or on a VM. More in [skills/coredesktop-dev-sibling.md](https://gitea.federated.computer/Federated_Computer/coredesktop/src/branch/main/skills/coredesktop-dev-sibling.md)." - type: text id: smoketests kicker: "Smoketests" headline: "Install and update, on real virtual machines." body: | The bats tests check the logic with fake commands. Smoketests check what fakes can't: pacman, yay, Flatpak, systemd, ufw, Snapper on btrfs, GNOME settings and a reboot. The scenarios live in CoreDesktop's `smoketest/scenarios/` (shared helpers in `smoketest/lib/scenario.sh`); coredesktop-dev provides the QEMU virtual machines that run them. They test your working copy's `HEAD`, so commit first. ``` coredesktop-dev smoketest list # the scenarios and their tier coredesktop-dev smoketest run # the quick ones (tier pr) coredesktop-dev smoketest run --tier all # everything, including a fresh install; hours coredesktop-dev smoketest run 40 43 # just these coredesktop-dev smoketest run --keep 40 # on failure, leave the VM up to look around coredesktop-dev smoketest shell installed # SSH into a throwaway VM ``` Scenarios cover a fresh install, `refresh`, a no-op update, upgrading from an older release, `update` replacing itself, new and failing migrations, a failing hook, an unreachable upstream, local edits, low disk space, a month-old machine, skipped packages and siblings. **How it works.** Each scenario runs on a throwaway copy of one of two images. *base* is Arch's cloud image with GNOME added as archinstall's desktop profile does it, and a user `tester` (password `tester`) who logs in automatically. *installed* is base after `install.sh` at the commit your branch started from; scenarios on it first `update` to the commit under test. Inside the VM, a bare repo at `/srv/smoketest/coredesktop.git` stands in for Gitea, so `install.sh` and `update` run unchanged. After a scenario, `fingerprint` describes the machine as text (packages, Flatpaks, services, firewall, files in `/etc`, GNOME settings). The baseline scenario installs an older commit, runs `update`, and checks the result matches a fresh install. If not, an `install.sh` change is probably missing its migration. **What you need.** KVM (virtualization turned on in the firmware), about 8 GB of RAM and 4 CPUs per VM (`SMOKETEST_MEMORY`, `SMOKETEST_CPUS`), and room in `~/.cache/coredesktop-dev/smoketest`: a VM disk grows to about 50 GB during a run, and is deleted afterwards. The first run builds both images before any scenario runs: *base* in a few minutes, *installed* in an hour or more. Later runs reuse them; rebuild *installed* now and then with `coredesktop-dev smoketest images installed`. Arch packages are cached and shared between VMs; Flatpaks aren't. To watch a VM's screen, set `SMOKETEST_VNC=1` and connect a VNC viewer to `127.0.0.1:5901`. **Following a run.** While a VM boots, or a command such as `install.sh` runs in it, the terminal says once a minute what it's still waiting for, or which command is still running and its latest line of output. The logs are in `~/.cache/coredesktop-dev/smoketest`: `build.log` and the VM's console, `serial.log`, in `build-base/` and `build-installed/` while an image builds, and each scenario's logs in `runs/-