Move the deployment into the app repo, and build it with podman

The playbook, its roles, its vars and a new inventory now live in ansible/,
beside the app they deploy, the way the other apps on this machine are laid out.
The inventory follows the same shape: one entry per Site, all on the same box,
each naming its own vars file through var_file, so adding a Site is one line and
a file rather than a command-line flag. ansible_host is written as the
resolvable name rather than an ssh alias so the inventory works on any machine.

The image is now built with podman as a multi-arch manifest and pushed to
registry.tanshu.com/menu-admin, mirroring the Makefile used elsewhere on this
machine: build-production, plus build-check and build-check-local for a build
that does not push. deploy.sh runs the checks, builds, pushes, then runs the
playbook for the Site named by SITE, with SKIP_DEPLOY for a push without a
deploy.

ESLint comes out again: this project's typescript@7 has no JavaScript compiler
API, so typescript-eslint cannot install, and linting only the JavaScript was
not worth keeping. Prettier stays, and the README records why ESLint is absent
and what would bring it back.
This commit is contained in:
tanshu committed 2026-09-22 23:18:18 +05:30
1 parent e64f65642f
commit 75b6492493
17 files changed
+417 -1067

No files matched your search

+17 -25
View File
@@ -16,18 +16,15 @@ which needs a human present.
## Deploying
```sh
./deploy.sh 2026-09-22 # tests, build, push to registry.tanshu.com
./deploy.sh 2026-09-22 # format, types, tests, podman build+push, deploy
SKIP_DEPLOY=1 ./deploy.sh 2026-09-22 # build and push only
```
then the playbook in `ansible-playbooks/menu-admin/` — its readme covers the
parallel run, the `site.env` step that gives the admin a password, and cutover.
After deploying, check the running site from the outside (read-only, exits
non-zero on failure, so it can gate a cutover):
```sh
npm run check-site -- https://menu-new.hopsngrains.com
```
The image is built with **podman** as a multi-arch manifest and pushed to
`registry.tanshu.com/menu-admin` (`Makefile`, mirrored from the other apps on
this machine). The Ansible deployment lives in `ansible/` in this repo, with one
inventory entry per Site; see `ansible/readme.md` for the first run, cutover and
rollback.
## Layout
@@ -85,13 +82,11 @@ npm run verify # integrity of .dev/data
npm run check-site -- http://127.0.0.1:3000 # checks a running site from outside
```
### Linting and formatting
### Formatting
```sh
npm run lint # eslint
npm run lint:fix
npm run format # prettier --write
npm run format:check # what CI and deploy.sh run
npm run format:check # what deploy.sh runs
```
Prettier owns formatting (`.prettierrc.json`); `docs/` is excluded because those
@@ -99,17 +94,14 @@ are hand-wrapped notes rather than code. `embeddedLanguageFormatting` is off on
purpose: the renderers build HTML inside `html` tagged template literals, and
letting Prettier reflow those would change the markup customers receive.
**ESLint does not lint the TypeScript, and cannot as things stand.** This project
uses the native TypeScript port (`typescript@7`), which ships no JavaScript
compiler API — and every ESLint TypeScript parser needs one. `typescript-eslint`
declares `typescript >=4.8.4 <6.1.0` as a peer and refuses to install; forcing it
through would leave a parser that cannot read the compiler it was given. The
TypeScript gate is therefore `npm run typecheck` (strict, with `noUnusedLocals`,
`noUncheckedIndexedAccess`, `exactOptionalPropertyTypes` and
`erasableSyntaxOnly`), and ESLint covers the JavaScript. To get ESLint over the
`.ts` files as well, either pin `typescript@5.9` — which supports everything this
project uses — and add `typescript-eslint`, or add `oxlint`, which parses
TypeScript without the compiler API.
**ESLint is deliberately absent.** This project's `typescript@7` is the native
port and ships no JavaScript compiler API, which every ESLint TypeScript parser
needs — `typescript-eslint` requires `typescript >=4.8.4 <6.1.0` and refuses to
install, and forcing it through leaves a parser that cannot read the compiler.
Linting only the JavaScript was not worth the config, so the TypeScript gate is
`npm run typecheck` (strict, with `noUnusedLocals`, `noUncheckedIndexedAccess`,
`exactOptionalPropertyTypes` and `erasableSyntaxOnly`) and ESLint can come back,
with `typescript-eslint`, once it supports TypeScript 7.
Dragging Pages is the one interaction that only a browser can check, so there is
a harness for it. It needs `geckodriver` on PATH and a running dev server: