Versioning and Upgrades
Graduation note
Section titled “Graduation note”When the implementation items below are complete, this doc should be split and graduated:
- Move the user-facing content (update mechanism, version pinning, branching) into a new section in
docs/readme-setup.md— that’s where users will look for “how do I update Daps?” - Rename this file to
docs/developer-versioning.mdto cover the maintainer-facing content: semver strategy, release process, distribution options, OSS practices. - Add
developer-to the prefix map indapster/_scripts/sync-docs.mjsand add a Developer sidebar section indapster/astro.config.mjs.
Context
Section titled “Context”Daps has no versioning yet: no version number in the CLI, no changelog, no formal update mechanism. This doc establishes the strategy across three areas: versioning Daps itself, how users receive Daps updates, and how users upgrade project dependencies (WordPress, Grist).
Daps versioning
Section titled “Daps versioning”Semantic versioning: MAJOR.MINOR.PATCH
| Bump | When |
|---|---|
| MAJOR | Breaking changes: compose conventions changed, daps.yaml format changed, CLI flags removed, template structure requires migration |
| MINOR | New workflows, new templates, new flags, image tag bumps in templates — backward compatible |
| PATCH | Bug fixes, docs, typo fixes, non-behavioral dependency bumps |
Starting version: 0.1.0 (pre-release; no stability guarantees).
Single source of truth: <Version>0.1.0</Version> in src/Dapsman.Cli/Dapsman.Cli.csproj. The CLI is the right home — it’s the deployed artifact the user runs. If domain/application libraries were ever published as NuGet packages independently, they’d carry their own versions; for now they’re internals.
Git tag v0.1.0 on Codeberg mirrors the csproj version.
Git tagging: first, find the commit you want to tag:
git log --oneline -8 main; git tag; git remote -vThen, create the tag locally and push it to the remote repo, e.g.:
git tag -a v0.1.0 2b5a753 -m "Daps 0.1.0"git push origin v0.1.0dapsman --version: Prints the version (from Assembly.GetName().Version) and exits. (Not yet implemented — tracked as an implementation item below.)
Changelog: docs/readme-changelog.md — one entry per release, newest first. Each entry: version header, release date, bullet points grouped as Added / Changed / Fixed / Breaking. Synced to dapster.org automatically.
Receiving Daps updates
Section titled “Receiving Daps updates”Current mechanism: git pull
Section titled “Current mechanism: git pull”# 1. Check what changed# (review docs/readme-changelog.md or the Codeberg release notes)
# 2. Pull updatesgit pull
# 3. Apply infrastructure changesdapsman local buildHandling a breaking (MAJOR) update
Section titled “Handling a breaking (MAJOR) update”A MAJOR version bump means something about your project configuration needs to change. The changelog’s migration guide describes exactly what. General process:
- Read the migration guide in the changelog
- Update your project’s compose files, daps.yaml, or scripts as instructed
dapsman local build
Pinning to a stable version
Section titled “Pinning to a stable version”For users who want stability over getting the latest: checkout a specific release tag and stay there until you’re ready to upgrade.
git checkout v0.2.0To upgrade to a later version:
git fetchgit checkout v0.3.0# follow any migration steps in the changelogdapsman local buildBranching for local customization
Section titled “Branching for local customization”Users who modify Daps itself (e.g. to add a private template) should maintain a personal branch based on a release tag:
git checkout -b my-daps v0.2.0# make local changesWhen a new Daps release comes out:
git fetchgit merge v0.3.0 # or rebase# resolve conflicts — usually minimal, most changes are in src/Breaking change protocol (developer)
Section titled “Breaking change protocol (developer)”When shipping a MAJOR version bump:
- Write a migration guide section in the changelog entry
- Add a
MIGRATION.mdor section inreadme-setup.mddescribing what users need to change - Consider keeping old behavior behind a flag for one MINOR version before removing it
Distribution options
Section titled “Distribution options”The git-clone approach requires git and some CLI familiarity. For a broader audience, packaged distribution is worth exploring once Daps is stable:
Self-contained binary releases — dotnet publish -r win-x64 --self-contained true produces a single exe with the .NET runtime bundled. Attach platform-specific binaries to Codeberg Releases:
- Windows:
dapsman-win-x64.exe(zipped) - macOS:
dapsman-osx-arm64,dapsman-osx-x64 - Linux:
dapsman-linux-x64
No .NET installation required. Binary is ~70 MB self-contained. Users update manually by downloading a new release.
Recommendation for now: Self-contained releases is the lowest-effort first step — no runtime dependency, works across platforms, Codeberg already supports release attachments.
Other options for later:
.NET global toolvia NuGet (dotnet tool install -g dapsman) — clean UX for users who have .NET installed- macOS: Homebrew tap (
brew install louieoc/daps/dapsman) - Windows: MSI installer (WiX or similar)
- Linux: apt/snap/AppImage
Upgrading project dependencies
Section titled “Upgrading project dependencies”Understanding what lives where
Section titled “Understanding what lives where”Whether an upgrade goes through the Docker image or through a bind-mounted directory determines how it’s done.
| What | Where | How to upgrade |
|---|---|---|
| WordPress core | Inside the container image | Update the image tag in the dockerfile, rebuild |
| WordPress plugins & themes | wp-content/ (bind-mounted) | WP Admin dashboard |
| MySQL | Container image | Update tag in compose file, redeploy |
| Redis | Container image | Update tag in compose file, redeploy |
| Host OS packages | The prod VM | unattended-upgrades (see below) |
| Host OS release (22.04 → 24.04) | The prod VM | Rebuild the VM from a newer image (see below) |
See templates/wordpress/README.md for the step-by-step WordPress core upgrade flow.
Host OS lifecycle
Section titled “Host OS lifecycle”Routine patching is a solved problem in principle and an open gap in practice — provisioning
does not currently install unattended-upgrades, so prod VMs drift. See
planning-security.md under “Automatic host security updates” for the
proposed change and implementation items.
Release upgrades are different, and Daps should not use do-release-upgrade. An in-place
release upgrade on a remote cloud VM is the riskiest operation available: interactive conffile
prompts, a Docker apt entry pinned to the old release codename, and no console access if it strands
partway. Daps has a better answer that is also its core value proposition — rebuild the VM rather
than upgrade it:
dapsman prod backup --project <name> --provider <provider># edit OS_IMAGE_ID in hosting/openstack_<provider>_instance_vars.shdapsman prod unprovision --provider <provider>dapsman prod provision --provider <provider>dapsman prod deploy --project <name> --provider <provider>dapsman prod sync-from-local --project <name> --provider <provider>Cattle, not pets. This treats the host as disposable, which is the property Daps already promises for moving between providers — so a failure in this flow is a portability bug worth finding.
The real cost is a new public IP, which means a DNS record update and propagation delay. Plan it deliberately rather than under pressure.
Timing. Ubuntu 22.04 LTS is in standard support until April 2027, so there is no urgency.
The instance vars for new provisions (OS_IMAGE_ID) should move to 24.04 LTS well before then,
once the cloud-init path has been tested against it. Existing VMs can be rebuilt onto the new image
independently, one provider at a time.
Is a template image tag bump a MAJOR or MINOR Daps update?
Section titled “Is a template image tag bump a MAJOR or MINOR Daps update?”MINOR. Template updates only affect new projects initialized after the update — existing projects have their own copy of the dockerfile and are not touched. Updating an existing project’s dependency is always the user’s explicit action. No Daps migration needed.
Pinning floating tags
Section titled “Pinning floating tags”Several templates currently use floating tags (:latest, nginx:alpine) which make upgrades implicit and non-reproducible. Best practice: pin to a specific version and update intentionally.
| Template | Service | Current | Better |
|---|---|---|---|
| wordpress | phpmyadmin | phpmyadmin:latest | phpmyadmin:5.2 |
| astro / static | nginx | nginx:alpine | nginx:1.27-alpine |
| grist | grist | gristlabs/grist:latest | gristlabs/grist:1.4 |
(Actual versions to confirm at time of pinning.)
Future: upgrade workflow
Section titled “Future: upgrade workflow”A dapsman upgrade --project <name> command could compare a project’s image tags against the current template version and suggest updates. Worth adding once Daps has multiple real users.
Open source release practices
Section titled “Open source release practices”- Codeberg Releases: create a release per git tag with the changelog entry as release notes; attach self-contained binaries per platform
- Pre-release labeling:
0.x.ysignals no stability guarantees; cut1.0.0once core workflows are stable and tested across multiple real projects - CONTRIBUTING.md: add contributor guidelines before soliciting external PRs
Implementation items
Section titled “Implementation items”- Add
<Version>0.1.0</Version>tosrc/Dapsman.Cli/Dapsman.Cli.csproj - Add
dapsman --versioncommand (printAssembly.GetName().Version) - Create
docs/readme-changelog.mdwith an initial0.1.0entry - Pin
phpmyadmin,nginx,gristlabs/gristto specific versions in templates - Add update instructions and version-pinning guidance to
docs/readme-setup.md - Set up Codeberg Releases with self-contained binaries on first release
- Test
openstack-cloud-init.yamlagainst Ubuntu 24.04, then bumpOS_IMAGE_IDinhosting/openstack_example_instance_vars.shand the per-provider vars files - (Future)
dapsman upgrade --project <name>workflow