Skip to content

Instantly share code, notes, and snippets.

@jamonholmgren
Last active March 27, 2026 23:57
Show Gist options
  • Select an option

  • Save jamonholmgren/02ba94f9b89aa6146883525dbc1cd17d to your computer and use it in GitHub Desktop.

Select an option

Save jamonholmgren/02ba94f9b89aa6146883525dbc1cd17d to your computer and use it in GitHub Desktop.
macOS script to upgrade Terrain3D from source
#!/usr/bin/env bash
set -euo pipefail
# Downloads the latest Terrain3D build artifacts from the main branch
# and installs them into addons/terrain_3d/.
# Can be run from the project root or any subfolder.
REPO="TokisanGames/Terrain3D"
ARTIFACT_NAME="Terrain3D"
show_help() {
cat <<'EOF'
Usage: ./Tools/upgrade_terrain3d [options]
Released as open source by Jammin Games. https://jammin.games
Gist: https://gist.github.com/jamonholmgren/02ba94f9b89aa6146883525dbc1cd17d
Downloads the latest Terrain3D addon from GitHub Actions CI (main branch)
and installs it into addons/terrain_3d/.
Can be run from the project root or any subfolder (looks for project.godot
in the current directory or one level up).
Tracks the current build via addons/terrain_3d/build_number.txt so
repeated runs are no-ops unless a newer build is available.
Options:
--force Re-download even if already on the latest build
--help Show this help message
Examples:
./Tools/upgrade_terrain3d # from project root
../Tools/upgrade_terrain3d # from a subfolder
./Tools/upgrade_terrain3d --force # always re-download
Requires: gh (GitHub CLI), jq
EOF
exit 0
}
# Parse flags
FORCE=false
for arg in "$@"; do
case "$arg" in
--force) FORCE=true ;;
--help|-h) show_help ;;
esac
done
# Preflight checks
if [[ "$(uname)" != "Darwin" ]]; then
echo "Error: This script only runs on macOS."
exit 1
fi
if ! command -v gh &>/dev/null; then
echo "Error: Requires the \`gh\` CLI (\`brew install gh\` or go to https://cli.github.com/ to download)."
exit 1
fi
if ! gh auth status &>/dev/null; then
echo "Error: Not logged in to GitHub. Run \`gh auth login\` first."
exit 1
fi
# Find project root by locating project.godot
if [[ -f "project.godot" ]]; then
PROJECT_DIR="$(pwd)"
elif [[ -f "../project.godot" ]]; then
PROJECT_DIR="$(cd .. && pwd)"
else
echo "Error: Could not find project.godot in current directory or parent directory."
echo "Run this script from the project root or a subfolder."
exit 1
fi
DEST="$PROJECT_DIR/addons/terrain_3d"
BUILD_NUMBER_FILE="$DEST/build_number.txt"
# Colors using tput
BOLD=$(tput bold)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
CYAN=$(tput setaf 6)
GRAY=$(tput setaf 7)
DKGRAY=$(tput setaf 8)
NC=$(tput sgr0)
printf '%s%s' "$CYAN" "$BOLD"
printf '\n═══════════════════════════════════════════════════'
printf '\n TERRAIN3D ADDON UPDATER '
printf '\n═══════════════════════════════════════════════════'
printf '%s\n' "$NC"
# Step 1: Find latest successful build
printf '%s▸ Finding latest successful build on main...%s\n' "$GRAY" "$NC"
RUN_JSON=$(gh run list --repo "$REPO" --branch main --status success --limit 1 \
--json databaseId,headSha,createdAt,displayTitle)
RUN_ID=$(echo "$RUN_JSON" | jq -r '.[0].databaseId')
RUN_SHA=$(echo "$RUN_JSON" | jq -r '.[0].headSha')
RUN_DATE=$(echo "$RUN_JSON" | jq -r '.[0].createdAt')
RUN_TITLE=$(echo "$RUN_JSON" | jq -r '.[0].displayTitle')
if [[ -z "$RUN_ID" || "$RUN_ID" == "null" ]]; then
printf '%s%s✗ No successful runs found on main branch.%s\n' "$RED" "$BOLD" "$NC"
exit 1
fi
printf '%s Run: %s%s%s\n' "$GRAY" "$YELLOW" "$RUN_ID" "$NC"
printf '%s Commit: %s%s%s\n' "$GRAY" "$YELLOW" "${RUN_SHA:0:10}" "$NC"
printf '%s Date: %s%s%s\n' "$GRAY" "$YELLOW" "$RUN_DATE" "$NC"
printf '%s Title: %s%s%s\n' "$GRAY" "$DKGRAY" "$RUN_TITLE" "$NC"
# Step 2: Check if we already have this build
if [[ -f "$BUILD_NUMBER_FILE" ]] && ! $FORCE; then
CURRENT_RUN_ID=$(head -1 "$BUILD_NUMBER_FILE" | grep -oE '[0-9]+' || echo "")
if [[ "$CURRENT_RUN_ID" == "$RUN_ID" ]]; then
printf '\n%s%s✓ Already up to date (run %s).%s\n\n' "$GREEN" "$BOLD" "$RUN_ID" "$NC"
exit 0
fi
printf '\n%s▸ Current build: %s → New build: %s%s\n' "$GRAY" "$CURRENT_RUN_ID" "$RUN_ID" "$NC"
else
if $FORCE; then
printf '\n%s▸ Force update requested.%s\n' "$YELLOW" "$NC"
else
printf '\n%s▸ No existing build_number.txt found — fresh install.%s\n' "$YELLOW" "$NC"
fi
fi
# Step 3: Download
printf '%s▸ Downloading artifacts...%s\n' "$GRAY" "$NC"
TMPDIR=$(mktemp -d)
cleanup() { rm -rf "$TMPDIR"; }
trap cleanup EXIT
gh run download "$RUN_ID" --repo "$REPO" --name "$ARTIFACT_NAME" --dir "$TMPDIR"
printf '%s %s✓ Download complete.%s\n' "$GREEN" "$BOLD" "$NC"
# Step 4: Copy
printf '%s▸ Copying addon to %s...%s\n' "$GRAY" "$DEST" "$NC"
cp -R "$TMPDIR/addons/terrain_3d/"* "$DEST/"
printf '%s %s✓ Files copied.%s\n' "$GREEN" "$BOLD" "$NC"
# Step 5: Remove macOS quarantine flags
if [[ "$(uname)" == "Darwin" ]]; then
printf '%s▸ Removing macOS quarantine flags...%s\n' "$GRAY" "$NC"
find "$DEST/bin" -name "libterrain.macos.*" \
-exec xattr -d com.apple.quarantine {} \; 2>/dev/null || true
printf '%s %s✓ Quarantine flags removed.%s\n' "$GREEN" "$BOLD" "$NC"
fi
# Step 6: Write build number file
cat > "$BUILD_NUMBER_FILE" <<EOF
$RUN_ID
commit: $RUN_SHA
date: $RUN_DATE
title: $RUN_TITLE
EOF
printf '%s▸ Wrote build_number.txt%s\n' "$GRAY" "$NC"
# Done
printf '\n%s%s✓ Terrain3D addon updated successfully!%s\n' "$GREEN" "$BOLD" "$NC"
printf '%s────────────────────────────────────────────────────%s\n\n' "$GRAY" "$NC"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment