|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- #! 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" \
- --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, keep_dir=False):
- """ 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 keep_dir and os.path.exists(path) and len(os.path.realpath(path)) > 1:
- for root, dirs, files in os.walk(path):
- for f in files:
- os.unlink(os.path.join(root, f))
- for d in dirs:
- shutil.rmtree(os.path.join(root, d), onerror=remove_readonly)
- elif 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', '--branch', branch, '.', tmp], cwd=GIT_REPO)
- #print(' '.join([GIT_PATH, 'archive', '--format', 'tar', branch, '|', 'tar', '-x', '-C', tmp]))
- #subprocess.call(' '.join([GIT_PATH, 'archive', '--format', 'tar', branch, '|', 'tar', '-x', '-C', tmp]), shell=True, cwd=GIT_REPO)
- else:
- cmd([GIT_PATH, 'clone', '.', tmp], cwd=GIT_REPO)
- rmrf(os.path.join(tmp, '.git'))
- rmrf(dest, keep_dir=True)
- try:
- if not os.path.exists(dest):
- os.makedirs(dest)
- print("Build destination created: ", dest)
- else:
- print("Build destination exists: ", dest)
- 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)
-
-
- # 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')
-
- # Clean up temp directories
- rmrf(TMP_WEBSITE)
- rmrf(TMP_WEBSITE_PREVIEW)
-
- # @TODO: link the library
|