Skip to content

Deploying the docx2acroform sidecar

The docx2acroform sidecar (compose service accessible-pdf-docx2acroform on 10.1.1.4, listening on docx2acroform:5008 on the internal pdf-net) runs the AI form rebuild β€” formspec_from_detected: taxonomy classification, field sizing, source-color theming, PDF/UA tagging.

Why this needs its own runbook

Its Docker image bakes the code in at build time (the Dockerfile COPYs tools/formspec/formspec, tools/docx2acroform/docx2acroform, packages/pdf-enhance/pdf_enhance, and services/docx2acroform/app.py). Nothing is mounted at runtime, so the running container keeps whatever code it was built with until it is rebuilt β€” a git pull on .4 alone changes nothing.

Historically it was in no GitHub deploy workflow. deploy.yml ships the Cloudflare apps and deploy-aws.yml ships the Lambda/CDK stack; neither touches this compose service. So a merged, green PR that changed only tools/formspec/** shipped the apps/forms frontend while the backend rebuild logic sat un-deployed β€” it looked deployed but wasn’t (issue #2909; PRs #2899/#2900/#2901 all hit this). Same class of trap as the flyer-tagger Lambda manual-deploy lag.

Deploy paths

There are now two, and both bake the deploying commit into BUILD_GIT_SHA (via the compose GIT_SHA build arg) so the running image is self-identifying.

  1. Automatic β€” the EC2 anchor. On a push to main touching the sidecar’s code, build-anchor-images.yml builds the docx2acroform image (listed in infra/cdk/anchor-images.json) and pushes it to ECR, and deploy-anchor.yml rolls it out to the anchor. deploy-sidecars.yml, which rebuilt the container in place on 10.1.1.4, was removed on 2026-10-03: 10.1.1.4 no longer runs the stack, and its CI runners were uninstalled the same day.

  2. Manual β€” npm run rebuild (scripts/rebuild-server.sh, SSH β†’ .4 β†’ docker compose build docx2acroform). Use for a one-off rebuild, to force a no-cache rebuild (npm run build:force), or if the workflow is unavailable. The script exports GIT_SHA=$(git rev-parse HEAD) before building, so a manual rebuild also stamps provenance.

A bare docker compose build docx2acroform with no GIT_SHA exported leaves BUILD_GIT_SHA=unknown; /version then reports "git_sha": "unknown", which the skew check reads as β€œprovenance not recorded” β€” prefer the two paths above.

Skew guard β€” /version

GET http://docx2acroform:5008/version
β†’ { "service": "docx2acroform",
"git_sha": "<baked commit>",
"formspec": { "class_count": <taxonomy size> } }

git_sha is the exact commit the image was built from. class_count is a cheap corroborating signal β€” it grows whenever the taxonomy grows, so it flags an old image even if the SHA is somehow absent.

Check the running sidecar against main from .4 (no host port is published, so probe from inside the container):

Terminal window
docker compose exec -T docx2acroform \
python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:5008/version').read().decode())"
git -C ~/accessible rev-parse origin/main # compare git_sha to this

If git_sha lags origin/main for a commit that touched the baked paths, the sidecar is stale β€” rerun the workflow (workflow_dispatch on Deploy Sidecars) or npm run rebuild.

PR checklist for formspec / docx2acroform changes

  • Change touches tools/formspec/**, tools/docx2acroform/**, packages/pdf-enhance/**, or services/docx2acroform/**?
  • After merge, confirm Deploy Sidecars ran green (it verifies /version).
  • If it didn’t fire (e.g. a path just outside the filter), run npm run rebuild and re-check /version.