Compare commits

...

17 Commits
dev ... main

Author SHA1 Message Date
ea314c73ef updated deployment script to work with both stage and prod 2026-02-24 16:25:58 -06:00
879b95ccf8 fix typo in payments app 2026-02-05 16:44:03 -06:00
rocketdebris
68972cfb70 Added payments app. 2026-01-27 12:53:04 -05:00
a40263fb39 update script 2026-01-08 08:01:07 -06:00
404389d95a update deployment script 2026-01-08 07:25:13 -06:00
1bc4ce4810 update script 2026-01-08 07:17:25 -06:00
3f8868ff55 add set -e to script 2025-12-16 00:30:48 -06:00
Ben
f470c3da58 Update the repo to point to our backup. 2025-12-15 21:17:08 -05:00
702a59a041 fix script 2025-12-13 09:12:09 -06:00
a2c69b384a add to script for deployment 2025-12-12 17:38:11 -06:00
rocketdebris
566c71d891 Changed target repo from Shiloh to Frappe for ERPNext. 2025-11-26 08:28:36 -05:00
rocketdebris
08a601e2f7 Updated build_new.sh for container version 1.1.9 2025-11-25 17:23:52 -05:00
Ben
110c6eace7 Changed branches for custom_ui. 2025-10-28 15:25:52 -04:00
rocketdebris
e6e52b5628 Updated build method for Brotherton ERPNext instance. Export apps_new.json as env var, then run build_new.sh. 2025-10-23 20:29:05 -04:00
rocketdebris
b30f82191a build for 1.0.4-test. Fixed a trailing comma in JSON. 2025-10-20 15:29:49 -04:00
rocketdebris
3f36fedd55 build for 1.0.4-test. 2025-10-20 15:29:16 -04:00
5601d97782 Replace the frappe team's "hack" that used docker nested anonymous volumes to pull sites/assets from the base image with a much simpler solution using symlinks 2025-01-15 18:41:48 -05:00
7 changed files with 325 additions and 5 deletions

18
.apps_new.stage.json Normal file
View File

@ -0,0 +1,18 @@
[
{
"url": "https://github.com/frappe/erpnext",
"branch": "version-15"
},
{
"url": "https://github.com/frappe/hrms",
"branch": "version-15"
},
{
"url": "https://github.com/frappe/payments",
"branch": "version-15"
},
{
"url": "https://git.ben-nilsen.com/bnilsen/custom_ui.git",
"branch": "development"
}
]

18
apps_new.json Normal file
View File

@ -0,0 +1,18 @@
[
{
"url": "https://github.com/frappe/erpnext",
"branch": "version-15"
},
{
"url": "https://github.com/frappe/hrms",
"branch": "version-15"
},
{
"url": "https://github.com/frappe/payments",
"branch": "version-15"
},
{
"url": "https://git.ben-nilsen.com/bnilsen/custom_ui.git",
"branch": "main"
}
]

23
build.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
export APPS_JSON='[
{
"url": "https://githaven.org/Shiloh/brotherton-erpnext",
"branch": "production"
},
{
"url": "https://github.com/frappe/hrms",
"branch": "v15.15.0"
}
]'
export APPS_JSON_BASE64=$(echo ${APPS_JSON} | base64 -w 0)
export TAG="1.0.4-test" # Change this
docker build --platform=linux/amd64 \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=v15.15.0 \
--build-arg=PYTHON_VERSION=3.11.6 \
--build-arg=NODE_VERSION=18.18.2 \
--build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
--tag=githaven.org/shiloh/frappe_docker:$TAG \
--file=images/custom/Containerfile .
docker push githaven.org/shiloh/frappe_docker:$TAG

203
build_new.sh Executable file
View File

