Skip to main content

Development

Build deskosctl and the DeskOS image from a checkout, run the tests, cut releases. Go 1.26 or later is required.

Build and test​

go build -o bin/deskosctl ./cmd/deskosctl

Run tests:

go test ./...
python3 -m unittest discover -s tests/vm # VM harness; CI runs it, make check does not
python3 -m unittest discover -s tests/supply-chain # SBOM comparison harness, same

Validate the included resources, and inspect the public CentOS reference workstation (--format json prints the canonical plan):

./bin/deskosctl validate ./examples/organization-and-role
./bin/deskosctl plan --workstation deskos-core-centos-stream-10

Build the image yourself​

  1. Render the build context:

    ./bin/deskosctl render \
    --workstation deskos-core-centos-stream-10 \
    --backend containerfile \
    --output ./dist/deskos-core-centos-stream-10
  2. Build it with rootful Podman, so bootc-image-builder can read it:

    sudo podman build -t localhost/deskos-core-centos-stream-10 ./dist/deskos-core-centos-stream-10

The QCOW2 and ISO commands in Installing DeskOS take localhost/deskos-core-centos-stream-10 as the image reference, and tests/vm/README.md boots the disk and checks the session.

Example: baseline and role​

An example that composes an organization baseline and a developer role on RHEL 10 reuses DeskOS resources without copying them (README):

./bin/deskosctl plan ./examples/organization-and-role \
--workstation example-devops-rhel-10

./bin/deskosctl render ./examples/organization-and-role \
--workstation example-devops-rhel-10 \
--output ./dist/example-devops-rhel-10

[!IMPORTANT] RHEL builds require appropriate Red Hat access and must not be publicly redistributed.

CLI​

CommandPurpose
validatechecks resources and composition
planshows the effective workstation before anything is built
renderproduces a deterministic build context
sbomwrites the declared CycloneDX SBOM of one workstation
versionprints the release version and commit (dev and the Git revision for local builds)

render writes into an empty or missing directory, or one it wrote before: it records every file in generated-manifest.json and replaces only those. It refuses a non-empty directory that is not a previous render, and refuses a previous render whose files were edited, rather than deleting something it did not create.

The declared SBOM and where a CVE scan fits are in supply-chain.md.

The CLI is also published as a container, quay.io/deskos/deskosctl:<tag>, from a release tag and signed like the other release artifacts. The embedded Core travels inside the image, so only the output directory needs a mount:

mkdir -p out
podman run --rm --userns=keep-id -v "$PWD/out":/out:z \
quay.io/deskos/deskosctl:latest render \
--workstation deskos-core-centos-stream-10 --output /out

Your own resources are an extra root, one that adds resources rather than repeating the Core, which fails the load with "defined again". --userns=keep-id maps your uid so the tool can write the output, and :z relabels the mount: on an SELinux host an unrelabeled root fails with permission denied, and relabeling a whole checkout can fail on root-owned artifacts, so mount the resource tree:

podman run --rm --userns=keep-id \
-v "$PWD/org-resources":/org:ro,z -v "$PWD/out":/out:z \
quay.io/deskos/deskosctl:latest render \
/org --workstation my-workstation --output /out

:latest is the newest stable release: a vX.Y.Z-<prerelease> tag publishes and signs its own tag and leaves :latest alone.

Releases​

Pushing a tag vX.Y.Z (or vX.Y.Z-<prerelease>) runs the CI checks and creates a GitHub Release (.github/workflows/release.yml) with:

AssetContents
deskosctl-vX.Y.Z-linux-amd64the CLI that builds an image; only linux/amd64 is built
deskos-vX.Y.Z-linux-amd64the runtime companion the image carries (ADR 0018), same commit and version checks
deskos-core-resources-vX.Y.Z.tar.gzresources/ of the same commit (DeskOS Core, platforms, assets), validated by that binary before release; a reproducible archive
SHA256SUMSchecksums of the three

The version-less aliases deskosctl-linux-amd64 and deskos-linux-amd64 make releases/latest/download/<name> work without knowing the tag; they track the latest stable release, not a prerelease.

[!NOTE] The binary is not signed.

git tag -a vX.Y.Z -m "deskosctl vX.Y.Z"
git push origin vX.Y.Z

To download and verify the current release (a vX.Y.Z name pins one), with gh or without it:

gh release download --repo deskosproject/deskos-core \
--pattern 'deskosctl-linux-amd64' --pattern 'SHA256SUMS'
sha256sum -c --ignore-missing SHA256SUMS
chmod +x deskosctl-linux-amd64
base=https://github.com/deskosproject/deskos-core/releases/latest/download
curl -fL -O "$base/deskosctl-linux-amd64" -O "$base/SHA256SUMS"
sha256sum -c --ignore-missing SHA256SUMS