06e5bd7f46
- 1 - I updated `smart-build.sh` so its interactive architecture menu now offers `macos-amd64`, `macos-arm64`, and includes both Darwin targets in `All Arch`, while preserving the existing `darwin` artifact naming in `dist/`. - 2 - I added a dedicated Darwin SQLite build path in `smart-build.sh` that routes macOS `bindata sqlite sqlite_unlock_notify` builds through `make release-darwin`, and I updated `Makefile` to make `release-darwin` configurable through `DARWIN_ARCHS` so helper scripts can request only `darwin-10.12/amd64` or `darwin-10.12/arm64`. - 3 - I hardened the Darwin SQLite flow in `smart-build.sh` for `code-server`-style containerized workspaces by distinguishing between a missing Docker CLI and an unreachable Docker daemon, by validating that the host Docker daemon can see the same mounted repository `go.mod` path as the current workspace, and by moving the temporary release output under `dist/` instead of `/tmp`. - 4 - I added `SMART_BUILD_DARWIN_HOST_REPO_PATH` support to `smart-build.sh` so Darwin SQLite builds can be redirected to a host-visible repository mount path when the interactive workspace path inside the container differs from the real host path used by the Docker daemon.
436 lines
13 KiB
Bash
Executable File
436 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Folosește instalarea Go standard dacă există, chiar dacă nu este în PATH.
|
|
if [ -x "/usr/local/go/bin/go" ]; then
|
|
export PATH="/usr/local/go/bin:$PATH"
|
|
fi
|
|
|
|
# Încarcă NVM dacă este disponibil
|
|
export NVM_DIR="$HOME/.nvm"
|
|
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
|
|
# Forțează folosirea versiunii 22
|
|
nvm use 22 > /dev/null 2>&1 || echo "⚠️ NVM nu a putut activa Node 22 automatically."
|
|
|
|
resolve_build_ref() {
|
|
git describe --tags --exact-match 2>/dev/null || git describe --tags --always
|
|
}
|
|
|
|
require_docker_for_darwin_sqlite() {
|
|
if ! command -v docker > /dev/null 2>&1; then
|
|
echo "❌ Docker is required for macOS SQLite cross-builds."
|
|
echo " Install the Docker CLI in this environment, or use the non-SQLite macOS build option."
|
|
echo " If you are running inside a code-server container, also mount the host Docker socket."
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker info > /dev/null 2>&1; then
|
|
echo "❌ Docker is installed but the daemon is not reachable."
|
|
echo " Start Docker, or expose the host Docker daemon to this container."
|
|
echo " For a code-server container, mount /var/run/docker.sock from the host."
|
|
if [ -n "${DOCKER_HOST:-}" ]; then
|
|
echo " Current DOCKER_HOST: ${DOCKER_HOST}"
|
|
else
|
|
echo " Current DOCKER_HOST is unset."
|
|
fi
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
resolve_xgo_image() {
|
|
local xgo_version
|
|
|
|
xgo_version="$(awk '$1 == "XGO_VERSION" { print $3; exit }' Makefile 2>/dev/null)"
|
|
if [ -z "$xgo_version" ]; then
|
|
xgo_version="go-1.25.x"
|
|
fi
|
|
|
|
printf 'ghcr.io/techknowlogick/xgo:%s' "$xgo_version"
|
|
}
|
|
|
|
resolve_darwin_sqlite_repo_root() {
|
|
local override_path
|
|
|
|
override_path="${SMART_BUILD_DARWIN_HOST_REPO_PATH:-}"
|
|
if [ -z "$override_path" ]; then
|
|
pwd -P
|
|
return
|
|
fi
|
|
|
|
if [ ! -d "$override_path" ] || [ ! -f "$override_path/go.mod" ]; then
|
|
echo "❌ SMART_BUILD_DARWIN_HOST_REPO_PATH is set, but the path is not usable in this container:"
|
|
echo " $override_path"
|
|
echo " Mount the host repository path into the container at the same absolute path, then retry."
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s' "$override_path"
|
|
}
|
|
|
|
validate_repo_bind_mount_for_darwin_sqlite() {
|
|
local repo_path="$1"
|
|
local xgo_image
|
|
|
|
xgo_image="$(resolve_xgo_image)"
|
|
|
|
if ! docker run --rm -v "$repo_path":/probe:ro --entrypoint sh "$xgo_image" -lc 'test -f /probe/go.mod'; then
|
|
echo "❌ Docker can reach the daemon, but the daemon cannot mount this repository path correctly:"
|
|
echo " $repo_path"
|
|
echo " The xgo container only sees an empty or different host path, so /source/go.mod is missing there."
|
|
echo " If smart-build runs inside a code-server container with the host Docker socket,"
|
|
echo " the repository must be mounted from a host bind path that exists at the same absolute path."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
write_sha256_file() {
|
|
local artifact_path="$1"
|
|
local artifact_dir artifact_name
|
|
|
|
artifact_dir="$(dirname "$artifact_path")"
|
|
artifact_name="$(basename "$artifact_path")"
|
|
|
|
if command -v sha256sum > /dev/null 2>&1; then
|
|
(
|
|
cd "$artifact_dir" || exit 1
|
|
sha256sum "$artifact_name" > "$artifact_name.sha256"
|
|
)
|
|
return
|
|
fi
|
|
|
|
if command -v shasum > /dev/null 2>&1; then
|
|
(
|
|
cd "$artifact_dir" || exit 1
|
|
shasum -a 256 "$artifact_name" > "$artifact_name.sha256"
|
|
)
|
|
return
|
|
fi
|
|
|
|
echo "❌ Neither sha256sum nor shasum is available for checksum generation."
|
|
exit 1
|
|
}
|
|
|
|
# --- 1. VERIFICARE INTEGRITATE ȘI CURĂȚARE CACHE INIȚIALĂ ---
|
|
echo "🔍 Initialization checks..."
|
|
|
|
if ! command -v go > /dev/null 2>&1; then
|
|
echo "❌ Go nu este disponibil în PATH. Instalează Go 1.26.2 sau adaugă binarul go în PATH."
|
|
exit 1
|
|
fi
|
|
|
|
notify_human_interaction() {
|
|
local bell_oga="/usr/share/sounds/freedesktop/stereo/bell.oga"
|
|
local bell_wav="/usr/share/sounds/alsa/Front_Center.wav"
|
|
local in_vscode_terminal=0
|
|
local notification_sent=0
|
|
|
|
if [ "${TERM_PROGRAM:-}" = "vscode" ] || [ -n "${VSCODE_IPC_HOOK_CLI:-}" ] || [ -n "${VSCODE_GIT_IPC_HANDLE:-}" ]; then
|
|
in_vscode_terminal=1
|
|
fi
|
|
|
|
if command -v notify-send > /dev/null 2>&1; then
|
|
notify-send "Gitea smart-build" "Human input required in smart-build.sh" > /dev/null 2>&1 && notification_sent=1
|
|
fi
|
|
|
|
if command -v canberra-gtk-play > /dev/null 2>&1; then
|
|
canberra-gtk-play -i bell > /dev/null 2>&1 && return
|
|
fi
|
|
|
|
if [ -f "$bell_oga" ] && command -v paplay > /dev/null 2>&1; then
|
|
paplay "$bell_oga" > /dev/null 2>&1 && return
|
|
fi
|
|
|
|
if [ -f "$bell_wav" ] && command -v aplay > /dev/null 2>&1; then
|
|
aplay -q "$bell_wav" > /dev/null 2>&1 && return
|
|
fi
|
|
|
|
if [ -f "$bell_wav" ] && command -v play > /dev/null 2>&1; then
|
|
play -q "$bell_wav" > /dev/null 2>&1 && return
|
|
fi
|
|
|
|
if [ -t 1 ]; then
|
|
printf '\a'
|
|
fi
|
|
|
|
if [ "$notification_sent" -eq 0 ] && [ "$in_vscode_terminal" -eq 1 ]; then
|
|
printf '\033[1;33m%s\033[0m\n' ">>> Human input required below <<<"
|
|
fi
|
|
}
|
|
|
|
apply_moderate_build_limits() {
|
|
local go_procs="$1"
|
|
local node_memory="$2"
|
|
|
|
export GOMAXPROCS="$go_procs"
|
|
export MAKEFLAGS="-j1"
|
|
|
|
if [[ "$NODE_OPTIONS" != *"--max-old-space-size="* ]]; then
|
|
export NODE_OPTIONS="${NODE_OPTIONS:+$NODE_OPTIONS }--max-old-space-size=$node_memory"
|
|
fi
|
|
}
|
|
|
|
echo ""
|
|
echo "⚙️ Select Build Load Profile:"
|
|
echo " Normal keeps the default build behavior."
|
|
echo " Moderate limits parallel jobs and keeps CPU/RAM usage lower."
|
|
echo " Low Resource is slower, but safest for weaker machines."
|
|
notify_human_interaction
|
|
load_options=("Normal" "Moderate (GOMAXPROCS=2, make -j1)" "Low Resource (GOMAXPROCS=1, make -j1)" "Quit")
|
|
select opt in "${load_options[@]}"
|
|
do
|
|
case $opt in
|
|
"Normal")
|
|
echo "✅ Selected: Normal build profile."
|
|
break
|
|
;;
|
|
"Moderate (GOMAXPROCS=2, make -j1)")
|
|
apply_moderate_build_limits 2 2048
|
|
echo "✅ Selected: Moderate build profile."
|
|
echo " GOMAXPROCS=$GOMAXPROCS MAKEFLAGS=\"$MAKEFLAGS\" NODE_OPTIONS=\"$NODE_OPTIONS\""
|
|
break
|
|
;;
|
|
"Low Resource (GOMAXPROCS=1, make -j1)")
|
|
apply_moderate_build_limits 1 2048
|
|
echo "✅ Selected: Low Resource build profile."
|
|
echo " GOMAXPROCS=$GOMAXPROCS MAKEFLAGS=\"$MAKEFLAGS\" NODE_OPTIONS=\"$NODE_OPTIONS\""
|
|
break
|
|
;;
|
|
"Quit")
|
|
exit 0
|
|
;;
|
|
*) echo "Opțiune invalidă $REPLY";;
|
|
esac
|
|
done
|
|
|
|
# Dacă compilarea anterioară a fost întreruptă, ștergem binarul parțial
|
|
if [ -f "gitea" ] || [ -f "gitea.exe" ]; then
|
|
echo "🧹 Garbages found. Cleanning..."
|
|
rm -f gitea gitea.exe
|
|
fi
|
|
|
|
# Verificăm dacă node_modules există. Dacă nu, forțăm pnpm install
|
|
if [ ! -d "node_modules" ]; then
|
|
echo "⚠️ node_modules missing. Instaling..."
|
|
if ! pnpm install --frozen-lockfile; then
|
|
echo "❌ Fail to install frontend dependencies."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# --- 2. LOGICĂ FRONTEND (CHECKSUM) ---
|
|
CHECKSUM_FILE=".frontend.hash"
|
|
CURRENT_HASH=$(find web_src package.json tailwind.config.js -type f -print0 2>/dev/null | xargs -0 sha1sum | sha1sum | awk '{print $1}')
|
|
|
|
if [ -f "$CHECKSUM_FILE" ] && [ "$CURRENT_HASH" == "$(cat $CHECKSUM_FILE)" ]; then
|
|
echo "✅ Frontend is unchanged."
|
|
else
|
|
echo "🚀 Code changes detected. Running frontend build..."
|
|
if ! make frontend; then
|
|
echo "❌ Fail to build frontend assets."
|
|
exit 1
|
|
fi
|
|
echo "$CURRENT_HASH" > "$CHECKSUM_FILE"
|
|
fi
|
|
|
|
# --- 3. MENIU INTERACTIV PENTRU ARHITECTURĂ ---
|
|
echo ""
|
|
echo "🎯 Select Arch to build:"
|
|
notify_human_interaction
|
|
arch_options=("linux-amd64" "linux-armv7" "windows-amd64" "macos-amd64" "macos-arm64" "All Arch" "Quit")
|
|
select opt in "${arch_options[@]}"
|
|
do
|
|
case $opt in
|
|
"linux-amd64")
|
|
TARGETS=("linux/amd64")
|
|
break
|
|
;;
|
|
"linux-armv7")
|
|
TARGETS=("linux/arm/7")
|
|
break
|
|
;;
|
|
"windows-amd64")
|
|
TARGETS=("windows/amd64")
|
|
break
|
|
;;
|
|
"macos-amd64")
|
|
TARGETS=("darwin/amd64")
|
|
break
|
|
;;
|
|
"macos-arm64")
|
|
TARGETS=("darwin/arm64")
|
|
break
|
|
;;
|
|
"All Arch")
|
|
TARGETS=("linux/amd64" "linux/arm/7" "windows/amd64" "darwin/amd64" "darwin/arm64")
|
|
break
|
|
;;
|
|
"Quit")
|
|
exit 0
|
|
;;
|
|
*) echo "Opțiune invalidă $REPLY";;
|
|
esac
|
|
done
|
|
|
|
echo ""
|
|
echo "🏷️ Select Build Tags:"
|
|
notify_human_interaction
|
|
tag_options=("bindata" "bindata sqlite sqlite_unlock_notify" "Quit")
|
|
select opt in "${tag_options[@]}"
|
|
do
|
|
case $opt in
|
|
"bindata")
|
|
BUILD_TAGS="bindata"
|
|
break
|
|
;;
|
|
"bindata sqlite sqlite_unlock_notify")
|
|
BUILD_TAGS="bindata sqlite sqlite_unlock_notify"
|
|
BUILD_VARIANT="sqlite"
|
|
break
|
|
;;
|
|
"Quit")
|
|
exit 0
|
|
;;
|
|
*) echo "Opțiune invalidă $REPLY";;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$BUILD_VARIANT" ]; then
|
|
BUILD_VARIANT="default"
|
|
fi
|
|
|
|
BUILD_REF="$(resolve_build_ref)"
|
|
BUILD_REF="${BUILD_REF//\//-}"
|
|
echo "🏷️ Build tag/reference: $BUILD_REF"
|
|
|
|
bindata_needs_update() {
|
|
local source_dir="$1"
|
|
local bindata_file="$2"
|
|
|
|
if [ ! -f "$bindata_file" ]; then
|
|
return 0
|
|
fi
|
|
|
|
find "$source_dir" -type f -newer "$bindata_file" -print -quit 2>/dev/null | grep -q .
|
|
}
|
|
|
|
ensure_bindata_asset() {
|
|
local label="$1"
|
|
local source_dir="$2"
|
|
local go_package="$3"
|
|
local bindata_file="$4"
|
|
|
|
if bindata_needs_update "$source_dir" "$bindata_file"; then
|
|
echo "♻️ Regenerating $label bindata..."
|
|
if ! CC= GOOS= GOARCH= CGO_ENABLED=0 go generate -tags bindata "$go_package"; then
|
|
echo "❌ Failed to regenerate $label bindata."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✅ $label bindata is up to date."
|
|
fi
|
|
}
|
|
|
|
ensure_bindata_assets() {
|
|
if [[ " $BUILD_TAGS " != *" bindata "* ]]; then
|
|
return
|
|
fi
|
|
|
|
echo "🔎 Checking embedded bindata assets..."
|
|
ensure_bindata_asset "templates" "templates" "./modules/templates" "modules/templates/bindata.dat"
|
|
ensure_bindata_asset "options" "options" "./modules/options" "modules/options/bindata.dat"
|
|
ensure_bindata_asset "public" "public" "./modules/public" "modules/public/bindata.dat"
|
|
ensure_bindata_asset "migration schemas" "modules/migration/schemas" "./modules/migration" "modules/migration/bindata.dat"
|
|
}
|
|
|
|
ensure_bindata_assets
|
|
|
|
build_darwin_sqlite_target() {
|
|
local arch="$1"
|
|
local output="$2"
|
|
local repo_root temp_dist built_file output_abs
|
|
local built_files=()
|
|
|
|
require_docker_for_darwin_sqlite
|
|
repo_root="$(resolve_darwin_sqlite_repo_root)"
|
|
validate_repo_bind_mount_for_darwin_sqlite "$repo_root"
|
|
output_abs="$(pwd -P)/$output"
|
|
|
|
temp_dist="$repo_root/dist/.smart-build-darwin-${arch}-$$"
|
|
rm -rf "$temp_dist"
|
|
if ! mkdir -p "$temp_dist"; then
|
|
echo "❌ Failed to create a temporary macOS release directory in dist/."
|
|
exit 1
|
|
fi
|
|
|
|
echo "📦 Building for darwin/$arch with TAGS=\"$BUILD_TAGS\" via release-darwin..."
|
|
if ! make -C "$repo_root" release-darwin TAGS="$BUILD_TAGS" DARWIN_ARCHS="darwin-10.12/$arch" DIST="$temp_dist"; then
|
|
rm -rf "$temp_dist"
|
|
echo "❌ Fail to build for darwin/$arch with SQLite"
|
|
exit 1
|
|
fi
|
|
|
|
mapfile -t built_files < <(find "$temp_dist/binaries" -maxdepth 1 -type f | sort)
|
|
if [ "${#built_files[@]}" -ne 1 ]; then
|
|
rm -rf "$temp_dist"
|
|
echo "❌ Unexpected macOS artifact count for darwin/$arch: ${#built_files[@]}"
|
|
exit 1
|
|
fi
|
|
built_file="${built_files[0]}"
|
|
|
|
mv "$built_file" "$output_abs"
|
|
rm -rf "$temp_dist"
|
|
|
|
write_sha256_file "$output_abs"
|
|
echo "✅ Created: $output_abs"
|
|
echo "✅ Created: $output_abs.sha256"
|
|
}
|
|
|
|
build_standard_target() {
|
|
local os="$1"
|
|
local arch="$2"
|
|
local arm_ver="$3"
|
|
local output="$4"
|
|
local ext="$5"
|
|
|
|
export GOOS=$os
|
|
export GOARCH=$arch
|
|
export GOARM=$arm_ver
|
|
export CGO_ENABLED=0
|
|
if [ "$BUILD_VARIANT" == "sqlite" ]; then
|
|
export CGO_ENABLED=1
|
|
fi
|
|
|
|
if make build TAGS="$BUILD_TAGS"; then
|
|
mv "gitea$ext" "$output"
|
|
write_sha256_file "$output"
|
|
echo "✅ Created: $output"
|
|
echo "✅ Created: $output.sha256"
|
|
else
|
|
echo "❌ Fail to build for $os/$arch${arm_ver:+/v$arm_ver}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# --- 4. COMPILARE ---
|
|
mkdir -p dist
|
|
for TARGET in "${TARGETS[@]}"; do
|
|
IFS="/" read -r OS ARCH ARM_VER <<< "$TARGET"
|
|
|
|
EXT="" && [ "$OS" == "windows" ] && EXT=".exe"
|
|
PLATFORM="$ARCH" && [ ! -z "$ARM_VER" ] && PLATFORM="armv$ARM_VER"
|
|
VARIANT_SUFFIX="" && [ "$BUILD_VARIANT" == "sqlite" ] && VARIANT_SUFFIX="-sqlite"
|
|
OUTPUT="dist/gitea-$BUILD_REF-$OS-$PLATFORM$VARIANT_SUFFIX$EXT"
|
|
|
|
if [ "$OS" == "darwin" ] && [ "$BUILD_VARIANT" == "sqlite" ]; then
|
|
build_darwin_sqlite_target "$ARCH" "$OUTPUT"
|
|
else
|
|
echo "📦 Building for $OS/$ARCH ${ARM_VER:+(v$ARM_VER) }with TAGS=\"$BUILD_TAGS\"..."
|
|
build_standard_target "$OS" "$ARCH" "$ARM_VER" "$OUTPUT" "$EXT"
|
|
fi
|
|
|
|
unset GOOS GOARCH GOARM CGO_ENABLED
|
|
done
|
|
|
|
echo "✨ Buid finished. Get file(s) from /dist"
|
|
go clean -cache # || true
|