018.2 — Manual Deployment Runbook (No AI Agent)¶
Purpose: a pure copy-paste command sequence for release history + staging deploy + production deploy, for when there's no Claude Code agent available — a bare terminal, a different operator, or a CI box. No explanation, no judgment calls beyond what's marked. 018 has the full reasoning behind every step below; 018.1 is the same work done by asking an agent instead of typing this.
Audience: whoever is at the keyboard doing the release by hand.
How to use this page: work top to bottom inside the section for what you're deploying. Every
step is either a command block (run it) or an explicit manual/UI action (marked MANUAL). Three
decisions can't be scripted — they're called out inline, each as one line, not a paragraph:
semver bump size, highlights wording, and highlights.portal tagging.
0 — Preflight (every target, every time)¶
cd /Users/abadr/Documents/Laplace/Projects/odoo19/next_ecommerce
git fetch origin && git status -sb # how far behind origin/main?
git pull --ff-only origin main # only if behind AND tree is clean
git branch -a | grep -iE "bump|release/" # leftover unmerged release branch?
cd /Users/abadr/Documents/Laplace/Projects/odoo19/addons_lp_ecommerce
git fetch origin && git status -sb
git pull --ff-only origin main
git branch -a | grep -iE "bump|release/"
If a leftover branch exists and main has moved past it: don't build on it or reuse its name —
branch fresh with a different name, and tell whoever owns the other branch it's superseded. Don't
force-delete or force-push over it.
1 — Frontend staging deploy (next_ecommerce)¶
1.1 — Decide the version bump¶
| Bump | When |
|---|---|
Patch (1.2.0 → 1.2.1) |
Bug-fix-only, nothing new to use |
Minor (1.2.1 → 1.3.0) |
Adds something a user can see (new page/button/behaviour) |
| Major | Not used on this project |
1.2 — Find the diff range for this release¶
cd next_ecommerce
ls -t _docs/releases/*.json | grep -v _TEMPLATE | head -1 # latest release file
jq -r '.headCommit, .headCommitBackend' <that file> # previous baseline SHAs
git log --oneline <headCommit>..HEAD # frontend commits shipping now
cd ../addons_lp_ecommerce && git log --oneline <headCommitBackend>..HEAD # backend commits since
headCommit/headCommitBackend are the previous release's branch-off point, not its own tip —
the range includes that release's own bump commit. Cross-check against the previous file's
changes array and drop anything already listed there.
1.3 — Write the release-note file¶
Fill in by hand:
- version, date, environments (the env(s) you're deploying), pr (fill in after the PR
exists)
- headCommit = current git rev-parse HEAD (before this release's own bump commit)
- headCommitBackend = git -C ../addons_lp_ecommerce rev-parse HEAD
- changes — one bullet per commit from step 1.2, prefixed [frontend] or [backend]
- highlights — business language, not commit-message jargon. "You can now…" / "Fixed an
issue where…". Omit entirely for purely internal/technical changes.
- highlights[].portal — check which files the commit actually touched
(git diff-tree --no-commit-id --name-only -r <sha>), don't guess from the message:
- client → files under client-portal routes (served from /)
- amp → files under admin/** (served from /admin/*)
- general → genuinely spans both, or portal-agnostic infra — a shared common/ui/** file
alone does not make a fix general if every other touched file sits under one portal
- backoffice → the change is actually in addons_lp_ecommerce, not next_ecommerce
1.4 — Bump the version in both places¶
Edit both (they must agree):
vim docker/<env>/.env.<env> # NEXT_PUBLIC_APP_VERSION=<new-version>
vim docker/<env>/docker-compose.yml # services.next-portal.environment.NEXT_PUBLIC_APP_VERSION
<env> = one of training, pre-prod, staging-b2b, training-b2b. Edit only the
environment(s) actually shipping.
1.5 — Build, upload, push to the server's registry¶
# single environment
bash docker/<env>/build_upload_amd64.sh --deploy
# all three staging envs at once (not `training` — deploy that one on its own)
bash docker/build_deploy_all_staging.sh
bash docker/build_deploy_all_staging.sh pre-prod staging-b2b # subset
# re-push an already-built tar without rebuilding
TAR_PATH="$PWD/docker/build_releases/<env>/<env>_<version>_amd64.tar" \
bash docker/<env>/build_upload_amd64.sh --no-build --deploy
This builds a linux/amd64 image tagged both <env> and <env>-<version>, saves a tar under
docker/build_releases/<env>/, scps it to the server, then loads/retags/pushes both tags to
127.0.0.1:5000. It does not restart the running container.
1.6 — Redeploy the running stack — MANUAL, Portainer only¶
- Stacks → the stack for that environment → Editor.
- Update the stack with Re-pull image and redeploy enabled.
- If Portainer doesn't re-pull: remove the container and redeploy the stack to force it.
1.7 — Commit and sync GitHub¶
git add docker/<env>/.env.<env> docker/<env>/docker-compose.yml _docs/releases/<new-version>.json
git commit -m "release: <new-version> — <env>"
git push origin <branch>
# open the Azure DevOps PR, get it merged, then on main:
bash scripts/sync_github_from_azure.sh
1.8 — Verify¶
Also confirm in Portainer the stack is running the new image tag.2 — Frontend production deploy (next_ecommerce)¶
Production has no manual build step and no review gate — pushing GitHub main is the deploy
action itself, live within minutes. Do this only once validated on staging-b2b and pre-prod,
and once any backend dependency has already reached Odoo.sh production.
2.1 — Write the release note and bump the version¶
Same as steps 1.2–1.3 above, but edit .env.production at the repo root instead of a
docker/<env>/ file:
2.2 — Rehearse locally (the Worker build differs from the container build)¶
2.3 — Deploy — this command is the live production deploy¶
git add .env.production _docs/releases/<new-version>.json
git commit -m "release: <new-version> — production"
git push github main
2.4 — Sync the GitHub mirror going forward¶
2.5 — Verify¶
Confirm the Cloudflare Workers Build succeeded in the dashboard and the site serves the new version.3 — Backend staging deploy (addons_lp_ecommerce)¶
The B2B team's own responsibility ends at the GitHub mirror sync in step 3.5 — from there,
promotion onto any Odoo.sh branch (staging-b2b → pre-prod → training → production) is done
exclusively by the ERP Team. There is no command below that does that promotion; don't look
for one.
3.1 — Find the diff range¶
cd addons_lp_ecommerce
ls -t _docs/releases/*.md | grep -v _TEMPLATE | head -1 # latest release file
grep "Head commit" <that file>
git log --oneline <that-sha>..HEAD
Same caveat as the frontend: Head commit is the previous release's branch-off point, not its
tip — cross-check against that file's own ## Changes and exclude anything already listed.
3.2 — Bump BUILD_NUMBER (mandatory, every deployable change)¶
This is the only way to verify from outside whether a submodule update actually picked up this code.
3.3 — Check before bumping the manifest version¶
If the manifest is already ahead of the latest release file (a feature/migration PR raised it
already), leave it as-is — only move BUILD_NUMBER. Bumping it again skips a version for no
reason.
3.4 — Write the release-note file¶
Fill in: date, module version, build number, Head commit = git rev-parse HEAD (before this
release's own bump commit), PR URL once known. ## Changes in plain business language, PR
number in parentheses — not commit-message jargon.
3.5 — Commit, PR, merge, sync GitHub¶
git add ecommerce/controllers/build_info_api.py ecommerce/__manifest__.py \
_docs/releases/<module_version>_build<N>.md
git commit -m "release: <module_version> build<N>"
git push origin <branch>
Direct push to main is rejected (TF402455) — open the PR:
https://dev.azure.com/TechnicalUnitedSA/ERP-Odoo/_git/addons_lp_ecommerce/pullrequestcreate?sourceRef=<branch>&targetRef=main
After it merges:
3.6 — Verify once the ERP Team confirms promotion¶
- Matchingbuild_number → live on that build.
- Older number → submodule still points at an old SHA, or the custom domain is serving a stale
numbered build (each push makes a new build; the custom domain must follow the branch).
- 404 → build-info endpoint predates this deploy.
4 — Backend production¶
Not a command sequence — this is entirely the ERP Team's manual branch-promotion process
(training → production, with Training-team UAT go/no-go in between). See
017 — Release Workflow Step Sequence.
The only thing to run from this side is the same verification command as 3.6, pointed at
https://www.samtia.com/ecommerce/api/build-info once told it shipped.
Quick copy block — frontend staging, start to finish¶
cd next_ecommerce
git fetch origin && git pull --ff-only origin main
# ...write _docs/releases/<version>.json (step 1.3)
# ...bump NEXT_PUBLIC_APP_VERSION in docker/<env>/.env.<env> + docker-compose.yml
bash docker/build_deploy_all_staging.sh
# ...Portainer: Re-pull image and redeploy (MANUAL)
git add -A && git commit -m "release: <version> — <env>" && git push origin <branch>
# ...merge PR, then:
bash scripts/sync_github_from_azure.sh
Quick copy block — backend staging, start to finish¶
cd addons_lp_ecommerce
git fetch origin && git pull --ff-only origin main
# ...bump BUILD_NUMBER (and manifest version only if not already raised)
# ...write _docs/releases/<module_version>_build<N>.md
git add -A && git commit -m "release: <module_version> build<N>" && git push origin <branch>
# open PR -> merge -> then:
bash _docs/scripts/sync_github_from_azure.sh
curl -s https://staging-b2b-odoo.adv-photonx.com/ecommerce/api/build-info
Troubleshooting¶
| Symptom | Fix |
|---|---|
No such image: moby/buildkit:buildx-stable-1 |
docker pull moby/buildkit:buildx-stable-1 |
no space left on device during build |
docker builder prune -af && docker system prune -af |
| SCP/SSH auth failure | confirm the public key is on the server (ssh-copy-id a.badr@192.168.2.32) or fix SSH_KEY_PATH in that env's .ssh.local |
network lp-apps not found in Portainer |
create an external network named lp-apps |
Frontend build-info/release-history.json doesn't show the new version |
confirm Portainer actually re-pulled (image digest, not just the tag) |
Backend build-info returns an old number after a push |
ask the ERP Team to confirm the submodule SHA: git -C lp log --oneline -1 |
Related Documents¶
- 014 — Deployment Architecture — pipeline topology and why each step exists.
- 017 — Odoo.sh Environments Guide — the ERP Team's branch promotion policy that step 3.6/section 4 depend on.
- 018 — Release and Build Process — the same runbook with full explanation and reasoning.
- 018.1 — AI-Agent-Assisted Deployment — the same work, done by asking an agent instead of running these commands by hand.