You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

181 lines
6.8 KiB

  1. #! python
  2. """
  3. This is an alternative to `git_hooks_post-receive.sh`
  4. The post commit hook in Gitea would include something like the following to ensure this script is called.
  5. #!/bin/sh
  6. read oldrev newrev ref
  7. python "D:\dev\websites\sandpoints-dev\custom_syadmin\git_hooks_post-receive.py" \
  8. --git_repo "D:\dev\websites\pirate-care-syllabus\gitea\gitea-repositories\gitea\pirate-care-syllabus.git" \
  9. --website "D:\dev\websites\testing-ground\sandpoints" \
  10. --website_preview "D:\dev\websites\testing-ground\sandpoints\_preview" \
  11. --hugo_preview_url http://localhost:8000/_preview/ \
  12. --library "D:\dev\websites\pirate-care-syllabus\_library" \
  13. --tmp_dir "D:\tmp\tmp"
  14. --oldrev $oldrev \
  15. --newrev $newrev \
  16. --ref $ref
  17. To test this script from the command line without relying on a commit hook being triggered, use:
  18. 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"
  19. Just a mental note to read refs from the post-receive hook like this:
  20. oldrev,newrev,refname = sys.stdin.readline().strip().split(’ ‘)
  21. """
  22. import os
  23. import argparse
  24. import random
  25. import string
  26. import subprocess
  27. import shutil
  28. import stat
  29. from datetime import datetime
  30. # format for dates
  31. date_format = "%m/%d/%Y, %H:%M:%S"
  32. # Set the variables we'll be allowing for (as CL arg or environment variable)
  33. vars = {
  34. 'oldrev': False, # set programmatically by git hook
  35. 'newrev': False, # set programmatically by git hook
  36. 'ref': False, # set programmatically by git hook
  37. 'library': '_library',
  38. 'website': '_website',
  39. 'website_preview': '_websitepreview',
  40. 'git_repo': False,
  41. 'base_url': False, #override the site's base
  42. 'git_url': False,
  43. 'git_path': 'git',
  44. 'hugo_path': 'hugo',
  45. 'tmp_dir': '/tmp',
  46. 'force': False,
  47. 'branch': None,
  48. 'preview_branch': None,
  49. }
  50. # logging time
  51. start_time = datetime.now().strftime(date_format)
  52. def random_string(length=3):
  53. """ Generates a random string """
  54. letters = string.ascii_lowercase
  55. return ''.join(random.choice(letters) for i in range(length))
  56. def get_value(name, default=False):
  57. """ Variables can be set as environment variable or in command line """
  58. if hasattr(args, name.lower()) and getattr(args, name.lower()) is not None:
  59. print('CLI:', name, getattr(args, name.lower()))
  60. return getattr(args, name.lower())
  61. elif name.upper() in os.environ:
  62. print('env:', name, os.environ[name.upper()])
  63. return os.environ[name.upper()]
  64. else:
  65. print('default:', name, default)
  66. return default
  67. def cmd(parts, cwd=None, env=None):
  68. """ Executes a shell command and returns the output """
  69. print(f"Command: {' '.join(parts)} ({cwd})")
  70. return subprocess.check_output(parts, cwd=cwd, env=env, universal_newlines=True).strip()
  71. def rmrf(path):
  72. """ Use safe-rm for recursive removal """
  73. """ @TODO: make it safer """
  74. def remove_readonly(func, path, excinfo):
  75. os.chmod(path, stat.S_IWRITE)
  76. func(path)
  77. # Try removal
  78. if os.path.exists(path) and len(os.path.realpath(path)) > 1:
  79. shutil.rmtree(path, onerror=remove_readonly)
  80. else:
  81. print("Either the path doesn't exist or you are trying to delete the root directory(?!):", path)
  82. def clobber(filepath, data, append=False):
  83. """ Equivalent of > or >> when append is True """
  84. mode = 'a' if append else 'w'
  85. with open(filepath, mode) as f:
  86. f.write(data)
  87. def build_site(dest, tmp, branch=None, hugo_environment='gitea'):
  88. """ builds the website to "dest" using "tmp" as an intermediate location """
  89. global GIT_PATH, GIT_REPO, HUGO_PATH
  90. if branch:
  91. print("Cloning branch: ", branch)
  92. cmd([GIT_PATH, 'clone', '--branch', branch, '.', tmp], cwd=GIT_REPO)
  93. #print(' '.join([GIT_PATH, 'archive', '--format', 'tar', branch, '|', 'tar', '-x', '-C', tmp]))
  94. #subprocess.call(' '.join([GIT_PATH, 'archive', '--format', 'tar', branch, '|', 'tar', '-x', '-C', tmp]), shell=True, cwd=GIT_REPO)
  95. else:
  96. cmd([GIT_PATH, 'clone', '.', tmp], cwd=GIT_REPO)
  97. rmrf(os.path.join(tmp, '.git'))
  98. rmrf(dest)
  99. try:
  100. os.makedirs(dest, exist_ok=True)
  101. except:
  102. print(f"Error creating the directory: {dest}")
  103. lcl = f'{tmp}/last-commit-log.txt'
  104. # overriding hugo config for development environments
  105. env = os.environ.copy()
  106. if BASE_URL:
  107. env["HUGO_PARAMS_BASEURL"] = BASE_URL
  108. if GIT_URL:
  109. env["HUGO_PARAMS_GITURL"] = GIT_URL
  110. # run the hugo command
  111. hugo_output = cmd([HUGO_PATH, '-e', hugo_environment, '-d', dest], cwd=tmp, env=env)
  112. clobber(lcl, hugo_output)
  113. now_time = datetime.now().strftime(date_format)
  114. clobber(lcl, f"\n{start_time}\n{now_time}", append=True)
  115. shutil.move(lcl, dest)
  116. # Parsing command line arguments
  117. parser = argparse.ArgumentParser()
  118. for v in vars:
  119. parser.add_argument(f"--{v.lower()}")
  120. args = parser.parse_args()
  121. # Load all variables from command line arguments or environment variables
  122. for v in vars:
  123. globals()[v.upper()] = get_value(v.lower(), vars[v])
  124. # set up directories
  125. os.makedirs(WEBSITE, exist_ok=True)
  126. os.makedirs(WEBSITE_PREVIEW, exist_ok=True)
  127. TMP_WEBSITE = os.path.join(TMP_DIR, 'website', random_string())
  128. TMP_WEBSITE_PREVIEW = os.path.join(TMP_DIR, 'websitepreview', random_string())
  129. os.makedirs(TMP_WEBSITE, exist_ok=True)
  130. os.makedirs(TMP_WEBSITE_PREVIEW, exist_ok=True)
  131. # start working
  132. # Check if someone edited the publish trigger
  133. published = False
  134. refs = cmd([GIT_PATH, 'diff-tree', '--no-commit-id', '--name-only', REF], cwd=GIT_REPO).split("\n")
  135. for r in refs:
  136. if FORCE or r == "PUBLISH.trigger.md":
  137. build_site(WEBSITE, TMP_WEBSITE, branch=BRANCH)
  138. published = True
  139. # Check if there is a !publish!
  140. if not published:
  141. refs = cmd([GIT_PATH, 'show', '--format="%s"', '-s'], cwd=GIT_REPO).split(' ')
  142. for r in refs:
  143. if r == "!publish!":
  144. build_site(WEBSITE, TMP_WEBSITE, branch=BRANCH)
  145. published = True
  146. # Let the world know if there hasn't been a publish
  147. if not published:
  148. print("The site wasn't build because there was no publish trigger, nor was it forced.")
  149. # create preview version
  150. build_site(WEBSITE_PREVIEW, TMP_WEBSITE_PREVIEW, branch=PREVIEW_BRANCH, hugo_environment='preview')
  151. # Clean up temp directories
  152. rmrf(TMP_WEBSITE)
  153. rmrf(TMP_WEBSITE_PREVIEW)
  154. # @TODO: link the library