fix(split): stage deploy root files only if present for git add
**Motivations:** - split script failed after subtree split when optional root files (e.g. .dockerignore) were missing on branch test **Root causes:** - git add with a missing path in the list fails entirely and stages nothing; git commit then fails under set -e **Correctifs:** - add each copied file only if it exists in the deploy repo; skip commit if index empty **Evolutions:** - none **Pages affectées:** - setup/split-lecoffre-ng-to-five-repos.sh
This commit is contained in:
parent
74cd0050d8
commit
259fc62cc3
208
setup/split-lecoffre-ng-to-five-repos.sh
Executable file
208
setup/split-lecoffre-ng-to-five-repos.sh
Executable file
@ -0,0 +1,208 @@
|
||||
#!/bin/bash
|
||||
# Split lecoffre_ng (branch test) into five Git repos with history (git subtree split).
|
||||
# Does NOT read or write /home/ncantu/code/lecoffre_ng: work is done in a disposable clone
|
||||
# from Gitea (or SPLIT_CLONE_URL). See docs/split-lecoffre-repos.md
|
||||
#
|
||||
# Env:
|
||||
# SPLIT_CLONE_URL clone source (default: git@git.4nkweb.com:4nk/lecoffre_ng.git)
|
||||
# SOURCE_BRANCH branch to split (default: test)
|
||||
# OUTPUT_BASE parent directory for output repos (default: /home/ncantu/code)
|
||||
# REPLACE_OUTPUT=1 remove existing lecoffre-io-*_ng dirs before rebuilding
|
||||
# PUSH=1 git push -u origin main for each sub-repo after commits
|
||||
# MAIN_BRANCH default: main
|
||||
#
|
||||
# Usage:
|
||||
# REPLACE_OUTPUT=1 ./split-lecoffre-ng-to-five-repos.sh
|
||||
# REPLACE_OUTPUT=1 PUSH=1 ./split-lecoffre-ng-to-five-repos.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CLONE_URL="${SPLIT_CLONE_URL:-git@git.4nkweb.com:4nk/lecoffre_ng.git}"
|
||||
SOURCE_BRANCH="${SOURCE_BRANCH:-test}"
|
||||
OUT="${OUTPUT_BASE:-/home/ncantu/code}"
|
||||
MAIN="${MAIN_BRANCH:-main}"
|
||||
PUSH="${PUSH:-0}"
|
||||
REPLACE_OUTPUT="${REPLACE_OUTPUT:-0}"
|
||||
|
||||
die() {
|
||||
echo "ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
declare -A REMOTES=(
|
||||
[docs]="git@git.4nkweb.com:4nk/lecoffre-io-docs_ng.git"
|
||||
[deploy]="git@git.4nkweb.com:4nk/lecoffre-io-deploy_ng.git"
|
||||
[shared]="git@git.4nkweb.com:4nk/lecoffre-io-shared_ng.git"
|
||||
[frontend]="git@git.4nkweb.com:4nk/lecoffre-io-frontend_ng.git"
|
||||
[backend]="git@git.4nkweb.com:4nk/lecoffre-io-backend_ng.git"
|
||||
)
|
||||
|
||||
declare -A DIRS=(
|
||||
[docs]="lecoffre-io-docs_ng"
|
||||
[deploy]="lecoffre-io-deploy_ng"
|
||||
[shared]="lecoffre-io-shared_ng"
|
||||
[frontend]="lecoffre-io-frontend_ng"
|
||||
[backend]="lecoffre-io-backend_ng"
|
||||
)
|
||||
|
||||
declare -A PREFIX=(
|
||||
[docs]="docs"
|
||||
[deploy]="deploy"
|
||||
[shared]="lecoffre-ressources-dev"
|
||||
[frontend]="lecoffre-front-main"
|
||||
[backend]="lecoffre-back-main"
|
||||
)
|
||||
|
||||
WORK="$(mktemp -d)"
|
||||
MONO="${WORK}/mono"
|
||||
cleanup() {
|
||||
rm -rf "${WORK}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "Clone: ${CLONE_URL} (branch ${SOURCE_BRANCH})"
|
||||
echo "Output: ${OUT}"
|
||||
echo "Replace existing: ${REPLACE_OUTPUT}"
|
||||
echo "Push: ${PUSH}"
|
||||
echo ""
|
||||
|
||||
git clone --branch "${SOURCE_BRANCH}" --single-branch "${CLONE_URL}" "${MONO}"
|
||||
cd "${MONO}"
|
||||
git rev-parse --verify "${SOURCE_BRANCH}" >/dev/null || die "Branch ${SOURCE_BRANCH} missing after clone"
|
||||
|
||||
split_branch() {
|
||||
local key="$1"
|
||||
local br="split-lecoffre-${key}"
|
||||
cd "${MONO}"
|
||||
git branch -D "${br}" 2>/dev/null || true
|
||||
git subtree split -P "${PREFIX[${key}]}" -b "${br}" "${SOURCE_BRANCH}" >/dev/null
|
||||
}
|
||||
|
||||
# On branch test, docs/ may be absent: ship top-level *.md into the docs repo instead.
|
||||
init_docs_repo() {
|
||||
local dest="${OUT}/${DIRS[docs]}"
|
||||
if [ "${REPLACE_OUTPUT}" = "1" ] && [ -d "${dest}" ]; then
|
||||
rm -rf "${dest}"
|
||||
fi
|
||||
if [ -d "${dest}" ]; then
|
||||
die "Destination exists: ${dest} (set REPLACE_OUTPUT=1 to overwrite)"
|
||||
fi
|
||||
mkdir -p "${dest}"
|
||||
cd "${dest}"
|
||||
git init -b "${MAIN}"
|
||||
shopt -s nullglob
|
||||
local f
|
||||
for f in "${MONO}"/*.md; do
|
||||
cp -a "${f}" "${dest}/$(basename "${f}")"
|
||||
done
|
||||
shopt -u nullglob
|
||||
if [ -z "$(git status --porcelain)" ]; then
|
||||
die "No *.md at monorepo root; cannot build docs repo without docs/"
|
||||
fi
|
||||
git add .
|
||||
git commit -m "Import root markdown from lecoffre_ng (branch ${SOURCE_BRANCH})"
|
||||
git remote add origin "${REMOTES[docs]}"
|
||||
}
|
||||
|
||||
init_from_split() {
|
||||
local key="$1"
|
||||
local dest="${OUT}/${DIRS[${key}]}"
|
||||
split_branch "${key}"
|
||||
local br="split-lecoffre-${key}"
|
||||
if [ "${REPLACE_OUTPUT}" = "1" ] && [ -d "${dest}" ]; then
|
||||
rm -rf "${dest}"
|
||||
fi
|
||||
if [ -d "${dest}" ]; then
|
||||
die "Destination exists: ${dest} (set REPLACE_OUTPUT=1 to overwrite)"
|
||||
fi
|
||||
mkdir -p "${dest}"
|
||||
cd "${dest}"
|
||||
git init -b "${MAIN}"
|
||||
git pull "${MONO}" "${br}"
|
||||
git remote add origin "${REMOTES[${key}]}"
|
||||
cd "${MONO}"
|
||||
git branch -D "split-lecoffre-${key}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
add_root_docs() {
|
||||
local dest="${OUT}/${DIRS[docs]}"
|
||||
local f
|
||||
for f in CHANGELOG.md; do
|
||||
if [ -f "${MONO}/${f}" ]; then
|
||||
cp -a "${MONO}/${f}" "${dest}/${f}"
|
||||
fi
|
||||
done
|
||||
cd "${dest}"
|
||||
if git status --porcelain | grep -q .; then
|
||||
git add CHANGELOG.md 2>/dev/null || true
|
||||
git commit -m "Add CHANGELOG from monorepo root (branch ${SOURCE_BRANCH})"
|
||||
fi
|
||||
}
|
||||
|
||||
add_root_deploy() {
|
||||
local dest="${OUT}/${DIRS[deploy]}"
|
||||
local files=(
|
||||
VERSION
|
||||
package.json
|
||||
package-lock.json
|
||||
.dockerignore
|
||||
.editorconfig
|
||||
.gitattributes
|
||||
.gitmessage
|
||||
.prettierignore
|
||||
README.md
|
||||
)
|
||||
local f
|
||||
for f in "${files[@]}"; do
|
||||
if [ -e "${MONO}/${f}" ]; then
|
||||
cp -a "${MONO}/${f}" "${dest}/${f}"
|
||||
fi
|
||||
done
|
||||
cd "${dest}"
|
||||
if ! git status --porcelain | grep -q .; then
|
||||
return 0
|
||||
fi
|
||||
# git add with a missing path fails the whole command and stages nothing; add only present files.
|
||||
for f in "${files[@]}"; do
|
||||
if [ -e "${f}" ]; then
|
||||
git add "${f}"
|
||||
fi
|
||||
done
|
||||
if git diff --cached --quiet; then
|
||||
return 0
|
||||
fi
|
||||
git commit -m "Add monorepo root metadata for deploy repo (branch ${SOURCE_BRANCH})"
|
||||
}
|
||||
|
||||
do_push() {
|
||||
local key="$1"
|
||||
local dest="${OUT}/${DIRS[${key}]}"
|
||||
cd "${dest}"
|
||||
git push -u origin "${MAIN}"
|
||||
}
|
||||
|
||||
echo "=== docs -> ${DIRS[docs]} ==="
|
||||
if [ -d "${MONO}/docs" ]; then
|
||||
init_from_split "docs"
|
||||
add_root_docs
|
||||
else
|
||||
echo "(no docs/ on ${SOURCE_BRANCH}: using root *.md)"
|
||||
init_docs_repo
|
||||
fi
|
||||
|
||||
for key in deploy shared frontend backend; do
|
||||
echo "=== ${key} -> ${DIRS[${key}]} (${PREFIX[${key}]}) ==="
|
||||
init_from_split "${key}"
|
||||
done
|
||||
|
||||
add_root_deploy
|
||||
|
||||
if [ "${PUSH}" = "1" ]; then
|
||||
for key in docs deploy shared frontend backend; do
|
||||
echo "=== push ${key} ==="
|
||||
do_push "${key}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done. Repos under ${OUT}/lecoffre-io-*_ng (from ${SOURCE_BRANCH}, lecoffre_ng local untouched)."
|
||||
Loading…
x
Reference in New Issue
Block a user