mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-02 17:31:39 +00:00
291 lines
7.0 KiB
Bash
Executable File
291 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -eu
|
|
|
|
# clear
|
|
|
|
# Detect git state and determine appropriate comparison base
|
|
git_comparison_base() {
|
|
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
|
|
# Check for uncommitted changes (staged or unstaged)
|
|
if [[ -n "$(git status --porcelain)" ]]; then
|
|
# Development mode - compare against last commit
|
|
echo "HEAD"
|
|
return
|
|
fi
|
|
|
|
# Check if we're on master/main branch
|
|
if [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
|
# On master - compare against last tag
|
|
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
|
if [[ -n "$last_tag" ]]; then
|
|
echo "$last_tag"
|
|
else
|
|
# No tags exist, compare against first commit
|
|
echo "$(git rev-list --max-parents=0 HEAD)"
|
|
fi
|
|
return
|
|
fi
|
|
|
|
# On feature branch with clean state - compare against master
|
|
echo "master"
|
|
}
|
|
|
|
# Get current git context for display
|
|
git_context() {
|
|
local base=$(git_comparison_base)
|
|
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
local has_changes=$(git status --porcelain | wc -l)
|
|
|
|
if [[ "$has_changes" -gt 0 ]]; then
|
|
echo "Development mode: comparing against HEAD (last commit)"
|
|
elif [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
|
echo "Master branch: comparing against $base"
|
|
else
|
|
echo "Feature branch: comparing against master"
|
|
fi
|
|
}
|
|
|
|
changed_files() {
|
|
local base=$(git_comparison_base)
|
|
|
|
if [[ "$base" == "HEAD" ]]; then
|
|
# In development mode - show uncommitted changes
|
|
git diff --name-only HEAD
|
|
git diff --cached --name-only
|
|
git ls-files --others --exclude-standard
|
|
else
|
|
# Compare against determined base
|
|
git diff --name-only "$base" "$(git rev-parse HEAD)"
|
|
fi | sort -u
|
|
}
|
|
|
|
changed_scopes() {
|
|
local changed_files=$(changed_files)
|
|
local context=$(git_context)
|
|
|
|
echo "🔍 Changed Files by Scope"
|
|
echo "========================="
|
|
echo "📍 $context"
|
|
echo ""
|
|
|
|
# Process each scope
|
|
yq eval '.[] | @json' .github/scopes.yml | while IFS= read -r scope_obj; do
|
|
local scope_name=$(echo "$scope_obj" | jq -r '.name')
|
|
local patterns=$(echo "$scope_obj" | jq -r '.include[]' | sed 's|^\./||; s|/\*\*$||')
|
|
local matched_files=""
|
|
|
|
# Find matching files for all patterns of this scope
|
|
for pattern in $patterns; do
|
|
while IFS= read -r file; do
|
|
[[ -n "$file" ]] && [[ "$file" == "$pattern"* ]] && matched_files+="$file\n"
|
|
done <<<"$changed_files"
|
|
done
|
|
|
|
# Display if there are matches
|
|
if [[ -n "$matched_files" ]]; then
|
|
local unique_count=$(echo -e "$matched_files" | sort -u | grep -c '^' || echo 0)
|
|
echo ""
|
|
echo "📦 $scope_name [$unique_count files]"
|
|
|
|
# Group files by directory
|
|
echo -e "$matched_files" | sort -u | while IFS= read -r file; do
|
|
[[ -n "$file" ]] || continue
|
|
|
|
# Indent based on directory depth
|
|
local depth=$(echo "$file" | tr -cd '/' | wc -c)
|
|
local indent=""
|
|
for ((i = 0; i < depth; i++)); do
|
|
indent=" $indent"
|
|
done
|
|
|
|
# Show just the filename with smart tree characters
|
|
local basename=$(basename "$file")
|
|
local dirname=$(dirname "$file")
|
|
|
|
if [[ "$dirname" != "." ]]; then
|
|
echo " 📁 $dirname/"
|
|
echo " └── $basename"
|
|
else
|
|
echo " └── $file"
|
|
fi
|
|
done | sort -u # Remove duplicate directory listings
|
|
fi
|
|
done
|
|
}
|
|
|
|
success() {
|
|
gum log --structured "$1" --prefix "✅" --prefix.foreground "#00ff00"
|
|
}
|
|
|
|
error() {
|
|
gum log --structured "$1" --prefix "❌" --prefix.foreground "#ff0000"
|
|
}
|
|
|
|
info() {
|
|
gum log --structured --prefix "📍" --prefix.foreground "#00ffff" "$1"
|
|
}
|
|
|
|
header() {
|
|
local title="$1"
|
|
gum style --border-foreground 240 --border double --align center --padding "0 1" "$title"
|
|
echo "" | gum format
|
|
}
|
|
|
|
separator() {
|
|
echo "---" | gum format
|
|
}
|
|
|
|
list_item() {
|
|
local item="$1"
|
|
echo "- $item" | gum format
|
|
}
|
|
|
|
devbox_run() {
|
|
local command="$1"
|
|
local action=$(echo "$command" | cut -f1 -d: | tr '[:upper:]' '[:lower:]')
|
|
local scope=$(echo "$command" | cut -f2 -d: | tr '[:upper:]' '[:lower:]')
|
|
local title="Executing devbox run $action:$scope..."
|
|
gum spin --show-error --spinner meter --title "$title" -- devbox run "$command"
|
|
success "$scope finished $action"
|
|
}
|
|
|
|
install() {
|
|
header "Install"
|
|
gum spin --show-error --spinner pulse --title "Installing Go..." -- go mod download
|
|
info "go(1.24.7)"
|
|
separator
|
|
}
|
|
|
|
build_all() {
|
|
header "Build"
|
|
devbox_run "build:core"
|
|
separator
|
|
}
|
|
|
|
test_all() {
|
|
header "Test"
|
|
devbox_run "test:core"
|
|
separator
|
|
}
|
|
|
|
release_all() {
|
|
header "Release"
|
|
devbox_run "release:core"
|
|
separator
|
|
}
|
|
|
|
snapshot_all() {
|
|
header "Snapshot"
|
|
devbox_run "snapshot:core"
|
|
separator
|
|
}
|
|
|
|
test_scopes() {
|
|
for scope in $(affected_scopes); do
|
|
# Check if the test script exists in devbox.json
|
|
if grep -q "\"test:$scope\":" devbox.json 2>/dev/null; then
|
|
echo "Testing scope: $scope"
|
|
devbox run "test:$scope"
|
|
else
|
|
echo "Skipping test for scope: $scope (no test script defined)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
build_scopes() {
|
|
for scope in $(affected_scopes); do
|
|
# Check if the build script exists in devbox.json
|
|
if grep -q "\"build:$scope\":" devbox.json 2>/dev/null; then
|
|
echo "Building scope: $scope"
|
|
devbox run "build:$scope"
|
|
else
|
|
echo "Skipping build for scope: $scope (no build script defined)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
release_scopes() {
|
|
for scope in $(affected_scopes); do
|
|
# Check if the release script exists in devbox.json
|
|
if grep -q "\"release:$scope\":" devbox.json 2>/dev/null; then
|
|
echo "Releasing scope: $scope"
|
|
devbox run "release:$scope"
|
|
else
|
|
echo "Skipping release for scope: $scope (no release script defined)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
snapshot_scopes() {
|
|
for scope in $(affected_scopes); do
|
|
# Check if the snapshot script exists in devbox.json
|
|
if grep -q "\"snapshot:$scope\":" devbox.json 2>/dev/null; then
|
|
echo "Creating snapshot for scope: $scope"
|
|
devbox run "snapshot:$scope"
|
|
else
|
|
echo "Skipping snapshot for scope: $scope (no snapshot script defined)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
affected_scopes() {
|
|
local verbose="${1:-false}"
|
|
local changed_files=$(changed_files)
|
|
|
|
if [[ "$verbose" == "true" ]] || [[ "$verbose" == "-v" ]]; then
|
|
echo "📍 $(git_context)" >&2
|
|
echo "" >&2
|
|
fi
|
|
|
|
yq eval -o=json '.[]' .github/scopes.yml | jq -r --arg files "$changed_files" '
|
|
select(.include[] as $pattern |
|
|
$files | split("\n")[] |
|
|
startswith($pattern | sub("^\\./"; "") | sub("/\\*\\*$"; ""))
|
|
) |
|
|
.name
|
|
' | sort -u
|
|
}
|
|
|
|
main() {
|
|
cmd="$1"
|
|
shift || true # Allow shifting even if no more args
|
|
|
|
case "$cmd" in
|
|
"build-all")
|
|
build_all
|
|
;;
|
|
"test-all")
|
|
test_all
|
|
;;
|
|
"release-all")
|
|
release_all
|
|
;;
|
|
"snapshot-all")
|
|
snapshot_all
|
|
;;
|
|
"build-scopes")
|
|
build_scopes
|
|
;;
|
|
"test-scopes")
|
|
test_scopes
|
|
;;
|
|
"release-scopes")
|
|
release_scopes
|
|
;;
|
|
"snapshot-scopes")
|
|
snapshot_scopes
|
|
;;
|
|
"install")
|
|
install
|
|
;;
|
|
*)
|
|
echo "Unknown command: $cmd"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|