Syllabus/custom_syadmin/git_hooks_post-receive.py

175 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

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.

#! python
"""
This is an alternative to `git_hooks_post-receive.sh`
The post commit hook in Gitea would include something like the following to ensure this script is called.
#!/bin/sh
read oldrev newrev ref
python "D:\dev\websites\sandpoints-dev\custom_syadmin\git_hooks_post-receive.py" \
--git_repo "D:\dev\websites\pirate-care-syllabus\gitea\gitea-repositories\gitea\pirate-care-syllabus.git" \
--website "D:\dev\websites\testing-ground\sandpoints" \
--website_preview "D:\dev\websites\testing-ground\sandpoints\_preview" \
--hugo_preview_url http://localhost:8000/_preview/ \
--library "D:\dev\websites\pirate-care-syllabus\_library" \
--tmp_dir "D:\tmp\tmp"
--oldrev $oldrev \
--newrev $newrev \
--ref $ref
To test this script from the command line without relying on a commit hook being triggered, use:
python "D:\dev\websites\sandpoints-dev\custom_syadmin\git_hooks_post-receive.py" --ref refs/heads/master --git_repo "D:\dev\websites\pirate-care-syllabus\gitea\gitea-repositories\gitea\pirate-care-syllabus.git" --website D:\\dev\\websites\\testing-ground\\sandpoints --website_preview D:\\dev\\websites\\testing-ground\\sandpoints\\_preview --tmp_dir D:\\tmp\\tmp --git_url "http://localhost:3000/gitea/pirate-care-syllabus" --base_url "http://localhost:8000"
Just a mental note to read refs from the post-receive hook like this:
oldrev,newrev,refname = sys.stdin.readline().strip().split( )
"""
import os
import argparse
import random
import string
import subprocess
import shutil
import stat
from datetime import datetime
# format for dates
date_format = "%m/%d/%Y, %H:%M:%S"
# Set the variables we'll be allowing for (as CL arg or environment variable)
vars = {
'oldrev': False, # set programmatically by git hook
'newrev': False, # set programmatically by git hook
'ref': False, # set programmatically by git hook
'library': '_library',
'website': '_website',
'website_preview': '_websitepreview',
'git_repo': False,
'base_url': False, #override the site's base
'git_url': False,
'git_path': 'git',
'hugo_path': 'hugo',
'tmp_dir': '/tmp',
'force': False,
'branch': None,
'preview_branch': None,
}
# logging time
start_time = datetime.now().strftime(date_format)
def random_string(length=3):
""" Generates a random string """
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(length))
def get_value(name, default=False):
""" Variables can be set as environment variable or in command line """
if hasattr(args, name.lower()) and getattr(args, name.lower()) is not None:
print('CLI:', name, getattr(args, name.lower()))
return getattr(args, name.lower())
elif name.upper() in os.environ:
print('env:', name, os.environ[name.upper()])
return os.environ[name.upper()]
else:
print('default:', name, default)
return default
def cmd(parts, cwd=None, env=None):
""" Executes a shell command and returns the output """
print(f"Command: {' '.join(parts)} ({cwd})")
return subprocess.check_output(parts, cwd=cwd, env=env, universal_newlines=True).strip()
def rmrf(path):
""" Use safe-rm for recursive removal """
""" @TODO: make it safer """
def remove_readonly(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
# Try removal
if os.path.exists(path) and len(os.path.realpath(path)) > 1:
shutil.rmtree(path, onerror=remove_readonly)
else:
print("Either the path doesn't exist or you are trying to delete the root directory(?!):", path)
def clobber(filepath, data, append=False):
""" Equivalent of > or >> when append is True """
mode = 'a' if append else 'w'
with open(filepath, mode) as f:
f.write(data)
def build_site(dest, tmp, branch=None, hugo_environment='gitea'):
""" builds the website to "dest" using "tmp" as an intermediate location """
global GIT_PATH, GIT_REPO, HUGO_PATH
if branch:
print("Cloning branch: ", branch)
cmd([GIT_PATH, 'clone', '--single-branch', '--branch', branch, '.', tmp], cwd=GIT_REPO)
else:
cmd([GIT_PATH, 'clone', '.', tmp], cwd=GIT_REPO)
rmrf(dest)
try:
os.makedirs(dest, exist_ok=True)
except:
print(f"Error creating the directory: {dest}")
lcl = f'{tmp}/last-commit-log.txt'
# overriding hugo config for development environments
env = os.environ.copy()
if BASE_URL:
env["HUGO_PARAMS_BASEURL"] = BASE_URL
if GIT_URL:
env["HUGO_PARAMS_GITURL"] = GIT_URL
# run the hugo command
hugo_output = cmd([HUGO_PATH, '-e', hugo_environment, '-d', dest], cwd=tmp, env=env)
clobber(lcl, hugo_output)
now_time = datetime.now().strftime(date_format)
clobber(lcl, f"\n{start_time}\n{now_time}", append=True)
shutil.move(lcl, dest)
rmrf(tmp)
# Parsing command line arguments
parser = argparse.ArgumentParser()
for v in vars:
parser.add_argument(f"--{v.lower()}")
args = parser.parse_args()
# Load all variables from command line arguments or environment variables
for v in vars:
globals()[v.upper()] = get_value(v.lower(), vars[v])
# set up directories
os.makedirs(WEBSITE, exist_ok=True)
os.makedirs(WEBSITE_PREVIEW, exist_ok=True)
TMP_WEBSITE = os.path.join(TMP_DIR, 'website', random_string())
TMP_WEBSITE_PREVIEW = os.path.join(TMP_DIR, 'websitepreview', random_string())
os.makedirs(TMP_WEBSITE, exist_ok=True)
os.makedirs(TMP_WEBSITE_PREVIEW, exist_ok=True)
# start working
# Check if someone edited the publish trigger
published = False
refs = cmd([GIT_PATH, 'diff-tree', '--no-commit-id', '--name-only', REF], cwd=GIT_REPO).split("\n")
for r in refs:
if FORCE or r == "PUBLISH.trigger.md":
build_site(WEBSITE, TMP_WEBSITE, branch=BRANCH)
published = True
# Check if there is a !publish!
if not published:
refs = cmd([GIT_PATH, 'show', '--format="%s"', '-s'], cwd=GIT_REPO).split(' ')
for r in refs:
if r == "!publish!":
build_site(WEBSITE, TMP_WEBSITE, branch=BRANCH)
published = True
# Let the world know if there hasn't been a publish
if not published:
print("The site wasn't build because there was no publish trigger, nor was it forced.")
# create preview version
build_site(WEBSITE_PREVIEW, TMP_WEBSITE_PREVIEW, branch=PREVIEW_BRANCH, hugo_environment='preview')
# @TODO: link the library