feat: add Python linting support with pylint and black
This commit is contained in:
@ -9,84 +9,113 @@ import argparse
|
||||
sys.path.append(os.path.join(os.path.expanduser("~/.dotfiles"), "bin"))
|
||||
from helpers.functions import printfe, run_command
|
||||
|
||||
|
||||
def help_message():
|
||||
"""Print help message and exit"""
|
||||
printfe("green", "Usage: upgrade.py [options]")
|
||||
printfe("green", "Options:")
|
||||
printfe("green", " --ha, -H Upgrade Home Manager packages.")
|
||||
printfe("green", " --ansible, -A Upgrade Ansible packages.")
|
||||
printfe("green", " --ansible-verbose Upgrade Ansible packages with verbose output. (-vvv)")
|
||||
printfe("green", " --full-speed, -F Upgrade packages and use all available cores for compilation. (Default: 8 cores)")
|
||||
printfe(
|
||||
"green",
|
||||
" --ansible-verbose Upgrade Ansible packages with verbose output. (-vvv)",
|
||||
)
|
||||
printfe(
|
||||
"green",
|
||||
" --full-speed, -F Upgrade packages and use all available cores for compilation. (Default: 8 cores)",
|
||||
)
|
||||
printfe("green", " --help, -h Display this help message.")
|
||||
return 0
|
||||
|
||||
|
||||
def check_git_repository():
|
||||
"""Check for changes in the dotfiles git repository and prompt user to pull if needed"""
|
||||
dotfiles_path = os.environ.get("DOTFILES_PATH", os.path.expanduser("~/.dotfiles"))
|
||||
|
||||
|
||||
printfe("cyan", "Checking for updates in dotfiles repository...")
|
||||
|
||||
|
||||
# Change to dotfiles directory
|
||||
current_dir = os.getcwd()
|
||||
os.chdir(dotfiles_path)
|
||||
|
||||
|
||||
# Check if this is a git repository
|
||||
status, _ = run_command(["git", "rev-parse", "--is-inside-work-tree"], shell=False)
|
||||
if not status:
|
||||
printfe("red", "The dotfiles directory is not a git repository.")
|
||||
os.chdir(current_dir)
|
||||
return False
|
||||
|
||||
|
||||
# Get the current branch name
|
||||
status, current_branch = run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"], shell=False)
|
||||
status, current_branch = run_command(
|
||||
["git", "rev-parse", "--abbrev-ref", "HEAD"], shell=False
|
||||
)
|
||||
if not status:
|
||||
printfe("red", "Failed to determine current branch.")
|
||||
os.chdir(current_dir)
|
||||
return False
|
||||
|
||||
|
||||
current_branch = current_branch.strip()
|
||||
|
||||
|
||||
# Fetch the latest changes
|
||||
status, output = run_command(["git", "fetch"], shell=False)
|
||||
if not status:
|
||||
printfe("red", f"Failed to fetch changes from git repository: {output}")
|
||||
os.chdir(current_dir)
|
||||
return False
|
||||
|
||||
|
||||
# Check if remote branch exists
|
||||
status, output = run_command(["git", "ls-remote", "--heads", "origin", current_branch], shell=False)
|
||||
status, output = run_command(
|
||||
["git", "ls-remote", "--heads", "origin", current_branch], shell=False
|
||||
)
|
||||
if not status or not output.strip():
|
||||
printfe("yellow", f"Remote branch 'origin/{current_branch}' not found. Using local branch only.")
|
||||
printfe(
|
||||
"yellow",
|
||||
f"Remote branch 'origin/{current_branch}' not found. Using local branch only.",
|
||||
)
|
||||
os.chdir(current_dir)
|
||||
return True
|
||||
|
||||
|
||||
# Check if we're behind the remote
|
||||
status, output = run_command(["git", "rev-list", f"HEAD..origin/{current_branch}", "--count"], shell=False)
|
||||
status, output = run_command(
|
||||
["git", "rev-list", f"HEAD..origin/{current_branch}", "--count"], shell=False
|
||||
)
|
||||
if not status:
|
||||
printfe("red", f"Failed to check for repository updates: {output}")
|
||||
os.chdir(current_dir)
|
||||
return False
|
||||
|
||||
|
||||
behind_count = output.strip()
|
||||
if behind_count == "0":
|
||||
printfe("green", f"Dotfiles repository is up to date on branch '{current_branch}'.")
|
||||
printfe(
|
||||
"green", f"Dotfiles repository is up to date on branch '{current_branch}'."
|
||||
)
|
||||
os.chdir(current_dir)
|
||||
return True
|
||||
|
||||
|
||||
# Show what changes are available
|
||||
status, output = run_command(["git", "log", f"HEAD..origin/{current_branch}", "--oneline"], shell=False)
|
||||
status, output = run_command(
|
||||
["git", "log", f"HEAD..origin/{current_branch}", "--oneline"], shell=False
|
||||
)
|
||||
if status:
|
||||
printfe("yellow", f"Your dotfiles repository is {behind_count} commit(s) behind on branch '{current_branch}'. Changes:")
|
||||
printfe(
|
||||
"yellow",
|
||||
f"Your dotfiles repository is {behind_count} commit(s) behind on branch '{current_branch}'. Changes:",
|
||||
)
|
||||
for line in output.strip().splitlines():
|
||||
printfe("yellow", f" • {line}")
|
||||
else:
|
||||
printfe("yellow", f"Your dotfiles repository is {behind_count} commit(s) behind on branch '{current_branch}'.")
|
||||
|
||||
printfe(
|
||||
"yellow",
|
||||
f"Your dotfiles repository is {behind_count} commit(s) behind on branch '{current_branch}'.",
|
||||
)
|
||||
|
||||
# Ask user if they want to pull changes
|
||||
response = input("Do you want to pull these changes? (yes/no): ").strip().lower()
|
||||
|
||||
|
||||
if response in ["yes", "y"]:
|
||||
status, output = run_command(["git", "pull", "origin", current_branch], shell=False)
|
||||
status, output = run_command(
|
||||
["git", "pull", "origin", current_branch], shell=False
|
||||
)
|
||||
if not status:
|
||||
printfe("red", f"Failed to pull changes: {output}")
|
||||
os.chdir(current_dir)
|
||||
@ -94,19 +123,20 @@ def check_git_repository():
|
||||
printfe("green", "Successfully updated dotfiles repository.")
|
||||
else:
|
||||
printfe("yellow", "Skipping repository update.")
|
||||
|
||||
|
||||
os.chdir(current_dir)
|
||||
return True
|
||||
|
||||
|
||||
def ensure_ansible_collections():
|
||||
"""Ensure required Ansible collections are installed"""
|
||||
# List of required collections that can be expanded in the future
|
||||
required_collections = [
|
||||
"community.general",
|
||||
]
|
||||
|
||||
|
||||
printfe("cyan", "Checking for required Ansible collections...")
|
||||
|
||||
|
||||
# Get list of installed collections using ansible-galaxy
|
||||
status, output = run_command(["ansible-galaxy", "collection", "list"], shell=False)
|
||||
if not status:
|
||||
@ -116,27 +146,27 @@ def ensure_ansible_collections():
|
||||
else:
|
||||
# Parse output to get installed collections
|
||||
installed_collections = []
|
||||
|
||||
|
||||
# Split output into lines and process
|
||||
lines = output.splitlines()
|
||||
collection_section = False
|
||||
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
|
||||
|
||||
# Skip empty lines
|
||||
if not line:
|
||||
continue
|
||||
|
||||
|
||||
# Check if we've reached the collection listing section
|
||||
if line.startswith("Collection"):
|
||||
collection_section = True
|
||||
continue
|
||||
|
||||
|
||||
# Skip the separator line after the header
|
||||
if collection_section and line.startswith("--"):
|
||||
continue
|
||||
|
||||
|
||||
# Process collection entries
|
||||
if collection_section and " " in line:
|
||||
# Format is typically: "community.general 10.4.0"
|
||||
@ -144,80 +174,113 @@ def ensure_ansible_collections():
|
||||
if len(parts) >= 1:
|
||||
collection_name = parts[0]
|
||||
installed_collections.append(collection_name)
|
||||
|
||||
|
||||
# Check which required collections are missing
|
||||
missing_collections = []
|
||||
for collection in required_collections:
|
||||
if collection not in installed_collections:
|
||||
missing_collections.append(collection)
|
||||
|
||||
|
||||
# Install missing collections
|
||||
if missing_collections:
|
||||
for collection in missing_collections:
|
||||
printfe("yellow", f"Installing {collection} collection...")
|
||||
status, install_output = run_command(["ansible-galaxy", "collection", "install", collection], shell=False)
|
||||
status, install_output = run_command(
|
||||
["ansible-galaxy", "collection", "install", collection], shell=False
|
||||
)
|
||||
if not status:
|
||||
printfe("yellow", f"Warning: Failed to install {collection} collection: {install_output}")
|
||||
printfe("yellow", f"Continuing anyway, but playbook might fail if it requires {collection}")
|
||||
printfe(
|
||||
"yellow",
|
||||
f"Warning: Failed to install {collection} collection: {install_output}",
|
||||
)
|
||||
printfe(
|
||||
"yellow",
|
||||
f"Continuing anyway, but playbook might fail if it requires {collection}",
|
||||
)
|
||||
else:
|
||||
printfe("green", f"Successfully installed {collection} collection")
|
||||
else:
|
||||
printfe("green", "All required collections are already installed.")
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
# Parse arguments
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument("--ha", "-H", action="store_true", help="Upgrade Home Manager packages")
|
||||
parser.add_argument("--ansible", "-A", action="store_true", help="Upgrade Ansible packages")
|
||||
parser.add_argument("--ansible-verbose", action="store_true", help="Upgrade Ansible packages with verbose output")
|
||||
parser.add_argument("--full-speed", "-F", action="store_true", help="Use all available cores")
|
||||
parser.add_argument("--help", "-h", action="store_true", help="Display help message")
|
||||
|
||||
parser.add_argument(
|
||||
"--ha", "-H", action="store_true", help="Upgrade Home Manager packages"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ansible", "-A", action="store_true", help="Upgrade Ansible packages"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ansible-verbose",
|
||||
action="store_true",
|
||||
help="Upgrade Ansible packages with verbose output",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--full-speed", "-F", action="store_true", help="Use all available cores"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--help", "-h", action="store_true", help="Display help message"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
if args.help:
|
||||
return help_message()
|
||||
|
||||
|
||||
# If no specific option provided, run all
|
||||
if not args.ha and not args.ansible and not args.ansible_verbose:
|
||||
args.ha = True
|
||||
args.ansible = True
|
||||
|
||||
|
||||
# If ansible_verbose is set, also set ansible
|
||||
if args.ansible_verbose:
|
||||
args.ansible = True
|
||||
|
||||
|
||||
# Always check git repository first
|
||||
if not check_git_repository():
|
||||
printfe("red", "Failed to check or update dotfiles repository.")
|
||||
return 1
|
||||
|
||||
|
||||
# Set cores and jobs based on full-speed flag
|
||||
if args.full_speed:
|
||||
import multiprocessing
|
||||
|
||||
cores = jobs = multiprocessing.cpu_count()
|
||||
else:
|
||||
cores = 8
|
||||
jobs = 1
|
||||
|
||||
|
||||
printfe("cyan", f"Limiting to {cores} cores with {jobs} jobs.")
|
||||
|
||||
|
||||
# Home Manager update
|
||||
if args.ha:
|
||||
dotfiles_path = os.environ.get("DOTFILES_PATH", os.path.expanduser("~/.dotfiles"))
|
||||
dotfiles_path = os.environ.get(
|
||||
"DOTFILES_PATH", os.path.expanduser("~/.dotfiles")
|
||||
)
|
||||
hostname = os.uname().nodename
|
||||
|
||||
|
||||
printfe("cyan", "Updating Home Manager flake...")
|
||||
os.chdir(f"{dotfiles_path}/config/home-manager")
|
||||
status, output = run_command(["nix", "--extra-experimental-features", "nix-command",
|
||||
"--extra-experimental-features", "flakes", "flake", "update"],
|
||||
shell=False)
|
||||
status, output = run_command(
|
||||
[
|
||||
"nix",
|
||||
"--extra-experimental-features",
|
||||
"nix-command",
|
||||
"--extra-experimental-features",
|
||||
"flakes",
|
||||
"flake",
|
||||
"update",
|
||||
],
|
||||
shell=False,
|
||||
)
|
||||
if not status:
|
||||
printfe("red", f"Failed to update Home Manager flake: {output}")
|
||||
return 1
|
||||
|
||||
|
||||
# Check if home-manager is installed
|
||||
status, _ = run_command(["which", "home-manager"], shell=False)
|
||||
if status:
|
||||
@ -225,15 +288,29 @@ def main():
|
||||
backup_file = os.path.expanduser("~/.config/mimeapps.list.backup")
|
||||
if os.path.exists(backup_file):
|
||||
os.remove(backup_file)
|
||||
|
||||
|
||||
printfe("cyan", "Upgrading Home Manager packages...")
|
||||
env = os.environ.copy()
|
||||
env["NIXPKGS_ALLOW_UNFREE"] = "1"
|
||||
|
||||
cmd = ["home-manager", "--extra-experimental-features", "nix-command",
|
||||
"--extra-experimental-features", "flakes", "switch", "-b", "backup",
|
||||
f"--flake", f".#{hostname}", "--impure", "--cores", str(cores), "-j", str(jobs)]
|
||||
|
||||
|
||||
cmd = [
|
||||
"home-manager",
|
||||
"--extra-experimental-features",
|
||||
"nix-command",
|
||||
"--extra-experimental-features",
|
||||
"flakes",
|
||||
"switch",
|
||||
"-b",
|
||||
"backup",
|
||||
f"--flake",
|
||||
f".#{hostname}",
|
||||
"--impure",
|
||||
"--cores",
|
||||
str(cores),
|
||||
"-j",
|
||||
str(jobs),
|
||||
]
|
||||
|
||||
result = subprocess.run(cmd, env=env)
|
||||
if result.returncode != 0:
|
||||
printfe("red", "Failed to upgrade Home Manager packages.")
|
||||
@ -241,39 +318,48 @@ def main():
|
||||
else:
|
||||
printfe("red", "Home Manager is not installed.")
|
||||
return 1
|
||||
|
||||
|
||||
# Ansible update
|
||||
if args.ansible:
|
||||
dotfiles_path = os.environ.get("DOTFILES_PATH", os.path.expanduser("~/.dotfiles"))
|
||||
dotfiles_path = os.environ.get(
|
||||
"DOTFILES_PATH", os.path.expanduser("~/.dotfiles")
|
||||
)
|
||||
hostname = os.uname().nodename
|
||||
username = os.environ.get("USER", os.environ.get("USERNAME", "user"))
|
||||
|
||||
|
||||
# Ensure required collections are installed
|
||||
if not ensure_ansible_collections():
|
||||
printfe("red", "Failed to ensure required Ansible collections are installed")
|
||||
printfe(
|
||||
"red", "Failed to ensure required Ansible collections are installed"
|
||||
)
|
||||
return 1
|
||||
|
||||
|
||||
printfe("cyan", "Running Ansible playbook...")
|
||||
ansible_cmd = [
|
||||
"/usr/bin/env",
|
||||
"ansible-playbook",
|
||||
"-i", f"{dotfiles_path}/config/ansible/inventory.ini",
|
||||
"-i",
|
||||
f"{dotfiles_path}/config/ansible/inventory.ini",
|
||||
f"{dotfiles_path}/config/ansible/playbook.yml",
|
||||
"--extra-vars", f"hostname={hostname}",
|
||||
"--extra-vars", f"ansible_user={username}",
|
||||
"--limit", hostname,
|
||||
"--ask-become-pass"
|
||||
"--extra-vars",
|
||||
f"hostname={hostname}",
|
||||
"--extra-vars",
|
||||
f"ansible_user={username}",
|
||||
"--limit",
|
||||
hostname,
|
||||
"--ask-become-pass",
|
||||
]
|
||||
|
||||
|
||||
if args.ansible_verbose:
|
||||
ansible_cmd.append("-vvv")
|
||||
|
||||
|
||||
result = subprocess.run(ansible_cmd)
|
||||
if result.returncode != 0:
|
||||
printfe("red", "Failed to upgrade Ansible packages.")
|
||||
return 1
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
Reference in New Issue
Block a user