@ -0,0 +1,203 @@
#!/bin/bash
set -e
TAG=""
REMOTE_HOST="erp.stage.sprinklersnorthwest.com"
REMOTE_USER="lasthour"
MIGRATE=false
BUILD_ONLY=false
ALREADY_EXISTING=false
PROD_DEPLOYMENT=false
APPS_JSON_FILE="./apps_new.stage.json"
while [[ $# -gt 0 ]]; do
case "$1" in
--tag)
if [[ -z "${2:-}" ]]; then
echo "Error: --tag requires a value"
echo "Usage: $0 [--tag <string>] [--remote-host <host>] [--remote-user <user>]"
exit 1
fi
TAG="$2"
shift 2
;;
--migrate)
MIGRATE=true
shift 1
;;
--prod)
PROD_DEPLOYMENT=true
REMOTE_HOST="erp.sprinklersnorthwest.com"
APPS_JSON_FILE="./apps_new.json"
shift 1
;;
--remote-host)
if [[ -z "${2:-}" ]]; then
echo "Error: --remote-host requires a value"
echo "Usage: $0 [--tag <string>] [--remote-host <host>] [--remote-user <user>]"
exit 1
fi
REMOTE_HOST="$2"
shift 2
;;
--remote-user)
if [[ -z "${2:-}" ]]; then
echo "Error: --remote-user requires a value"
echo "Usage: $0 [--tag <string>] [--remote-host <host>] [--remote-user <user>]"
exit 1
fi
REMOTE_USER="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 --tag <version> [OPTIONS]"
echo ""
echo "Automated Build & Deploy Script for Brotherton Frappe Docker"
echo "--------------------------------------------------------"
echo ""
echo "description:"
echo " This script orchestrates the full deployment pipeline. It first validates that"
echo " the requested tag does not already exist locally, remotely, or in the registry."
echo " It then builds the Docker image, pushes it to the registry, and triggers the"
echo " remote deployment script."
echo ""
echo "Remote Deployment Actions (executed on server via re-deploy.sh):"
echo " 1. Updates 'frappe-compose.yml' with the new image tag (preserves backup)."
echo " 2. Restarts containers to load the new image."
echo " 3. Runs 'bench migrate' (only if --migrate is passed)."
echo " 4. Compiles assets via 'bench build' and 'bench build-frontend'."
echo " 5. cleanup: Removes old images (Patch Version - 2) to save space."
echo " 6. RECOVERY: If any step fails, it automatically rolls back config and containers."
echo ""
echo "Options:"
echo " --tag <string> REQUIRED. Version tag for the image (e.g., 1.0.0)."
echo " --migrate Run 'bench migrate' on the remote server."
echo " --prod Deploy to production server (overrides --remote-host)."
echo " --build-only Build and push only; skip remote deployment checks & action."
echo " --remote-host <host> Target server (Default: $REMOTE_HOST)."
echo " --remote-user <user> SSH User (Default: $REMOTE_USER)."
echo " -h, --help Show this help message."
echo ""
exit 0
;;
--build-only)
BUILD_ONLY=true
shift 1
;;
*)
echo "Usage: $0 [--tag <string>] [--remote-host <host>] [--remote-user <user>]"
exit 1
;;
esac
done
if [[ -z "$TAG" ]]; then
echo "Error: --tag is required"
echo "Usage: $0 [--tag <string>] [--remote-host <host>] [--remote-user <user>]"
exit 1
fi
cleanup() {
set +e
echo "🚨 Build failed! Starting cleanup..."
IMAGE_NAME="githaven.org/shiloh/brotherton_frappe_docker:$TAG"
# Local cleanup
if docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
echo "🗑️ Removing local image $IMAGE_NAME..."
docker rmi -f "$IMAGE_NAME"
else
echo "Local image $IMAGE_NAME not found."
fi
# Remote cleanup
echo "Checking remote registry for $IMAGE_NAME..."
if skopeo inspect "docker://$IMAGE_NAME" >/dev/null 2>&1; then
echo "🗑️ Removing remote image $IMAGE_NAME..."
skopeo delete "docker://$IMAGE_NAME"
else
echo "Remote image $IMAGE_NAME not found."
fi
}
echo ""
echo "+-----------------------------------------------+"
echo " ██████╗ ██╗ ██╗██╗██╗ ██████╗ ██╗ ██╗"
echo " ██╔════╝ ██║ ██║██║██║ ██╔═══██╗██║ ██║"
echo " ╚█████╗ ███████║██║██║ ██║ ██║███████║"
echo " ╚═══██╗ ██╔══██║██║██║ ██║ ██║██╔══██║"
echo " ██████╔╝ ██║ ██║██║███████╗╚██████╔╝██║ ██║"
echo " ╚═════╝ ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝"
echo "+-----------------------------------------------+"
echo " Automated Build & Deploy Script for Brotherton Frappe Docker"
echo ""
sleep 3
trap 'cleanup' ERR
IMAGE_NAME="githaven.org/shiloh/brotherton_frappe_docker:$TAG"
echo "🔍 Checking for pre-existing tag: $TAG"
if skopeo inspect "docker://$IMAGE_NAME" >/dev/null 2>&1; then
echo "❗ Tag $TAG already exists in the remote registry."
ALREADY_EXISTING=true
else
echo "✅ Tag $TAG is available in registry."
fi
if docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
echo "❗ Tag $TAG already exists in the local Docker images."
ALREADY_EXISTING=true
else
echo "✅ Tag $TAG is available locally."
fi
if [[ -n "$REMOTE_HOST" ]] && [ "$BUILD_ONLY" = false ]; then
echo "Checking remote server $REMOTE_HOST for existing image..."
if ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "docker image inspect $IMAGE_NAME >/dev/null 2>&1"; then
echo "❗ Tag $TAG already exists on remote server $REMOTE_HOST."
ALREADY_EXISTING=true
else
echo "✅ Tag $TAG is available on remote server."
fi
fi
if [ "$ALREADY_EXISTING" = true ]; then
echo "⚠️ Build aborted due to existing tag. View logs above to identify where the tag exists."
exit 1
fi
export TAG
export APPS_JSON_BASE64=$(base64 -w 0 "$APPS_JSON_FILE")
echo "Building Brotherton Frappe Docker Image with tag: $TAG"
echo "APPS_JSON_BASE64: $APPS_JSON_BASE64"
echo "🚀 Starting Docker build..."
docker build --no-cache \
--build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
--build-arg=FRAPPE_BRANCH=version-15 \
--build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
--tag=githaven.org/shiloh/brotherton_frappe_docker:$TAG \
--file=images/layered/Containerfile .
echo "✅ Docker build completed!"
echo "📤 Pushing image to registry..."
docker push githaven.org/shiloh/brotherton_frappe_docker:$TAG
echo "✅ Image pushed successfully!"
MIGRATE_COMMAND=""
if [ "$MIGRATE" = true ]; then
MIGRATE_COMMAND="--migrate"
fi
if [[ -n "$REMOTE_HOST" ]] && [ "$BUILD_ONLY" = false ]; then
echo "🔗 Connecting to remote server $REMOTE_USER@$REMOTE_HOST..."
ssh "$REMOTE_USER@$REMOTE_HOST" "./re-deploy.sh --tag $TAG $MIGRATE_COMMAND"
echo "✅ Remote deployment completed!"
else
echo "⚙️ Build-only mode enabled; skipping remote deployment."
fi
if [ "$BUILD_ONLY" = false ]; then
echo "🎉 Deployment of tag $TAG completed successfully!"
else
echo "🎉 Build and push of tag $TAG completed successfully!"
fi

