Skip to content

feat(launcher): add a pinned, checksum-verified install command - #49

Merged
github-actions[bot] merged 6 commits into
mainfrom
feat/736-pinned-install
Nov 6, 2026
Merged

github-actions[bot] merged 6 commits into
mainfrom
feat/736-pinned-install

Conversation

@znerol2

@znerol2 znerol2 commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The README told users to fetch bin/dmf-init from main and pipe a script from main into bash. This PR replaces that with a pinned, checksum-verified install:

  • New release workflow: .github/workflows/release-launcher.yml runs on v* tags. It attaches bin/dmf-init and a one-line SHA256SUMS to the release. Actions are pinned by SHA, and the only permission is contents: write.
  • One install command in the README: set version=vX.Y.Z, download both assets from that tag's release, verify with sha256sum -c (or shasum -a 256 -c on macOS), then run bash dmf-init up. Each step runs only if the previous one succeeds. A paragraph explains how to pick a version and what the check does and doesn't prove.
  • Removed: the pipe-to-bash from main.
  • New test: test/launcher/test-install-command.sh, run by a new launcher CI job. It extracts the README command and runs it against local fixture files, with no network. It checks that the command:
    • is pinned to a tag and doesn't reference /main
    • passes with a good checksum
    • refuses a wrong, empty, missing or tampered checksum
    • works with sha256sum and with shasum only

Release plan

The README pins v0.3.6. That will be the first release built by the new workflow, so the first one with SHA256SUMS. v0.3.6 gets tagged right after this PR merges. Until then, the documented command fails closed with a 404, so hold stays on until the review is done.

Not in this PR

  • The checksum sits next to the binary, so it catches corruption but isn't a signature. GitHub artifact attestations are planned as follow-up work.
  • The launcher's default image is still :latest.

Checks

  • shellcheck and actionlint pass.
  • The existing launcher test passes.

Closes dmfdeploy/dmfdeploy#736

Release tags now publish the launcher with a SHA256SUMS file. The README
install command downloads both for a named tag, checks the launcher against
the checksum, and runs it only on a match. A wrong, empty or missing checksum
file stops it before anything runs. A test extracts the documented command
from the README and runs it against local fixtures.

Closes dmfdeploy/dmfdeploy#736

Signed-off-by: znerol2 <6800371+znerol2@users.noreply.github.com>
@znerol2
znerol2 requested a review from a team as a code owner November 6, 2026 13:31
@znerol2 znerol2 added the hold Disarm auto-merge: PR will not land on approval while this label is set label Nov 6, 2026
v0.3.6 is the first release the launcher workflow builds, so it is the
first one with a SHA256SUMS asset. The install test now takes the
fixture release directory from the README's version= line, so the next
version bump needs no test change.

Refs dmfdeploy/dmfdeploy#736

Signed-off-by: znerol2 <6800371+znerol2@users.noreply.github.com>
… v0.4.0

The published launcher defaulted to the :latest image, so a launcher that
passed its checksum could start a newer, unverified image. The release
workflow now stamps the release tag into a copy of the launcher before it
computes SHA256SUMS. The stamp fails unless the marker line appears exactly
once. The image workflow pushes the semver tag without the leading "v", so
the stamp does the same. The --image flag still overrides the default.

This also bumps VERSION, pyproject.toml, and the README install command to
0.4.0, and adds the stamp tests to the launcher CI job.

Refs dmfdeploy/dmfdeploy#736

Signed-off-by: znerol2 <6800371+znerol2@users.noreply.github.com>
The install command now downloads each asset with its own curl call into a
new temporary directory, requires SHA256SUMS to hold exactly one
"<digest>  dmf-init" line, and compares the digest of the downloaded file
itself. A file already in the working directory can no longer run, and a
checksum file that names another file no longer passes.

The launcher job moves into publish-image.yml and runs only after the image
build job succeeds. It stamps the launcher with the image digest from that
build, so the published launcher points at exactly the image that was
pushed. scripts/build-launcher-release.sh holds the stamp-then-checksum
order, and a test checks that SHA256SUMS matches the final bytes.

The README now says the launcher assets start at v0.4.0.

Refs dmfdeploy/dmfdeploy#736

Signed-off-by: znerol2 <6800371+znerol2@users.noreply.github.com>
On macOS, `cd ""` succeeds and stays in the current directory, so a failed
mktemp let the downloads overwrite files there and run a launcher from it.
The README command now creates the directory into a variable and requires a
non-empty path to an existing directory before it changes into it.

The install-command test now serves a local HTTP fixture that returns 404 and
500 responses with valid bodies, so removing `curl -f` fails a test. It also
shadows mktemp with a failing stub in bash and zsh and checks that planted
files and a symlink stay unchanged. CI requires python3 for the HTTP cases.

Refs dmfdeploy/dmfdeploy#736

Signed-off-by: znerol2 <6800371+znerol2@users.noreply.github.com>
Refs dmfdeploy/dmfdeploy#736

Signed-off-by: znerol2 <6800371+znerol2@users.noreply.github.com>
@znerol2
znerol2 requested a review from lkirc November 6, 2026 15:15

@lkirc lkirc left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking findings in 67b086d. The release job validates and stamps the pushed image digest before checksumming the launcher; the documented install path fails closed on transfer or checksum errors.

@znerol2 znerol2 removed the hold Disarm auto-merge: PR will not land on approval while this label is set label Nov 6, 2026
@github-actions
github-actions Bot merged commit 921b0da into main Nov 6, 2026
16 checks passed
@znerol2
znerol2 deleted the feat/736-pinned-install branch November 8, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Give dmf-init a pinned, checksum-verified install path

2 participants