100 lines
3.5 KiB
Markdown
100 lines
3.5 KiB
Markdown
---
|
|
title: "Monorepo Deploy Script — Subdirectory .git Check Pitfall"
|
|
aliases: [monorepo-git-pull, deploy-script-monorepo, git-pull-monorepo]
|
|
tags: [monorepo, git, bash, deploy, devops]
|
|
sources:
|
|
- "daily/2026-04-16.md"
|
|
created: 2026-04-16
|
|
updated: 2026-04-16
|
|
---
|
|
|
|
# Monorepo Deploy Script — Subdirectory .git Check Pitfall
|
|
|
|
A deploy script written for a multi-repo setup (separate git repos for backend and frontend) will silently fail to pull new code when the project is converted to a monorepo. The script checks for `.git` in subdirectories that don't exist in a monorepo, never finds them, skips the `git pull`, and exits successfully — leaving the server running old code with no warning.
|
|
|
|
## Key Points
|
|
|
|
- **Silent failure**: the script exits 0 even though `git pull` never ran — nothing in stdout indicates the problem
|
|
- The symptom: running `scripts/deploy.sh` reports success, but the server is still running the old version
|
|
- **Fix**: in a monorepo, `git pull` runs once at the repo root — remove all subdirectory `.git` checks
|
|
- The warning message (if the script emitted one) is easy to miss in CI/CD output or when tailing logs
|
|
- Multi-repo scripts often check `backend/.git` and `frontend/.git` to determine if each component needs to be pulled separately
|
|
|
|
## Details
|
|
|
|
### The Anti-Pattern
|
|
|
|
```bash
|
|
# scripts/deploy.sh — written for multi-repo, broken in monorepo
|
|
|
|
if [ -d "backend/.git" ]; then
|
|
echo "Pulling backend..."
|
|
cd backend && git pull && cd ..
|
|
fi
|
|
|
|
if [ -d "frontend/.git" ]; then
|
|
echo "Pulling frontend..."
|
|
cd frontend && git pull && cd ..
|
|
fi
|
|
|
|
# In a monorepo: neither condition is true → git pull never runs
|
|
# Script exits 0 anyway → deploy "succeeds" with stale code
|
|
```
|
|
|
|
### The Fix
|
|
|
|
```bash
|
|
# scripts/deploy.sh — monorepo version
|
|
|
|
set -e
|
|
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
cd "$ROOT_DIR"
|
|
|
|
echo "Pulling latest code..."
|
|
git pull
|
|
|
|
echo "Rebuilding backend..."
|
|
cd backend && pip install -r requirements.txt && cd ..
|
|
|
|
echo "Rebuilding frontend..."
|
|
cd frontend && npm ci && npm run build && cd ..
|
|
|
|
echo "Restarting services..."
|
|
systemctl restart myapp-backend
|
|
systemctl reload nginx
|
|
```
|
|
|
|
One `git pull` at the root covers all subdirectories in a monorepo.
|
|
|
|
### Detecting the Problem
|
|
|
|
If a deploy claims success but the running version doesn't match the expected commit:
|
|
|
|
```bash
|
|
# On the server — check what commit is actually running
|
|
git log -1 --oneline
|
|
|
|
# Compare with what should be deployed
|
|
git fetch origin main
|
|
git log -1 --oneline origin/main
|
|
```
|
|
|
|
If they differ after a "successful" deploy, the deploy script didn't actually pull.
|
|
|
|
### Coexisting Deploy Scripts
|
|
|
|
Repositories that transitioned from multi-repo to monorepo sometimes have two deploy scripts:
|
|
- `full-deploy.sh` — the original multi-repo script (potentially still working for other components)
|
|
- `scripts/deploy.sh` — the active script that was incorrectly carried over
|
|
|
|
Always identify which script is actually invoked by the CI/CD system or cron job before modifying.
|
|
|
|
## Related Concepts
|
|
|
|
- [[wiki/concepts/shell-static-deploy-patterns]] — broader deploy script patterns including cp pitfalls and web server reload
|
|
- [[wiki/concepts/fastapi-mongodb-role-migration]] — the feature deployed in the same session where this bug was found
|
|
- [[wiki/architecture/_index]] — Docker Compose deployment patterns used alongside these scripts
|
|
|
|
## Sources
|
|
|
|
- [[daily/2026-04-16.md]] — `scripts/deploy.sh` in Ford QC web app discovered checking `backend/.git` and `frontend/.git`; monorepo never matched; fixed to `git pull` at root
|