You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
i might have just two questions - just trying to understand the concept of immutable releases. are those also possible with docker images as release assets, or are those docker images also immutable? and have git tags been moved for previous releases and or have release assets been modified or deleted in previous versions of ddev? (so far i thought after a release git tag and release assets remained the same)
We already have non-movable and non-removable tags for ddev/ddev with rulesets.
Right now, we can edit releases and replace assets - we never do that and shouldn't be able to as a safety measure.
As far as I understand, releases can still be edited while they are drafts, so the release process can still be completed. We had several intermittent problems with GoReleaser before, so we had to delete assets and rerun GoReleaser to regenerate them.
As for editing the release description - I don't see any restrictions related to that for immutable releases in the docs.
As for the Docker images - I don't know yet, need to investigate.
Some adjacent supply-chain options for container images, parked here from a discussion on #8707 so they aren't lost. Nothing here is proposed for this issue's scope — just the list, for later.
#8707 makes container image tags bare content hashes and gives every image the standard org.opencontainers.image.* metadata, in two forms: config labels, which travel with a docker pull and show in docker inspect offline, and annotations on the manifest index, which describe the tag itself and are readable from the registry without pulling. revision now records the exact commit an image was built from, which is what most of the options below build on.
Provenance and integrity, closest to this issue:
SBOM and provenance attestations.docker buildx build --sbom=true --provenance=mode=max, attached via the OCI referrers API. This is the container-image counterpart of immutable releases: it says what is inside an image and how it was built, and it's the prerequisite for signing. Costs push time and registry storage.
Signing (cosign, or docker trust). Worth doing once attestations exist. Pairs with immutable release artifacts so both halves of a release, the binaries and the images, are verifiable.
Base image tracking via org.opencontainers.image.base.name / .base.digest, which buildx can populate automatically. Turns "which of our images are still on the old base?" into a registry query instead of an archaeology exercise — useful for CVE triage.
Sharper staleness warnings.imageVersionMismatch() currently says "built for X but this DDEV expects Y". With revision it could say how far behind a pinned image is, or link a compare URL.
Per-repository Docker Hub READMEs explaining the content-hash tag scheme. Documentation rather than metadata, but it's what someone browsing tags on Docker Hub sees first.
One gotcha that affects several of these: docker buildx imagetools create inherits the media type of its sources and has no flag to override it, and a Docker manifest list has nowhere to store annotations. Images whose per-arch builds came from buildx end up as OCI indexes and keep their annotations; images built with the classic builder don't. DDEV's currently published images are OCI indexes, but the automatic build path added in #8707 builds per-arch with plain docker build, so it would need something like --output type=registry,oci-mediatypes=true before annotations or attestations stick there.
Status of this issue, with #9076 open to implement it.
The checklist above
Read about immutable releases: done.
Test with ddev-test/ddev: done, with two trial releases, v1.108.1-draftflow1 and v1.108.1-draftflow2. Both are published and immutable, with 24 assets including SPDX SBOMs.
scripts/release.sh vX.Y.Z --notes-issue N takes the notes from the comment with the ## Installation heading. It turns @ user into @user, and for a stable release turns /en/latest/ links into /en/stable/. It creates a draft with those notes followed by GitHub's generated What's Changed, New Contributors, and Full Changelog, then starts the release workflow.
main-build.yml releases on workflow_dispatch instead of release: created. Creating or publishing a release in the web UI no longer starts a build.
GoReleaser reuses the draft, adds SBOMs for the archives, and publishes. Homebrew and AUR are pushed after publishing.
actions/attest adds signed build provenance for every file in checksums.txt. GitHub adds its own release attestation when an immutable release is published.
A user-facing docs page on verifying downloads and images.
A /ddev:release agent skill that drafts the notes and runs scripts/release.sh.
A ddev debug command, or extra ddev version rows, that reports the revision of the running images.
Both trial runs had to be re-run because GitHub didn't assign a macOS runner within 15 minutes. The draft stays unpublished meanwhile, but a release can be delayed.
Activity
rfay commentedon May 8, 2026
It's a good idea. It will cause us some small pain at some point when we want to fix one little thing, but it's OK.
Of course, for DDEV a real immutable release would also include immutable docker images for that tag.
rpkoller commentedon May 8, 2026
i might have just two questions - just trying to understand the concept of immutable releases. are those also possible with docker images as release assets, or are those docker images also immutable? and have git tags been moved for previous releases and or have release assets been modified or deleted in previous versions of ddev? (so far i thought after a release git tag and release assets remained the same)
but in general it sounds like a great idea.
stasadev commentedon May 8, 2026
We already have non-movable and non-removable tags for
ddev/ddevwith rulesets.Right now, we can edit releases and replace assets - we never do that and shouldn't be able to as a safety measure.
As far as I understand, releases can still be edited while they are drafts, so the release process can still be completed. We had several intermittent problems with GoReleaser before, so we had to delete assets and rerun GoReleaser to regenerate them.
As for editing the release description - I don't see any restrictions related to that for immutable releases in the docs.
As for the Docker images - I don't know yet, need to investigate.
rpkoller commentedon May 8, 2026
thank you! in regard to docker i found this link: https://docs.docker.com/docker-hub/repos/manage/hub-images/immutable-tags/ ... looks to be in beta...
rfay commentedon May 11, 2026
I thought we had an issue about reproducible builds as well, which is certainly a related initiative. It would be amazing to have
rfay commentedon Aug 16, 2026
Some adjacent supply-chain options for container images, parked here from a discussion on #8707 so they aren't lost. Nothing here is proposed for this issue's scope — just the list, for later.
#8707 makes container image tags bare content hashes and gives every image the standard
org.opencontainers.image.*metadata, in two forms: config labels, which travel with adocker pulland show indocker inspectoffline, and annotations on the manifest index, which describe the tag itself and are readable from the registry without pulling.revisionnow records the exact commit an image was built from, which is what most of the options below build on.Provenance and integrity, closest to this issue:
SBOM and provenance attestations.
docker buildx build --sbom=true --provenance=mode=max, attached via the OCI referrers API. This is the container-image counterpart of immutable releases: it says what is inside an image and how it was built, and it's the prerequisite for signing. Costs push time and registry storage.Signing (cosign, or
docker trust). Worth doing once attestations exist. Pairs with immutable release artifacts so both halves of a release, the binaries and the images, are verifiable.Base image tracking via
org.opencontainers.image.base.name/.base.digest, which buildx can populate automatically. Turns "which of our images are still on the old base?" into a registry query instead of an archaeology exercise — useful for CVE triage.Operational, lower priority:
Support diagnostics. A
ddev debug image-provenance, or extraddev versionrows, reporting therevisionand build date of the images actually running rather than the ones the binary expects. Probably the cheapest item on the list, since the metadata is already there after feat(images): Automatically push and then test new images when changes made, fixes #8609 #8707.Sharper staleness warnings.
imageVersionMismatch()currently says "built for X but this DDEV expects Y". Withrevisionit could say how far behind a pinned image is, or link a compare URL.Per-repository Docker Hub READMEs explaining the content-hash tag scheme. Documentation rather than metadata, but it's what someone browsing tags on Docker Hub sees first.
One gotcha that affects several of these:
docker buildx imagetools createinherits the media type of its sources and has no flag to override it, and a Docker manifest list has nowhere to store annotations. Images whose per-arch builds came from buildx end up as OCI indexes and keep their annotations; images built with the classic builder don't. DDEV's currently published images are OCI indexes, but the automatic build path added in #8707 builds per-arch with plaindocker build, so it would need something like--output type=registry,oci-mediatypes=truebefore annotations or attestations stick there.ci(release): start the GoReleaser changelog at the previous release
rfay commentedon Nov 6, 2026
Status of this issue, with #9076 open to implement it.
The checklist above
ddev-test/ddev: done, with two trial releases, v1.108.1-draftflow1 and v1.108.1-draftflow2. Both are published and immutable, with 24 assets including SPDX SBOMs.scripts/release.shcreates the draft from the notes in the release issue, and GoReleaser publishes it after attaching every asset. Blocking a hand-published release is only partial, see Publish releases with a GitHub App token, the only bypass on the release tag ruleset #9078.What #9076 changes
scripts/release.sh vX.Y.Z --notes-issue Ntakes the notes from the comment with the## Installationheading. It turns@ userinto@user, and for a stable release turns/en/latest/links into/en/stable/. It creates a draft with those notes followed by GitHub's generated What's Changed, New Contributors, and Full Changelog, then starts the release workflow.main-build.ymlreleases onworkflow_dispatchinstead ofrelease: created. Creating or publishing a release in the web UI no longer starts a build.actions/attestadds signed build provenance for every file inchecksums.txt. GitHub adds its own release attestation when an immutable release is published.Before the next release on
ddev/ddevrefs/tags/v*tag ruleset with restricted creation, update, and deletion, as onddev-test/ddev.gh attestation verifyandgh release verifyagainst theddev-testreleases. Claude Code's machine couldn't reach Sigstore, so they're unverified.release-commenter.ymlanddocs-stable.ymlstill run. Both trials were prereleases, soreleasednever fired.Follow-ups
Possibilities not filed yet:
/ddev:releaseagent skill that drafts the notes and runsscripts/release.sh.ddev debugcommand, or extraddev versionrows, that reports therevisionof the running images.Both trial runs had to be re-run because GitHub didn't assign a macOS runner within 15 minutes. The draft stays unpublished meanwhile, but a release can be delayed.
Generated by Claude Code
ci(release): draft-first releases with SBOMs and provenance, for ddev…
ci(release): start the GoReleaser changelog at the previous release