ck-git-hosting

Packages, continuous integration, and releases

What is built where

ArtifactBuilt byTarget
ck-git-hosting_V_arm64.deb, ck-git-hosting_V_amd64.debpackaging/build-deb.sh in a Debian 13 containerDebian 13 servers, including Raspberry Pi 4/5 on arm64
ckgit_V_arm64.deb, ckgit_V_amd64.debsameDebian 13 clients
ckdocs_V_arm64.deb, ckdocs_V_amd64.debsamethe documentation-site generator, standalone (no file overlap with the other two, so it installs anywhere independently)
ck-git-runner_V_arm64.deb, ck-git-runner_V_amd64.debsamea remote CI runner for another machine (its own binary path, account and unit; no file overlap with the server package)
ck-git-hosting-V-linux-{arm64,amd64}.tar.gzpackaging/build-tarball.shother systemd distributions with glibc 2.41 or newer; carries bin/ckdocs too
ckgit-V-macos-{arm64,x86_64}.tar.gzsame, --client-onlymacOS clients; carries bin/ckdocs too
ck-git-hosting-V-source.tar.gzgit archiveHomebrew formula source
SHA256SUMSrelease jobverification
packages (a .tar bundling the arm64/amd64 .debs, a source tarball, and build-version)this project's own self-hosted CI (.ckgit/ci.yml), stored as a release asset on the serverck-git-hosting-deploy (the server package) and ckgit release download / packaging/update-cli.sh (the source tarball)
this repository's documentation site (ckdocs.yml, README.md, docs/)ckdocs build in both CI channels: .ckgit/ci.yml's docs step (self-hosted) and .github/workflows/pages.yml (GitHub)ck-git Pages on the server (the dashboard's Docs button) and https://cklukas.github.io/ck-git-hosting/

The version comes from the VERSION file. A release is created by pushing a tag vMAJOR.MINOR.PATCH that matches it; the workflow refuses a mismatch. Pushing the same tag to both the GitHub origin remote and this project's own hosted ckgit remote produces the two channels side by side -- see Releases and the self-hosted release and deploy guide.

Continuous integration

.github/workflows/ci.yml runs on every push and pull request:

  • Linux amd64 and arm64 with GCC and Clang: strict -Werror build plus the unit and integration suites (make all check).
  • macOS Apple silicon and Intel: the same.
  • Debian 13 container on both architectures: builds all four packages, runs lintian for information, installs them with apt, confirms the daemon, CI runner, Pages, and ckdocs binaries and units are in place, creates a device key line and a project, removes the packages while verifying that server.ini and the repository survive, then purges and verifies that the repository still survives.

Every job passes BUILD_ROOT=$RUNNER_TEMP, overriding the Makefile's own portable default (TMPDIR, or /tmp; a checkout's own local.mk can pin a different one — see local.mk.example), and the Makefile only accepts build directories beneath the selected root either way. The arm64 jobs use the ubuntu-24.04-arm runner label and the Intel macOS job uses macos-15-intel; both are hosted labels that GitHub may rename in future, in which case only the matrix entries change.

Debian and Raspberry Pi

sudo apt install ./ck-git-hosting_0.1.0_arm64.deb
sudo ckgit-admin authorized-key --client-id mac-studio --public-key mac-studio.pub \
  | sudo tee -a /etc/ck-git-hosting/authorized_keys

The package installs the same tree as packaging/install.sh, with two package-specific choices: the units live in /usr/lib/systemd/system, and authorized_keys is created by the maintainer script rather than shipped, so neither an upgrade nor a purge touches device keys by accident. server.ini and the sshd drop-in are conffiles. apt remove keeps configuration, state, repositories, and the account; apt purge removes configuration and state and still keeps every bare repository and the account, printing what was left behind.

The maintainer scripts skip systemctl when systemd is not running and skip the sshd reload when sshd is absent, which is how the container test runs. If sshd -t rejects the drop-in, it is renamed to .disabled and sshd is not reloaded.

Build packages locally on a Debian host:

make BUILD_ROOT=/tmp/ck BUILD_DIR=/tmp/ck/build all check
sh packaging/build-deb.sh --build-dir /tmp/ck/build --output /tmp/ck/dist

--stage-only writes the two package roots without dpkg-deb, which the test suite uses on a workstation. CKGIT_MAINTAINER overrides the Maintainer field.

Without --version, a local build is stamped 0.1.0~YYYYMMDD.HHMM.<commit>. dpkg orders ~ below anything, including the empty string, so this snapshot sorts below the plain release 0.1.0 and above every earlier snapshot of the same VERSION — a real 0.1.0 release is never seen as a downgrade from an earlier development build, and apt install ./ck-git-hosting_*.deb still always upgrades from one snapshot to the next. A rebuilt package with an unchanged version is "already installed" to apt and needs dpkg -i or apt reinstall. Both the GitHub release workflow and this project's own self-hosted CI (.ckgit/ci.yml) pass the tag version explicitly for a tag matching VERSION, so a release published either way carries the identical clean version, for example 0.1.0. Installing a snapshot of an already-released VERSION over that release (for example testing a further change to master before bumping VERSION again) needs apt --allow-downgrades or dpkg -i, which only warns; this is deliberate — bump VERSION on master right after tagging a release, and a plain apt upgrade keeps working during the normal cycle.

Other Linux distributions

Unpack the Linux tarball and run the installer from inside it; the unpacked directory is a valid --build-dir:

tar -xzf ck-git-hosting-0.1.0-linux-arm64.tar.gz
cd ck-git-hosting-0.1.0-linux-arm64
sudo sh packaging/install.sh --build-dir . --dry-run
sudo sh packaging/install.sh --build-dir . --yes

The archive is built against Debian 13's glibc. Older distributions build from source with only Make and a C++20 compiler:

make BUILD_ROOT=/tmp/ck BUILD_DIR=/tmp/ck/build all check

macOS client with Homebrew

This repository is also a Homebrew tap: Formula/ckgit.rb builds the client from the released source archive with a verified checksum.

brew tap cklukas/ck-git-hosting https://github.com/cklukas/ck-git-hosting
brew install ckgit
brew install --HEAD ckgit

After every release the workflow's final job rewrites the formula's url, sha256, homepage, and head for that release and commits the change to the default branch, so brew upgrade ckgit follows releases. Until the first release only --HEAD installs succeed, because the placeholder checksum cannot match.

Without Homebrew, unpack ckgit-V-macos-arm64.tar.gz or the x86_64 archive and copy bin/ckgit to a directory on PATH.

Cutting a release

  1. Update VERSION and land the change on the default branch with CI green.
  2. Tag and push: git tag v0.1.0 && git push origin v0.1.0.
  3. The release workflow builds and tests every artifact, publishes the release with SHA256SUMS, and updates the Homebrew formula.

Release notes are generated from a fixed template; edit the release on GitHub afterwards for anything version-specific.