From 8a6249c930e4e99e33d13308996add0d0c19dfbf Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 11 Apr 2024 22:51:16 +0000 Subject: [PATCH] adding script --- scripts/README.md | 16 ++++ scripts/dccd.sh | 190 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 scripts/README.md create mode 100755 scripts/dccd.sh diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..785a957 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,16 @@ +Make executable: +``` +sudo chmod +x dccd.sh +``` +Example: +``` +./dccd.sh -b main -d /home/mafyuh/Auto-Homelab -p -f 'arrs' +``` +Crontab: +``` +*/30 * * * * /home/mafyuh/dccd.sh -b main -d /home/mafyuh/Auto-Homelab -l /tmp/dccd.txt -p -f 'arrs' +``` +View Logs: +``` +cat /tmp/dccd.txt +``` diff --git a/scripts/dccd.sh b/scripts/dccd.sh new file mode 100755 index 0000000..b559002 --- /dev/null +++ b/scripts/dccd.sh @@ -0,0 +1,190 @@ +#!/bin/bash + +######################################## +# Default configuration values +######################################## +BASE_DIR="" # Initialize empty variable +LOG_FILE="/tmp/dccd.log" # Default log file name +PRUNE=0 # Default prune setting +REMOTE_BRANCH="main" # Default remote branch name + +######################################## +# Functions +######################################## +log_message() { + local message="$1" + echo "$(date +'%Y-%m-%d %H:%M:%S') - $message" | tee -a "$LOG_FILE" +} + +update_compose_files() { + local dir="$1" + local folder_pattern="$2" # Added parameter for folder pattern + + cd "$dir" || { log_message "ERROR: Directory doesn't exist, exiting..."; exit 127; } + + # Make sure we're in a git repo + if [ ! -d .git ]; then + log_message "ERROR: Directory is not a git repository, exiting..." + exit 1 + else + log_message "INFO: Git repository found!" + fi + + # Check if there are any changes in the Git repository + if ! git fetch origin; then + log_message "ERROR: Unable to fetch changes from the remote repository (the server may be offline or unreachable)" + exit 1 + fi + + local_hash=$(git rev-parse HEAD) + remote_hash=$(git rev-parse "origin/$REMOTE_BRANCH") + log_message "INFO: Local hash is $local_hash" + log_message "INFO: Remote hash is $remote_hash" + + # Check for uncommitted local changes + uncommitted_changes=$(git status --porcelain) + if [ -n "$uncommitted_changes" ]; then + log_message "ERROR: Uncommitted changes detected in $dir, exiting..." + exit 1 + fi + + # Check if the local hash matches the remote hash + if [ "$local_hash" != "$remote_hash" ]; then + log_message "STATE: Hashes don't match, updating..." + + # Pull any changes in the Git repository + if ! git pull --quiet origin "$REMOTE_BRANCH"; then + log_message "ERROR: Unable to pull changes from the remote repository (the server may be offline or unreachable)" + exit 1 + fi + + # Loop through directories matching the specified pattern + find "$dir" -type d -name "$folder_pattern" | while IFS= read -r folder; do + log_message "INFO: Found folder matching pattern: $folder" + + # If EXCLUDE is set and the directory matches the exclude pattern, skip + if [ -n "$EXCLUDE" ] && [[ "$folder" == *"$EXCLUDE"* ]]; then + log_message "INFO: Excluding directory $folder" + continue + fi + + # Go into the directory + cd "$folder" || { log_message "ERROR: Failed to enter directory $folder"; continue; } + + # Redeploy compose file in this directory + log_message "STATE: Redeploying compose file in directory: $folder" + docker compose up -d --quiet-pull + + # Go back to the original directory + cd "$dir" || { log_message "ERROR: Failed to return to directory $dir"; exit 1; } + done + else + log_message "STATE: Hashes match, so nothing to do" + fi + + # Check if PRUNE is provided + if [ $PRUNE -eq 1 ]; then + log_message "STATE: Pruning images" + docker image prune --all --force + fi + + log_message "STATE: Done!" +} + +usage() { + printf " + Usage: $0 [OPTIONS] + + Options: + -b Specify the remote branch to track (default: main) + -d Specify the base directory of the git repository (required) + -h Show this help message + -l Specify the path to the log file (default: /tmp/dccd.log) + -p Specify if you want to prune docker images (default: don't prune) + -x Exclude directories matching the specified pattern (relative to the base directory) + -f Specify the pattern for folder names to match + + Example: /path/to/dccd.sh -b master -d /path/to/git_repo -l /tmp/dccd.txt -p -f 'arrs' + +" + exit 1 +} + +######################################## +# Options +######################################## + +while getopts ":b:d:hl:px:f:" opt; do + case "$opt" in + b) + REMOTE_BRANCH="$OPTARG" + ;; + d) + BASE_DIR="$OPTARG" + ;; + h) + usage + ;; + l) + LOG_FILE="$OPTARG" + ;; + p) + PRUNE=1 + ;; + x) + EXCLUDE="$OPTARG" + ;; + f) + FOLDER_PATTERN="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + usage + ;; + esac +done + +######################################## +# Script starts here +######################################## + +touch "$LOG_FILE" +{ + echo "########################################" + echo "# Starting!" + echo "########################################" +} >> "$LOG_FILE" + +# Check if BASE_DIR is provided +if [ -z "$BASE_DIR" ]; then + log_message "ERROR: The base directory (-d) is required, exiting..." + usage +else + log_message "INFO: Base directory is set to $BASE_DIR" +fi + +# Check if REMOTE_BRANCH is provided +if [ -z "$REMOTE_BRANCH" ]; then + log_message "INFO: The remote branch isn't specified, so using $REMOTE_BRANCH" +else + log_message "INFO: The remote branch is set to $REMOTE_BRANCH" +fi + +# Check if EXCLUDE is provided +if [ -n "$EXCLUDE" ]; then + log_message "INFO: Will be excluding pattern $EXCLUDE" +fi + +# Check if FOLDER_PATTERN is provided +if [ -z "$FOLDER_PATTERN" ]; then + log_message "ERROR: The folder pattern (-f) is required, exiting..." + usage +else + log_message "INFO: Folder pattern is set to $FOLDER_PATTERN" +fi + +update_compose_files "$BASE_DIR" "$FOLDER_PATTERN"