Add a deploy script, with no host in it #60

Closed
opened 2026-08-26 17:12:39 +00:00 by jcoffey-dev · 0 comments
Owner

Stacked on #59 — it calls node scripts/version.mjs, which lands there. Base is version-numbers; retarget to main once #59 merges.

Your live deploy script has never been under version control, which makes it the one part of the pipeline that can silently fall out of step with the repo — as it just did. It builds without --build-arg IHASMAIL_VERSION, so after #59 every deployment would report 2.16.0 regardless of what was actually built.

What's published, and what isn't

Every path, name, port and volume is a variable with a default that describes the shape of a deployment rather than any particular one:

APP="${IHASMAIL_APP:-$HOME/apps/ihasmail}"
ENVF="${IHASMAIL_ENV:-$APP/.env.production}"
NAME="${IHASMAIL_NAME:-ihasmail}"
BIND="${IHASMAIL_BIND:-127.0.0.1:8090}"
VOLUME="${IHASMAIL_VOLUME:-ihasmail-data}"
IMAGE_REPO="${IHASMAIL_IMAGE:-ihasmail}"

So the repo gets the logic — the hold guard, the confirmation, the health poll — and none of the topology. Same convention as Caddyfile.example and nginx.example.conf.

Worth saying plainly: nothing sensitive was in the original either. It never reads the environment file, only hands the path to docker run --env-file. But the absolute paths named a user and a directory layout, and there's no reason for those to be public just to get version control over the guards.

Two things it does that the original didn't

Passes the version to the build — the whole reason this came up. With a wrinkle worth knowing: a Docker tag may not contain +, which a version for a commit outside a pull request does (2.16.57+g1fa6578). Confirmed:

$ docker tag … plustest:2.16.57+gabc1234
error parsing reference: … is not a valid reference format

So the tag turns + into - while the build is told the real form. About and /api/health still report 2.16.57+g1fa6578 correctly.

Tags each build with its version as well as :current, so rolling back means running the previous tag rather than rebuilding it — the original overwrote one tag and left nothing to go back to. The failure path now lists what's available.

Testing

Exercised against a throwaway clone, container, volume and image — not just syntax-checked:

case result
hold guard, held commit in target but not in production refused, named the commit and the file
hold guard, held commit production already carries allowed through — you can't be blocked by what you already run
confirmation guard, no tty, no --yes refused, listed what it would have introduced
--dry-run stopped before building or touching anything
full run built, replaced the container, reported healthy
version through the whole pipeline image 2.16.57-g0549a09, app reports 2.16.57+g0549a09

All test containers, images and volumes removed afterwards.

Before you use it on the live host

The defaults match your setup, but check IHASMAIL_ENV and IHASMAIL_IMAGE — the existing container runs ihasmail:2.0, and this tags ihasmail:<version> plus ihasmail:current. Your first run with it will build a fresh tag rather than reusing that one.

Merged 2026-08-26 as coffey-labs/ihasmail@ea83631609

Rebuilt from: git history, session transcript.

> **Stacked on #59** — it calls `node scripts/version.mjs`, which lands there. Base is `version-numbers`; retarget to `main` once #59 merges. Your live deploy script has never been under version control, which makes it the one part of the pipeline that can silently fall out of step with the repo — as it just did. It builds without `--build-arg IHASMAIL_VERSION`, so after #59 every deployment would report `2.16.0` regardless of what was actually built. ## What's published, and what isn't Every path, name, port and volume is a variable with a default that describes the *shape* of a deployment rather than any particular one: ```sh APP="${IHASMAIL_APP:-$HOME/apps/ihasmail}" ENVF="${IHASMAIL_ENV:-$APP/.env.production}" NAME="${IHASMAIL_NAME:-ihasmail}" BIND="${IHASMAIL_BIND:-127.0.0.1:8090}" VOLUME="${IHASMAIL_VOLUME:-ihasmail-data}" IMAGE_REPO="${IHASMAIL_IMAGE:-ihasmail}" ``` So the repo gets the logic — the hold guard, the confirmation, the health poll — and none of the topology. Same convention as `Caddyfile.example` and `nginx.example.conf`. Worth saying plainly: nothing sensitive was in the original either. It never reads the environment file, only hands the path to `docker run --env-file`. But the absolute paths named a user and a directory layout, and there's no reason for those to be public just to get version control over the guards. ## Two things it does that the original didn't **Passes the version to the build** — the whole reason this came up. With a wrinkle worth knowing: a Docker tag may not contain `+`, which a version for a commit outside a pull request does (`2.16.57+g1fa6578`). Confirmed: ``` $ docker tag … plustest:2.16.57+gabc1234 error parsing reference: … is not a valid reference format ``` So the *tag* turns `+` into `-` while the *build* is told the real form. About and `/api/health` still report `2.16.57+g1fa6578` correctly. **Tags each build with its version as well as `:current`**, so rolling back means running the previous tag rather than rebuilding it — the original overwrote one tag and left nothing to go back to. The failure path now lists what's available. ## Testing Exercised against a throwaway clone, container, volume and image — not just syntax-checked: | case | result | |---|---| | hold guard, held commit in target but not in production | refused, named the commit and the file | | hold guard, held commit production already carries | allowed through — you can't be blocked by what you already run | | confirmation guard, no tty, no `--yes` | refused, listed what it would have introduced | | `--dry-run` | stopped before building or touching anything | | full run | built, replaced the container, reported healthy | | version through the whole pipeline | image `2.16.57-g0549a09`, app reports `2.16.57+g0549a09` | All test containers, images and volumes removed afterwards. ## Before you use it on the live host The defaults match your setup, but check `IHASMAIL_ENV` and `IHASMAIL_IMAGE` — the existing container runs `ihasmail:2.0`, and this tags `ihasmail:<version>` plus `ihasmail:current`. Your first run with it will build a fresh tag rather than reusing that one. **Merged** 2026-08-26 as coffey-labs/ihasmail@ea836316098e <sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.