diff --git a/Containers/Docker/Docker Compose/Custom Containers/Git Repo Updater.md b/Containers/Docker/Docker Compose/Custom Containers/Git Repo Updater.md index 3a573a5..ddde5fe 100644 --- a/Containers/Docker/Docker Compose/Custom Containers/Git Repo Updater.md +++ b/Containers/Docker/Docker Compose/Custom Containers/Git Repo Updater.md @@ -1,99 +1,114 @@ **Purpose**: Docker container running Alpine Linux that automates and improves upon much of the script mentioned in the [Git Repo Updater](https://docs.bunny-lab.io/Scripts/Bash/Git%20Repo%20Updater) document. It offers the additional benefits of checking for updates every 5 seconds instead of every 60 seconds. It also accepts environment variables to provide credentials and notification settings, and can have an infinite number of monitored repositories. ### Deployment -You can find the current up-to-date Gitea repository that includes the `docker-compose.yml` and `.env` files that you need to deploy everything [here](https://git.cyberstrawberry.net/container-registry/-/packages/container/git-repo-updater/latest) +You can find the current up-to-date Gitea repository that includes the `docker-compose.yml` and `.env` files that you need to deploy everything [here](https://git.bunny-lab.io/container-registry/-/packages/container/git-repo-updater/latest) ```jsx title="docker-compose.yml" version: '3.3' services: git-repo-updater: privileged: true container_name: git-repo-updater - environment: - - REPO_URL=${REPO_URL} - - COPY_DIR=${COPY_DIR} - - NTFY_URL=${NTFY_URL} - - GIT_USERNAME=${GIT_USERNAME} - - GIT_PASSWORD=${GIT_PASSWORD} - - TZ=America/Denver + env_file: + - stack.env image: git.bunny-lab.io/container-registry/git-repo-updater:latest volumes: - #This folder is where the repository will be downloaded and updated - it needs a unique folder name. - - ${TEMP_DIR}:/root/Repo_Watcher/repo - #This is where you want the git repository data to be copied to (e.g. a server's data folder) - - ${COPY_DIR}:/DATA + - /srv/containers:/srv/containers restart: always ``` ```jsx title=".env" -REPO_URL=https://git.bunny-lab.io/bunny-lab/placeholder.git -NTFY_URL=https://ntfy.bunny-lab.io/git-repo-updater -TEMP_DIR=/srv/containers/git-repo-updater/REPO-NAME -COPY_DIR=/srv/containers/server-name/data +# Gitea Credentials GIT_USERNAME=nicole.rappe GIT_PASSWORD=USE-AN-APP-PASSWORD + +# NTFY Push Notification Server URL +NTFY_URL=https://ntfy.cyberstrawberry.net/git-repo-updater + +# Repository/Destination Pairs (Add as Many as Needed) +REPO_01="https://git.bunny-lab.io/repo1.git,/srv/containers/destination" +REPO_02="https://git.bunny-lab.io/repo1.git,/srv/containers/destination" +REPO_03="https://git.bunny-lab.io/repo1.git,/srv/containers/destination" ``` ### Build / Development If you want to learn how the container was assembled, the related build files are located [here](https://git.cyberstrawberry.net/container-registry/git-repo-updater) ```jsx title="Dockerfile" -FROM ubuntu:latest +# Use Alpine as the base image of the container +FROM alpine:latest # Install necessary packages -RUN apt-get update && \ - apt-get install -y git curl rsync +RUN apk --no-cache add git curl rsync # Add script -COPY repo_watcher.sh /root/Repo_Watcher/repo_watcher.sh +COPY repo_watcher.sh /repo_watcher.sh +RUN chmod +x /repo_watcher.sh -# Make script executable -RUN chmod +x /root/Repo_Watcher/repo_watcher.sh +#Create Directory to store Repositories +RUN mkdir -p /root/Repo_Watcher -# Start script -CMD ["/bin/bash", "-c", "/root/Repo_Watcher/repo_watcher.sh"] +# Start script (Alpine uses /bin/sh instead of /bin/bash) +CMD ["/bin/sh", "-c", "/repo_watcher.sh"] ``` ```jsx title="repo_watcher.sh" -#!/bin/bash +#!/bin/sh +# Function to process each repo-destination pair +process_repo() { + REPO_URL=$1 + DESTINATION=$2 + + # Set Git credentials + git config --global credential.helper 'store --file /tmp/git-credentials' + echo "url=$REPO_URL" > /tmp/git-credentials + echo "username=$GIT_USERNAME" >> /tmp/git-credentials + echo "password=$GIT_PASSWORD" >> /tmp/git-credentials + + # Directory to hold the repository locally + REPO_DIR="/root/Repo_Watcher/$(basename $REPO_URL)" + + # Clone the repo if it doesn't exist, or navigate to it if it does + if [ ! -d "$REPO_DIR" ]; then + curl -d "Cloning: $REPO_URL" $NTFY_URL + echo "Cloning: $REPO_URL" + git clone "$REPO_URL" "$REPO_DIR" + fi + cd "$REPO_DIR" + + # Fetch the latest changes + git fetch origin main + + # Check if the local repository is behind the remote + LOCAL=$(git rev-parse @) + REMOTE=$(git rev-parse @{u}) + + if [ $LOCAL != $REMOTE ]; then + curl -d "Updating: $REPO_URL" $NTFY_URL + echo "Updating: $REPO_URL" + git pull origin main + rsync -av --delete --exclude '.git/' ./ "$DESTINATION" + else + echo "Repository $REPO_URL Up-to-Date" + fi +} + +# Main loop while true; do - # Set Git credentials - git config --global credential.helper 'store --file /tmp/git-credentials' - echo "url=$REPO_URL" > /tmp/git-credentials - echo "username=$GIT_USERNAME" >> /tmp/git-credentials - echo "password=$GIT_PASSWORD" >> /tmp/git-credentials + # Iterate over each environment variable matching 'REPO_[0-9]+' + env | grep '^REPO_[0-9]\+=' | while IFS='=' read -r name value; do + # Split the value by comma and read into separate variables + OLD_IFS="$IFS" # Save the original IFS + IFS=',' # Set IFS to comma for splitting + set -- $value # Set positional parameters ($1, $2, ...) + REPO_URL="$1" # Assign first parameter to REPO_URL + DESTINATION="$2" # Assign second parameter to DESTINATION + IFS="$OLD_IFS" # Restore original IFS - # Navigate to the watcher directory - cd /root/Repo_Watcher - - # Clone the repo if it doesn't exist - if [ -z "$(find /root/Repo_Watcher/repo -maxdepth 1 -mindepth 1 -type f -o -type d 2>/dev/null)" ]; then - curl -d "Repository $REPO_URL doesn't exist locally - Downloading..." $NTFY_URL - echo "Repository $REPO_URL doesn't exist locally - Downloading..." - git clone $REPO_URL repo - cd repo - rsync -av --delete --exclude '.git/' ./ /DATA - fi - - cd repo - - # Fetch the latest changes - git fetch origin main - - # Check if the local repository is behind the remote - LOCAL=$(git rev-parse @) - REMOTE=$(git rev-parse @{u}) - BASE=$(git merge-base @ @{u}) - - if [ $LOCAL = $REMOTE ]; then - echo "Repository Up-to-Date" - else - curl -d "$REPO_URL Automatically Pulling Updates..." $NTFY_URL - echo "Pulling Updates from Repository..." - git pull origin main - rsync -av --delete --exclude '.git/' ./ /DATA - fi - - # Wait for 5 seconds before the next iteration - sleep 5 + process_repo "$REPO_URL" "$DESTINATION" + done + # Wait for 5 seconds before the next iteration + sleep 5 done + + ``` \ No newline at end of file