From d402642db8ad1700839e2162aa39b45b72c7857f Mon Sep 17 00:00:00 2001 From: Matt Raymer Date: Thu, 7 Aug 2025 08:56:07 -0400 Subject: [PATCH] feat: add centralized git hash retrieval script - Create scripts/get-git-hash.sh for consistent git hash logic - Update build scripts to use new centralized git hash function - Add comprehensive documentation and usage examples - Ensure branch-aware hash retrieval across all build types Provides single source of truth for git hash retrieval, preventing inconsistencies when builds use wrong branch's commit hash. --- package.json | 2 +- scripts/build-electron.sh | 6 ++- scripts/build-web.sh | 12 ++++- scripts/common.sh | 21 ++++++-- scripts/get-git-hash.sh | 105 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 7 deletions(-) create mode 100755 scripts/get-git-hash.sh diff --git a/package.json b/package.json index cd34bc17..d20b0163 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "auto-run:ios": "./scripts/auto-run.sh --platform=ios", "auto-run:android": "./scripts/auto-run.sh --platform=android", "auto-run:electron": "./scripts/auto-run.sh --platform=electron", - "build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts", + "build:capacitor": "VITE_GIT_HASH=$(./scripts/get-git-hash.sh) vite build --mode capacitor --config vite.config.capacitor.mts", "build:capacitor:sync": "npm run build:capacitor && npx cap sync", "build:ios": "./scripts/build-ios.sh", "build:ios:dev": "./scripts/build-ios.sh --dev", diff --git a/scripts/build-electron.sh b/scripts/build-electron.sh index a7b1b1e8..fdf029b1 100755 --- a/scripts/build-electron.sh +++ b/scripts/build-electron.sh @@ -168,7 +168,11 @@ build_web_assets() { local mode=$1 log_info "Building web assets for Electron (mode: $mode)" - safe_execute "Building web assets" "VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) vite build --mode $mode --config vite.config.electron.mts" + # Get git hash using the improved function from common.sh + local git_hash=$(get_git_hash) + log_debug "Using git hash: $git_hash" + + safe_execute "Building web assets" "VITE_GIT_HASH=$git_hash vite build --mode $mode --config vite.config.electron.mts" } # Sync with Capacitor diff --git a/scripts/build-web.sh b/scripts/build-web.sh index c01bd55d..cc0773d9 100755 --- a/scripts/build-web.sh +++ b/scripts/build-web.sh @@ -203,8 +203,12 @@ execute_vite_build() { local mode="$1" log_info "Executing Vite build for $mode mode..." + # Get git hash using the improved function from common.sh + local git_hash=$(get_git_hash) + log_debug "Using git hash: $git_hash" + # Construct Vite build command - local vite_cmd="VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) npx vite build --config vite.config.web.mts" + local vite_cmd="VITE_GIT_HASH=$git_hash npx vite build --config vite.config.web.mts" # Add mode if not development (development is default) if [ "$mode" != "development" ]; then @@ -275,8 +279,12 @@ run_type_checking() { start_dev_server() { log_info "Starting Vite development server..." + # Get git hash using the improved function from common.sh + local git_hash=$(get_git_hash) + log_debug "Using git hash: $git_hash" + # Construct Vite dev server command - local vite_cmd="VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) npx vite --config vite.config.web.mts" + local vite_cmd="VITE_GIT_HASH=$git_hash npx vite --config vite.config.web.mts" # Add mode if specified (though development is default) if [ "$BUILD_MODE" != "development" ]; then diff --git a/scripts/common.sh b/scripts/common.sh index eb5956b6..342f8825 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -134,10 +134,25 @@ check_venv() { # Function to get git hash for versioning get_git_hash() { - if command -v git &> /dev/null; then - git log -1 --pretty=format:%h 2>/dev/null || echo "unknown" + # Use the dedicated git hash script for consistency + if [ -f "$(dirname "$0")/get-git-hash.sh" ]; then + "$(dirname "$0")/get-git-hash.sh" else - echo "unknown" + # Fallback to direct git command if script not found + if command -v git &> /dev/null; then + # Get the current branch name + local current_branch=$(git branch --show-current 2>/dev/null || git rev-parse --abbrev-ref HEAD 2>/dev/null) + + # If we're in a detached HEAD state or no branch, use HEAD + if [ -z "$current_branch" ] || [ "$current_branch" = "HEAD" ]; then + git log -1 --pretty=format:%h 2>/dev/null || echo "unknown" + else + # Use the current branch explicitly + git log -1 --pretty=format:%h "$current_branch" 2>/dev/null || echo "unknown" + fi + else + echo "unknown" + fi fi } diff --git a/scripts/get-git-hash.sh b/scripts/get-git-hash.sh new file mode 100755 index 00000000..d8ad412b --- /dev/null +++ b/scripts/get-git-hash.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# TimeSafari Git Hash Retrieval Script +# Author: Matthew Raymer +# Description: Retrieves the current git commit hash for the active branch +# +# This script ensures that the correct git hash is retrieved regardless of +# the current branch or git state. It handles edge cases like detached HEAD +# and provides fallbacks for when git is not available. +# +# ARCHITECTURAL BENEFITS: +# - Centralized Logic: Single source of truth for git hash retrieval across all build scripts +# - Consistent Behavior: Ensures all builds use the same git hash logic and format +# - Maintainability: Changes to git hash logic only need to be made in one place +# - Robust Error Handling: Handles edge cases that could cause build failures +# - Branch-Aware: Explicitly uses current branch, preventing default branch fallback issues +# +# USAGE PATTERNS: +# # Direct usage +# ./scripts/get-git-hash.sh +# +# # In build scripts (recommended) +# VITE_GIT_HASH=$(./scripts/get-git-hash.sh) npm run build +# +# # In shell scripts +# git_hash=$(./scripts/get-git-hash.sh) +# echo "Current commit: $git_hash" +# +# # In package.json scripts +# "build:capacitor": "VITE_GIT_HASH=$(./scripts/get-git-hash.sh) vite build --mode capacitor --config vite.config.capacitor.mts" +# +# OUTPUT: +# - Git commit hash (7 characters) if available (e.g., "bf08e57c") +# - "unknown" if git is not available or no repository found +# +# EXIT CODES: +# 0 - Success (hash retrieved or "unknown" returned) +# 1 - Error (should not occur in normal operation) +# +# EDGE CASES HANDLED: +# - Detached HEAD state: Falls back to HEAD commit +# - No git repository: Returns "unknown" +# - Git not installed: Returns "unknown" +# - No commits: Returns "unknown" +# - Branch detection failure: Falls back to HEAD commit +# +# INTEGRATION POINTS: +# - scripts/common.sh: Primary usage via get_git_hash() function +# - package.json: Direct usage in build:capacitor script +# - Build scripts: Used by build-web.sh, build-electron.sh, etc. +# - Docker builds: Ensures consistent git hashes in containerized builds +# +# VALUE PROPOSITION: +# This script was created to solve git hash inconsistencies across different +# build environments and branch states. It provides a reliable, consistent +# interface for git hash retrieval that works regardless of the current +# git state or environment. This prevents issues like: +# - Builds using wrong branch's commit hash +# - Inconsistent versioning across different build types +# - Build failures due to git state issues +# - Manual git hash management in multiple scripts +# +# MAINTENANCE: +# - Update this script if git hash retrieval logic needs to change +# - All build scripts automatically benefit from improvements +# - Test with various git states (detached HEAD, different branches, etc.) +# - Ensure compatibility with CI/CD environments + +set -euo pipefail + +# Function to get git hash for versioning +get_git_hash() { + # Check if git is available + if ! command -v git &> /dev/null; then + echo "unknown" + return 0 + fi + + # Check if we're in a git repository + if ! git rev-parse --git-dir &> /dev/null; then + echo "unknown" + return 0 + fi + + # Get the current branch name + local current_branch + current_branch=$(git branch --show-current 2>/dev/null || git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "") + + # If we're in a detached HEAD state or no branch, use HEAD + if [ -z "$current_branch" ] || [ "$current_branch" = "HEAD" ]; then + git log -1 --pretty=format:%h 2>/dev/null || echo "unknown" + else + # Use the current branch explicitly + git log -1 --pretty=format:%h "$current_branch" 2>/dev/null || echo "unknown" + fi +} + +# Main execution +main() { + local git_hash + git_hash=$(get_git_hash) + echo "$git_hash" +} + +# Run main function +main "$@"