Files
ERP-core/deploy/scripts/common.sh
T
ImanThiyanga 8e472ac996
CI/CD - ERP Core / scripts (pull_request) Failing after 12m21s
CI/CD - ERP Core / e2e-typecheck (pull_request) Failing after 13m13s
CI/CD - ERP Core / frontend (pull_request) Failing after 14m5s
CI/CD - ERP Core / backend (pull_request) Failing after 14m57s
CI/CD - ERP Core / detect (pull_request) Failing after 13m42s
CI/CD - ERP Core / Build & Deploy (pull_request) Failing after 12m47s
CI/CD - ERP Core / ci-ok (pull_request) Failing after 14m58s
initialising for ci-cd pipeline
2026-09-16 11:53:55 +05:30

132 lines
5.3 KiB
Bash

#!/usr/bin/env bash
# Shared settings + helpers for the ERP-Core CI/CD scripts. Sourced by the other scripts, never
# run directly. Runbook: docs/40-DEPLOYMENT.md (values here must match the server bootstrap, §4).
# shellcheck disable=SC2034 # variables are consumed by the scripts that source this file
set -euo pipefail
# ── Repository (folders whose git tree hash decides what is checked / built / deployed) ─────
BACKEND_PATH="Backend/ERPCore"
BACKEND_TESTS_PATH="Backend/ERPCore.Tests"
MIGRATIONS_PATH="Backend/ERPCore/Migrations"
FRONTEND_PATH="Frontend/erp-system"
E2E_PATH="Testing/e2e"
GITEA_URL="${GITEA_URL:-https://gitea.hexdive.com}"
REPO_SLUG="New_REP_SYSTEM/ERP-core"
REPO_GIT_URL="$GITEA_URL/$REPO_SLUG.git"
# ── Server layout of the ON-HOLD two-environment design (deploy/on-hold/). Active production does
# not use these paths — see .gitea/workflows/ci-cd.yml (erpcore.service, /home/erp/core/publish).
# ERP_ROOT still hosts the build lock taken by ci-backend.sh. ─────────────────────────────────
ERP_ROOT="${ERP_ROOT:-/opt/erpcore}"
RELEASES_DIR="$ERP_ROOT/releases/backend"
BUILD_LOCK="$ERP_ROOT/.build.lock"
BACKUP_DIR="${ERP_BACKUP_DIR:-/var/backups/erpcore}"
E2E_REPORTS_DIR="${ERP_E2E_REPORTS_DIR:-/var/lib/erpcore/e2e-reports}"
# ── Build images (builds run in CPU/memory-capped containers on the shared 8 GB VPS) ───────
DOTNET_SDK_IMAGE="mcr.microsoft.com/dotnet/sdk:10.0"
NODE_IMAGE="node:24-alpine"
WEB_IMAGE_REPO="erp-web"
DOTNET_EF_VERSION="10.0.9" # keep in step with Microsoft.EntityFrameworkCore.* in ERPCore.csproj
log() { printf '[erp] %s\n' "$*"; }
warn() { printf '[erp] WARNING: %s\n' "$*" >&2; }
fail() {
printf '[erp] ERROR: %s\n' "$*" >&2
exit 1
}
# load_env <test|release> — per-environment values. Ports, unit/container names and database
# names must match the server (systemd unit, Apache vhosts, /etc/erpcore/<env>.env).
# While both branches are on hold every call fails, so the lines after the case are unreachable.
# shellcheck disable=SC2317
load_env() {
ERP_ENV="$1"
case "$ERP_ENV" in
# ON HOLD — test environment (deploy/on-hold/README.md, docs/40-DEPLOYMENT.md "On hold").
# test)
# SERVICE="erpcore@test"
# BACKEND_PORT=5230
# WEB_CONTAINER="erp-web-test"
# WEB_PORT=3030
# DB_NAME="ERPCoreStaging"
# BACKUP_POLICY="on-migration"
# HEALTH_TIMEOUT=90
# PUBLIC_URL="https://test-erp.hexdive.com"
# ;;
# ON HOLD — the two-environment layout for release (/opt/erpcore, erpcore@release). NOT how
# production runs today: the active deploy is .gitea/workflows/ci-cd.yml → erpcore.service +
# /home/erp/core/publish. Nothing active calls load_env.
# release)
# SERVICE="erpcore@release"
# BACKEND_PORT=5220
# WEB_CONTAINER="erp-web"
# WEB_PORT=3020
# DB_NAME="ERPCore"
# BACKUP_POLICY="always"
# HEALTH_TIMEOUT=300
# PUBLIC_URL="https://erp.hexdive.com"
# ;;
*) fail "unknown environment '$ERP_ENV' (expected test or release)" ;;
esac
ENV_DIR="$ERP_ROOT/$ERP_ENV"
STATE_DIR="$ENV_DIR/.deployed"
CURRENT_LINK="$ENV_DIR/backend/current"
}
# env_for_branch <branch> — the environment a push to <branch> deploys to.
env_for_branch() {
case "$1" in
# ON HOLD — test environment: Dev) echo test ;;
production) echo release ;;
*) return 1 ;;
esac
}
# tree_hash <path> [rev] — git tree (or blob) id of a path. Identical folder content gives an
# identical hash no matter which commit, branch or merge produced it — that is what lets a
# Dev → production release reuse the build test already made. Empty if the path is absent.
tree_hash() { git rev-parse --verify --quiet "${2:-HEAD}:$1" 2>/dev/null || true; }
read_state() { cat "$STATE_DIR/$1" 2>/dev/null || true; }
write_state() {
mkdir -p "$STATE_DIR"
printf '%s\n' "$2" >"$STATE_DIR/$1.tmp"
mv -f "$STATE_DIR/$1.tmp" "$STATE_DIR/$1"
}
# record_history <side> <hash> <result> — append-only audit of every deploy attempt.
record_history() {
mkdir -p "$STATE_DIR"
printf '%s\t%s\t%s\t%s\tsha=%s\trun=%s\n' "$(date -u +%FT%TZ)" "$1" "$2" "$3" \
"${GITHUB_SHA:-manual}" "${GITHUB_RUN_NUMBER:-}" >>"$STATE_DIR/history.log"
}
# set_output <name> <value> — Gitea Actions step output (only logged when run by hand).
set_output() {
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then printf '%s=%s\n' "$1" "$2" >>"$GITHUB_OUTPUT"; fi
log "$1=$2"
}
# with_build_lock — serialize heavy work on this host. The runner's capacity is 1 today; this
# keeps two jobs from writing the same releases/<hash>.tmp or image tag if that is ever raised.
with_build_lock() {
mkdir -p "$ERP_ROOT"
exec 9>"$BUILD_LOCK"
flock 9
}
# git_remote <git args...> — run git with the ERPSECRET token as an HTTP header (never echoed,
# never written to .git/config).
git_remote() {
: "${ERP_GIT_TOKEN:?ERP_GIT_TOKEN (secrets.ERPSECRET) is required}"
local basic
basic="$(printf 'oauth2:%s' "$ERP_GIT_TOKEN" | base64 | tr -d '\n')"
git -c "http.extraHeader=Authorization: Basic $basic" "$@"
}
# selinux_mount_suffix — ":z" relabels bind mounts on SELinux hosts (AlmaLinux) so containers
# can read them; empty elsewhere (e.g. a developer laptop).
selinux_mount_suffix() {
if command -v selinuxenabled >/dev/null 2>&1 && selinuxenabled; then echo ":z"; fi
}