View File

@ -27,6 +27,8 @@ services:
command:
- >
ls -1 apps > sites/apps.txt;
rm -rf sites/assets || true;
ln -s /home/frappe/frappe-bench/assets sites/assets || true;
bench set-config -g db_host $$DB_HOST;
bench set-config -gp db_port $$DB_PORT;
bench set-config -g redis_cache "redis://$$REDIS_CACHE";

View File

@ -131,11 +131,9 @@ COPY --from=builder --chown=frappe:frappe /home/frappe/frappe-bench /home/frappe
WORKDIR /home/frappe/frappe-bench
VOLUME [ \
"/home/frappe/frappe-bench/sites", \
"/home/frappe/frappe-bench/sites/assets", \
"/home/frappe/frappe-bench/logs" \
]
# Move the generated assets folder out of the "sites" folder, which will be attached to a volume and thus persisted
# So that it can be referenced by symlink even after "sites" is replaced with the volume
RUN mv /home/frappe/frappe-bench/sites/assets /home/frappe/frappe-bench/assets
CMD [ \
"/home/frappe/frappe-bench/env/bin/gunicorn", \

View File

@ -0,0 +1,58 @@
ARG FRAPPE_BRANCH=version-15
FROM frappe/build:${FRAPPE_BRANCH} AS builder
ARG FRAPPE_BRANCH=version-15
ARG FRAPPE_PATH=https://github.com/frappe/frappe
ARG APPS_JSON_BASE64
USER root
RUN if [ -n "${APPS_JSON_BASE64}" ]; then \
mkdir /opt/frappe && echo "${APPS_JSON_BASE64}" | base64 -d > /opt/frappe/apps.json; \
fi
USER frappe
RUN export APP_INSTALL_ARGS="" && \
if [ -n "${APPS_JSON_BASE64}" ]; then \
export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \
fi && \
bench init ${APP_INSTALL_ARGS}\
--frappe-branch=${FRAPPE_BRANCH} \
--frappe-path=${FRAPPE_PATH} \
--no-procfile \
--no-backups \
--skip-redis-config-generation \
--verbose \
/home/frappe/frappe-bench && \
cd /home/frappe/frappe-bench && \
echo "{}" > sites/common_site_config.json && \
find apps -mindepth 1 -path "*/.git" | xargs rm -fr
FROM frappe/base:${FRAPPE_BRANCH} AS backend
USER frappe
COPY --from=builder --chown=frappe:frappe /home/frappe/frappe-bench /home/frappe/frappe-bench
WORKDIR /home/frappe/frappe-bench
VOLUME [ \
"/home/frappe/frappe-bench/sites", \
"/home/frappe/frappe-bench/sites/assets", \
"/home/frappe/frappe-bench/logs" \
]
CMD [ \
"/home/frappe/frappe-bench/env/bin/gunicorn", \
"--chdir=/home/frappe/frappe-bench/sites", \
"--bind=0.0.0.0:8000", \
"--threads=4", \
"--workers=2", \
"--worker-class=gthread", \
"--worker-tmp-dir=/dev/shm", \
"--timeout=120", \
"--preload", \
"frappe.app:application" \
]