dotfiles/scripts/edit-os.sh
2025-07-11 23:29:18 +03:00

266 lines
9.7 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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!"