diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6900d41 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +# Use a common python image +FROM python:3.10-slim + +# Install dependencies +RUN apt-get update && apt-get install -y \ + wget \ + git \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Download and install Hugo +RUN wget -O /tmp/hugo.deb "https://github.com/gohugoio/hugo/releases/download/v0.129.0/hugo_extended_0.129.0_linux-amd64.deb" \ + && dpkg -i /tmp/hugo.deb \ + && rm /tmp/hugo.deb + +# Create a directory for the site +WORKDIR /app + +# Copy the update script and Python script +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +COPY update-site.py /usr/local/bin/update-site.py + +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Run the update script in a loop +CMD ["/bin/sh", "-c", "while true; do /usr/local/bin/entrypoint.sh; sleep 30; done"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..4515eea --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +services: + hugo: + build: + context: . + dockerfile: Dockerfile + environment: + - GIT_REPO_URL="https://git.kitsunehosting.net/Kenwood/kitsune-hosting.git" + volumes: + - site-source:/app/site + - site-public:/app/public + restart: unless-stopped + + nginx: + image: nginx:alpine + volumes: + - site-public:/usr/share/nginx/html + ports: + - "80:80" + restart: unless-stopped + +volumes: + site-source: # HugoHost + site-public: # HugoHost diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..b557c70 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e + +# Run the Python script +python3 /usr/local/bin/update-site.py diff --git a/update-site.py b/update-site.py new file mode 100644 index 0000000..783f912 --- /dev/null +++ b/update-site.py @@ -0,0 +1,128 @@ +import os +import time +import shutil +import logging +import subprocess + +from datetime import datetime + +# Define file paths +GIT_REPO_PATH = "/app/site" +PUB_PATH = "/app/public" +FOOTER_FILE_PATH = "/app/site/themes/kitsune-theme/layouts/partials/footer.html" +HASH_FILE_PATH = "/app/current-git-hash.txt" + + +def get_git_hash() -> str: + try: + result = subprocess.run( + ["git", "rev-parse", "HEAD"], + cwd=GIT_REPO_PATH, + capture_output=True, + text=True, + ) + except FileNotFoundError: + logging.warning( + f"No site found at {GIT_REPO_PATH}, assuming first-start. Will clone." + ) + return None + + r_hash = result.stdout.strip() + + return r_hash if len(r_hash) > 3 else None + + +def update_repo(): + # Make dir + logging.info(f"Making dirs {GIT_REPO_PATH}") + if get_git_hash() == None and os.path.exists(GIT_REPO_PATH): + logging.warning("Clearing file path") + subprocess.run(["rm", "-rv", f"{GIT_REPO_PATH}/*"]) + os.makedirs(GIT_REPO_PATH, exist_ok=True) + + # Clone + url = os.environ.get("GIT_REPO_URL", "").strip('"') + if get_git_hash() == None: + logging.info(f"Cloning '{url}'.") + subprocess.run(["git", "clone", url, GIT_REPO_PATH, "--recurse-submodules"]) + else: + logging.info(f"Fetch '{url}'.") + subprocess.run(["git", "fetch"], cwd=GIT_REPO_PATH) + logging.info(f"Pull '{url}'.") + subprocess.run(["git", "fetch"], cwd=GIT_REPO_PATH) + logging.info(f"Update submodules '{url}'.") + subprocess.run( + ["git", "submodule", "update", "--init", "--recursive"], cwd=GIT_REPO_PATH + ) + + # Return new hash + return get_git_hash() + + +def build_pages(): + logging.info("Cleaning files") + subprocess.run(["rm", "-rv", f"{PUB_PATH}/."]) + subprocess.run(["rm", "-rv", f"{GIT_REPO_PATH}/public/."]) + + logging.info("Building pages") + subprocess.run(["hugo"], cwd=GIT_REPO_PATH) + + logging.info("Copying files") + subprocess.run(["cp", "-rv", f"{GIT_REPO_PATH}/public/.", PUB_PATH]) + + +def update_footer(last_build_time, git_hash): + with open(FOOTER_FILE_PATH, "r") as file: + footer_content = file.read() + + build_info = f"Last Build: {last_build_time}, Git Hash: {git_hash}" + new_footer_content = footer_content.replace("", build_info) + + with open(FOOTER_FILE_PATH, "w") as file: + file.write(new_footer_content) + + +def main(): + # Time! + startime = time.time() + + # Get the current Git hash + current_git_hash = get_git_hash() + last_git_hash = "" + + # Check if the Git hash file exists + if not os.path.exists(HASH_FILE_PATH): + logging.warning(f"Hash at {HASH_FILE_PATH} doesn't exist!") + else: + with open(HASH_FILE_PATH, "r") as file: + last_git_hash = file.read().strip() + + if current_git_hash == last_git_hash and current_git_hash != None: + logging.info( + f"No new changes detected. Skipping rebuild for {current_git_hash}." + ) + return + + # Update repo + logging.info("Updating repo") + current_git_hash = update_repo() + + # Update footer with build metadata + last_build_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + update_footer(last_build_time, current_git_hash) + + # Rebuild site + logging.info("Building the site") + build_pages() + + # Store the new Git hash + with open(HASH_FILE_PATH, "w") as file: + file.write(current_git_hash) + + logging.info(f"Done in {time.time() - startime}!") + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + + main()