266 lines
9.7 KiB
Bash
Executable File
266 lines
9.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
|
||
# Exit immediately if a command exits with a non-zero status.
|
||
set -e
|
||
# Treat unset variables as an error when substituting.
|
||
set -u
|
||
# Pipestatus
|
||
set -o pipefail
|
||
|
||
# --- Configuration ---
|
||
: "${NIX_CONFIG_DIR:=/etc/nix-darwin}" # Path to your Nix configuration directory
|
||
: "${GIT_REMOTE_NAME:=origin}"
|
||
GIT_BRANCH_NAME_CMD="git -C \"$NIX_CONFIG_DIR\" rev-parse --abbrev-ref HEAD"
|
||
: "${GIT_BRANCH_NAME:=$(eval "$GIT_BRANCH_NAME_CMD" 2>/dev/null || echo main)}"
|
||
|
||
# Ollama configuration
|
||
: "${OLLAMA_MODEL:=llama3.2:3b}" # Ollama model
|
||
: "${OLLAMA_HOST:=http://localhost:11434}" # Default Ollama API host
|
||
|
||
# Hardcoded Nix switch command
|
||
NIX_SWITCH_COMMAND="sudo darwin-rebuild switch"
|
||
# If your flake requires a specific attribute, modify it here, e.g.:
|
||
# NIX_SWITCH_COMMAND="sudo darwin-rebuild switch --flake .#yourDarwinConfigName"
|
||
# --- End Configuration ---
|
||
|
||
# Function to check if a command exists
|
||
command_exists() {
|
||
command -v "$1" >/dev/null 2>&1
|
||
}
|
||
|
||
# Check for dependencies
|
||
if ! command_exists ollama; then
|
||
echo "❌ Error: ollama CLI not found. Please install Ollama."
|
||
exit 1
|
||
fi
|
||
if ! command_exists jq; then
|
||
echo "❌ Error: jq not found. Please install jq."
|
||
exit 1
|
||
fi
|
||
if ! command_exists code; then
|
||
echo "❌ Error: 'code' (VSCode CLI) not found. Please ensure it's in your PATH."
|
||
echo " You might need to install it from within VSCode (View -> Command Palette -> 'Shell Command: Install code command in PATH')."
|
||
exit 1
|
||
fi
|
||
if ! command_exists sudo; then
|
||
echo "❌ Error: 'sudo' command not found. This script requires sudo for 'darwin-rebuild switch'."
|
||
exit 1
|
||
fi
|
||
if ! command_exists darwin-rebuild; then
|
||
echo "❌ Error: 'darwin-rebuild' command not found. Please ensure Nix-Darwin is installed correctly."
|
||
exit 1
|
||
fi
|
||
|
||
|
||
# --- VSCode Integration ---
|
||
echo "Nix config directory: $NIX_CONFIG_DIR"
|
||
echo "-----------------------------------------------------"
|
||
echo "💻 Opening VSCode to edit Nix configuration at $NIX_CONFIG_DIR..."
|
||
echo " The script will continue after you close VSCode."
|
||
|
||
if ! code --wait "$NIX_CONFIG_DIR"; then
|
||
echo "❌ Error: 'code --wait \"$NIX_CONFIG_DIR\"' failed."
|
||
echo " Please ensure VSCode is installed correctly and the 'code' command with '--wait' works."
|
||
exit 1
|
||
fi
|
||
echo "✅ VSCode closed. Proceeding with the script..."
|
||
echo "-----------------------------------------------------"
|
||
# --- End VSCode Integration ---
|
||
|
||
|
||
# Function to generate commit message using Ollama
|
||
generate_commit_message() {
|
||
local diff_content
|
||
diff_content=$(git -C "$NIX_CONFIG_DIR" diff --staged)
|
||
|
||
if [ -z "$diff_content" ]; then
|
||
echo "chore: No changes to commit"
|
||
return
|
||
fi
|
||
|
||
local max_diff_lines=150
|
||
local truncated_diff
|
||
truncated_diff=$(echo "$diff_content" | head -n "$max_diff_lines")
|
||
if [ "$(echo "$diff_content" | wc -l)" -gt "$max_diff_lines" ]; then
|
||
truncated_diff+=$'\n\n... (diff truncated) ...'
|
||
fi
|
||
|
||
local prompt
|
||
prompt=$(cat <<EOF
|
||
You are an expert at writing Conventional Commit messages.
|
||
Analyze the following git diff from a Nix configuration repository (nix-darwin).
|
||
The configuration directory is: $NIX_CONFIG_DIR
|
||
Generate a concise and informative Conventional Commit message.
|
||
|
||
The commit message must follow this format:
|
||
<type>(<scope>): <subject>
|
||
|
||
[optional body]
|
||
|
||
[optional footer]
|
||
|
||
Allowed types:
|
||
- feat: A new feature or package addition
|
||
- fix: A bug fix in the configuration
|
||
- docs: Documentation changes
|
||
- style: Code style changes (formatting, whitespace)
|
||
- refactor: Code changes that neither fix a bug nor add a feature
|
||
- perf: A code change that improves performance
|
||
- test: Adding missing tests or correcting existing tests
|
||
- build: Changes that affect the build system or external dependencies
|
||
- ci: Changes to CI configuration files and scripts
|
||
- chore: Other changes that don't modify source or test files
|
||
|
||
Consider these for Nix configurations:
|
||
- Adding a new package: 'feat' or 'feat(pkg)' or 'feat(darwin)'
|
||
- Updating flake inputs: 'build(deps): update flake inputs' or 'chore(deps): update flake inputs'
|
||
- Modifying system settings: 'refactor(system)' or 'fix(system)'
|
||
- Changing themes or appearances: 'style(theme)'
|
||
- General maintenance or minor tweaks: 'chore' or 'refactor'
|
||
|
||
Focus on a short, descriptive subject line (max 50-70 chars).
|
||
If no specific scope is obvious, you can omit it.
|
||
If the changes are minor, 'chore' or 'refactor' are good defaults.
|
||
|
||
Git Diff:
|
||
---
|
||
$truncated_diff
|
||
---
|
||
|
||
Generate ONLY the commit message. Do not include any other explanatory text.
|
||
EOF
|
||
)
|
||
|
||
echo "🧠 Generating commit message with Ollama ($OLLAMA_MODEL)..." >&2
|
||
local json_payload
|
||
json_payload=$(jq -n \
|
||
--arg model "$OLLAMA_MODEL" \
|
||
--arg prompt "$prompt" \
|
||
'{
|
||
model: $model,
|
||
prompt: $prompt,
|
||
stream: false,
|
||
options: {
|
||
temperature: 0.3,
|
||
num_predict: 150
|
||
}
|
||
}')
|
||
|
||
# Check if jq failed (e.g., if variables were not set properly for jq)
|
||
if [ -z "$json_payload" ]; then
|
||
echo "Error: Failed to create JSON payload with jq." >&2
|
||
return
|
||
fi
|
||
|
||
local ollama_response
|
||
ollama_response=$(curl -s --fail \
|
||
-X POST \
|
||
-H "Content-Type: application/json" \
|
||
--data "$json_payload" \
|
||
"$OLLAMA_HOST/api/generate")
|
||
|
||
if [ -z "$ollama_response" ]; then
|
||
echo "❌ Ollama request failed or returned empty. Using default commit message." >&2
|
||
echo "chore: Automated Nix config update $(date +'%Y-%m-%d %H:%M:%S')"
|
||
return
|
||
fi
|
||
|
||
local generated_message
|
||
generated_message=$(echo "$ollama_response" | jq -r '.response | sub("^\\s*"; "") | sub("\\s*$"; "")')
|
||
|
||
if [ -z "$generated_message" ] || [[ "$generated_message" == "null" ]]; then
|
||
echo "⚠️ Ollama did not return a valid message. Using default commit message." >&2
|
||
echo "chore: Automated Nix config update $(date +'%Y-%m-%d %H:%M:%S')"
|
||
else
|
||
if [[ "$generated_message" =~ ^[a-z]+(\([a-zA-Z0-9_-]+\))?!?: ]]; then
|
||
echo "$generated_message"
|
||
else
|
||
echo "⚠️ Ollama message doesn't look like a conventional commit. Prepending 'chore: '." >&2
|
||
echo "chore: $generated_message"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
|
||
echo "Current effective configuration:"
|
||
echo "Nix config directory: $NIX_CONFIG_DIR"
|
||
echo "Nix switch command to run: $NIX_SWITCH_COMMAND"
|
||
echo "Git remote: $GIT_REMOTE_NAME"
|
||
echo "Git branch: $GIT_BRANCH_NAME"
|
||
echo "Ollama model: $OLLAMA_MODEL"
|
||
echo "-----------------------------------------------------"
|
||
|
||
# 1. Navigate to the Nix config Git repository using pushd
|
||
# This is done *before* the switch command so darwin-rebuild finds flake.nix
|
||
echo "🔄 Changing directory to $NIX_CONFIG_DIR using pushd..."
|
||
if ! pushd "$NIX_CONFIG_DIR" > /dev/null; then
|
||
echo "❌ Failed to pushd into $NIX_CONFIG_DIR. Is the path correct and accessible?"
|
||
exit 1
|
||
fi
|
||
echo "✅ Successfully changed to $NIX_CONFIG_DIR (current directory: $PWD)."
|
||
echo "-----------------------------------------------------"
|
||
|
||
# Ensure we popd at the end, even if errors occur.
|
||
# A trap is more robust, but for now, manual popd before exits and at the end.
|
||
_cleanup() {
|
||
echo "🔄 Returning to original directory using popd..."
|
||
if ! popd > /dev/null; then
|
||
echo "⚠️ Failed to popd. Current directory ($PWD) might not be the original one."
|
||
fi
|
||
}
|
||
# trap _cleanup EXIT # Uncomment this for more robust cleanup on any exit
|
||
|
||
# 2. Run the Nix switch command
|
||
echo "🚀 Starting Nix switch: $NIX_SWITCH_COMMAND"
|
||
echo " This command will be run from: $PWD"
|
||
# The '|| echo ...' construct ensures the script continues even if the command fails,
|
||
# due to 'set -e'. A warning will be printed on failure.
|
||
# Using 'eval' to correctly handle the command string if it contains spaces and needs sudo.
|
||
eval "$NIX_SWITCH_COMMAND" || echo "⚠️ Nix switch command exited with a non-zero status. Continuing as requested..."
|
||
echo "ℹ️ Nix switch command execution finished. Proceeding..."
|
||
echo "-----------------------------------------------------"
|
||
|
||
# 3. Check for changes
|
||
echo "🔍 Checking for Git changes in current directory ($PWD)..."
|
||
if git diff --quiet && git diff --staged --quiet; then
|
||
echo "ℹ️ No changes detected in $NIX_CONFIG_DIR. Nothing to commit or push."
|
||
_cleanup # Call cleanup function
|
||
exit 0
|
||
fi
|
||
echo "✅ Changes detected."
|
||
echo "-----------------------------------------------------"
|
||
|
||
# 4. Add changes
|
||
echo "💾 Staging all changes in current directory ($PWD)..."
|
||
git add .
|
||
echo "-----------------------------------------------------"
|
||
|
||
# 5. Generate Commit Message
|
||
COMMIT_MESSAGE=$(generate_commit_message) # generate_commit_message uses git -C "$NIX_CONFIG_DIR"
|
||
echo "💬 Generated commit message:"
|
||
echo "$COMMIT_MESSAGE"
|
||
echo "-----------------------------------------------------"
|
||
|
||
# 6. Commit and Push
|
||
echo "✍️ Committing to local repository in current directory ($PWD)..."
|
||
if printf '%s\n' "$COMMIT_MESSAGE" | git commit -F - ; then
|
||
echo "✅ Commit successful."
|
||
else
|
||
echo "❌ Git commit failed. Please check the repository status and the generated message."
|
||
echo " Ensure you have commit permissions for $NIX_CONFIG_DIR."
|
||
_cleanup # Call cleanup function
|
||
exit 1
|
||
fi
|
||
|
||
echo "📡 Pushing to $GIT_REMOTE_NAME $GIT_BRANCH_NAME from current directory ($PWD)..."
|
||
if ! git push "$GIT_REMOTE_NAME" "$GIT_BRANCH_NAME"; then
|
||
echo "⚠️ Git push failed. The commit was made locally, but not pushed."
|
||
echo " Please check your remote connection, permissions, and push manually if needed."
|
||
else
|
||
echo "✅ Push successful."
|
||
fi
|
||
echo "-----------------------------------------------------"
|
||
|
||
_cleanup # Call cleanup function
|
||
echo "🎉 All done!"
|