mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-01-06 07:23:16 +00:00
_ch
This commit is contained in:
4
.github/workflows/autochangelog.yml
vendored
4
.github/workflows/autochangelog.yml
vendored
@@ -29,12 +29,12 @@ jobs:
|
||||
run: |
|
||||
pip install pyyaml
|
||||
python tools/GenerateChangelog/ss13_autochangelog.py \
|
||||
html/changelogs \
|
||||
html/changelogs_ch \
|
||||
${{ github.event.pull_request.number }} \
|
||||
"${{ github.event.pull_request.user.login }}" \
|
||||
"${{ github.event.pull_request.body }}"
|
||||
python tools/GenerateChangelog/ss13_genchangelog.py \
|
||||
html/changelogs
|
||||
html/changelogs_ch
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Automatic changelog generation for ${{ github.events.pull_request.number }}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
//VOREStation Edit End
|
||||
|
||||
// CHOMPedit Start - Better Changelogs
|
||||
var/latest_changelog = file("/html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
|
||||
var/latest_changelog = file("/html/changelogs_ch/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
|
||||
changelog_hash = fexists(latest_changelog) ? md5(latest_changelog) : 0 //for telling if the changelog has changed recently
|
||||
// CHOMPedit End
|
||||
|
||||
|
||||
19
html/changelogs_ch/__CHANGELOG_README.txt
Normal file
19
html/changelogs_ch/__CHANGELOG_README.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Changelogs are included with commits as text .yml files created individually by the committer. If you want to create a changelog entry you create a .yml file in the /changelogs_ch directory; nothing else needs to be touched unless you are a maintainer.
|
||||
|
||||
#######################################################
|
||||
|
||||
TO MAKE A CHANGELOG .YML ENTRRY
|
||||
|
||||
1. Make a copy of the file example.yml in html/changelogs_ch and rename it to [YOUR USERNAME]-PR-[YOUR PR NUMBER].yml or [YOUR USERNAME]-[YOUR BRANCH NAME]. Only the username is strictly required, anything else is organizational and can be ignored if you so wish.
|
||||
|
||||
2. Change the author to yourself
|
||||
|
||||
3. Replace the changes text with a description of the changes in your PR, keep the double quotes to avoid errors (your changelog can be written ICly or OOCly, it doesn't matter)
|
||||
|
||||
4. (Optional) set the change prefix (rscadd) to a different one listed above in example.yml (this affects what icon is used for your changelog entry)
|
||||
|
||||
5. When commiting make sure your .yml file is included in the commit (it will usually be unticked as an unversioned file)
|
||||
|
||||
#######################################################
|
||||
|
||||
If you have trouble ask for help in #codershuttle on irc.sorcery.net or read https://tgstation13.org/wiki/Guide_to_Changelogs
|
||||
60
html/changelogs_ch/example.yml
Normal file
60
html/changelogs_ch/example.yml
Normal file
@@ -0,0 +1,60 @@
|
||||
################################
|
||||
# Example Changelog File
|
||||
#
|
||||
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
|
||||
#
|
||||
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
|
||||
# When it is, any changes listed below will disappear.
|
||||
#
|
||||
# Valid Prefixes:
|
||||
# bugfix
|
||||
# - (fixes bugs)
|
||||
# wip
|
||||
# - (work in progress)
|
||||
# qol
|
||||
# - (quality of life)
|
||||
# soundadd
|
||||
# - (adds a sound)
|
||||
# sounddel
|
||||
# - (removes a sound)
|
||||
# rscadd
|
||||
# - (adds a feature)
|
||||
# rscdel
|
||||
# - (removes a feature)
|
||||
# imageadd
|
||||
# - (adds an image or sprite)
|
||||
# imagedel
|
||||
# - (removes an image or sprite)
|
||||
# maptweak
|
||||
# spellcheck
|
||||
# - (fixes spelling or grammar)
|
||||
# experiment
|
||||
# - (experimental change)
|
||||
# balance
|
||||
# - (balance changes)
|
||||
# code_imp
|
||||
# - (misc internal code change)
|
||||
# refactor
|
||||
# - (refactors code)
|
||||
# config
|
||||
# - (makes a change to the config files)
|
||||
# admin
|
||||
# - (makes changes to administrator tools)
|
||||
# server
|
||||
# - (miscellaneous changes to server)
|
||||
#################################
|
||||
|
||||
# Your name.
|
||||
author: "
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- rscadd: "Added a changelog editing system that should cause fewer conflicts and more accurate timestamps."
|
||||
- rscdel: "Killed innocent kittens."
|
||||
@@ -25,7 +25,7 @@
|
||||
var/list/data = list( "dates" = list() )
|
||||
var/regex/ymlRegex = regex(@"\.yml", "g")
|
||||
|
||||
for(var/archive_file in sortList(flist("html/changelogs/archive/")))
|
||||
for(var/archive_file in sortList(flist("html/changelogs_ch/archive/")))
|
||||
var/archive_date = ymlRegex.Replace(archive_file, "")
|
||||
data["dates"] = list(archive_date) + data["dates"]
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/datum/asset/changelog_item/New(date)
|
||||
item_filename = sanitize_filename("[date].yml")
|
||||
register_asset(item_filename, file("html/changelogs/archive/" + item_filename))
|
||||
register_asset(item_filename, file("html/changelogs_ch/archive/" + item_filename))
|
||||
|
||||
/datum/asset/changelog_item/send(client)
|
||||
if (!item_filename)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@echo off
|
||||
rem Cheridan asked for this. - N3X
|
||||
call python ss13_genchangelog.py ../../html/changelogs
|
||||
call python ss13_genchangelog.py ../../html/changelog.html ../../html/changelogs
|
||||
pause
|
||||
|
||||
4
tools/GenerateChangelog/makeChangelog_ch.bat
Normal file
4
tools/GenerateChangelog/makeChangelog_ch.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
rem Cheridan asked for this. - N3X
|
||||
call python ss13_genchangelog.py ../../html/changelogs_ch
|
||||
pause
|
||||
@@ -26,15 +26,15 @@ all_changelog_entries = {}
|
||||
|
||||
validPrefixes = {
|
||||
"fix": 'bugfix',
|
||||
"fixed": 'bugfix',
|
||||
"fixes": 'bugfix',
|
||||
"bugfix": 'bugfix',
|
||||
"wip": 'wip',
|
||||
"qol": 'qol',
|
||||
"tweak": 'tweak',
|
||||
"tweaks": 'tweak',
|
||||
"rsctweak": 'tweak',
|
||||
"soundadd": 'soundadd',
|
||||
"sounddel": 'sounddel',
|
||||
"add": 'rscadd',
|
||||
"added": 'rscadd',
|
||||
"adds": 'rscadd',
|
||||
"rscadd": 'rscadd',
|
||||
"del": 'rscdel',
|
||||
@@ -51,13 +51,7 @@ validPrefixes = {
|
||||
"spellcheck": 'spellcheck',
|
||||
"experimental": 'experiment',
|
||||
"experiments": 'experiment',
|
||||
"experiment": 'experiment',
|
||||
"balance": 'balance',
|
||||
"code_imp": 'code_imp',
|
||||
"refactor": 'refactor',
|
||||
"config": 'config',
|
||||
"admin": 'admin',
|
||||
"server": 'server',
|
||||
"experiment": 'experiment'
|
||||
}
|
||||
|
||||
incltag = False
|
||||
|
||||
127
tools/GenerateChangelog/ss13_autochangelog_ch.py
Normal file
127
tools/GenerateChangelog/ss13_autochangelog_ch.py
Normal file
@@ -0,0 +1,127 @@
|
||||
'''
|
||||
Usage:
|
||||
$ python ss13_autochangelog.py [--dry-run] html/changelogs_ch [PR_number] [PR_author] [PR_Body]
|
||||
|
||||
ss13_autochangelog.py - Generate changelog YAML files from pull request.
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import os, sys, re, time, argparse
|
||||
from datetime import datetime, date
|
||||
from time import time
|
||||
|
||||
today = date.today()
|
||||
|
||||
dateformat = "%d %B %Y"
|
||||
|
||||
opt = argparse.ArgumentParser()
|
||||
opt.add_argument('target_dir', help='The location to write changelog files to.')
|
||||
opt.add_argument('pr_numb', help='The number of the pull request.')
|
||||
opt.add_argument('pr_author', help='The author of the pull request. If specific authors aren\'t specified, the PR author will be used')
|
||||
opt.add_argument('pr_body', help='The body of the pull request to parse for changelogs.')
|
||||
|
||||
args = opt.parse_args()
|
||||
|
||||
all_changelog_entries = {}
|
||||
|
||||
validPrefixes = {
|
||||
"fix": 'bugfix',
|
||||
"fixed": 'bugfix',
|
||||
"fixes": 'bugfix',
|
||||
"bugfix": 'bugfix',
|
||||
"wip": 'wip',
|
||||
"qol": 'qol',
|
||||
"soundadd": 'soundadd',
|
||||
"sounddel": 'sounddel',
|
||||
"add": 'rscadd',
|
||||
"added": 'rscadd',
|
||||
"adds": 'rscadd',
|
||||
"rscadd": 'rscadd',
|
||||
"del": 'rscdel',
|
||||
"dels": 'rscdel',
|
||||
"delete": 'rscdel',
|
||||
"deletes": 'rscdel',
|
||||
"rscdeldel": 'rscdel',
|
||||
"imageadd": 'imageadd',
|
||||
"imagedel": 'imagedel',
|
||||
"maptweak": 'maptweak',
|
||||
"remap": 'maptweak',
|
||||
"remaps": 'maptweak',
|
||||
"typo": 'spellcheck',
|
||||
"spellcheck": 'spellcheck',
|
||||
"experimental": 'experiment',
|
||||
"experiments": 'experiment',
|
||||
"experiment": 'experiment',
|
||||
"balance": 'balance',
|
||||
"code_imp": 'code_imp',
|
||||
"refactor": 'refactor',
|
||||
"config": 'config',
|
||||
"admin": 'admin',
|
||||
"server": 'server',
|
||||
}
|
||||
|
||||
incltag = False
|
||||
new_logs = {}
|
||||
author = args.pr_author
|
||||
new = 0
|
||||
|
||||
# Parse PR body for changelog entries
|
||||
print('Reading changelogs...')
|
||||
for line in args.pr_body.splitlines():
|
||||
print(f"Checking line '{line}'")
|
||||
if line[:1] == "🆑": # Find the start of the changelog
|
||||
print("Found opening :cl: tag")
|
||||
if incltag == True: # If we're already reading logs, skip
|
||||
continue
|
||||
incltag = True
|
||||
|
||||
# Fetch the author name
|
||||
author = line[1:]
|
||||
author.strip()
|
||||
|
||||
if not len(author):
|
||||
author = args.pr_author
|
||||
|
||||
if author not in new_logs:
|
||||
new_logs[author] = [] # Make array entry for the author
|
||||
continue
|
||||
|
||||
# If we hit a /cl, we're no longer reading logs
|
||||
elif line == "/🆑":
|
||||
print("Found closing /:cl: tag")
|
||||
incltag = False
|
||||
|
||||
# If we aren't reading logs, we don't care about any other line contents
|
||||
if not incltag:
|
||||
continue
|
||||
|
||||
# Split line into tag (icon) and body (comment)
|
||||
body = re.split("[ ,:-]", line, 1)
|
||||
if len(body) != 2:
|
||||
continue # If there's just one word, then it can't really be a changelog, now can it
|
||||
|
||||
if body[0] in validPrefixes:
|
||||
tag = validPrefixes[body[0]]
|
||||
body = body[1].strip(" ,-:\t\n")
|
||||
else: # If the tag is invalid, just default to rscadd
|
||||
tag = "rscadd"
|
||||
body = line.strip(" ,-:\t\n")
|
||||
|
||||
new_logs[author].append(f" - {tag}: \"{body}\"")
|
||||
new += 1
|
||||
|
||||
print(f"Writing {new} new changelog entries.") # f supposedly formats new into the var
|
||||
|
||||
for auth in new_logs:
|
||||
# Sanitize authors without changes
|
||||
if not len(new_logs[auth]):
|
||||
continue
|
||||
|
||||
f = open(os.path.join(args.target_dir, f"{auth}{args.pr_numb}.yml"), 'w')
|
||||
print(f"Writing changes to {f}")
|
||||
f.write(f'author: {auth}\n')
|
||||
f.write('delete-after: True\n')
|
||||
f.write('changes:\n')
|
||||
for log in new_logs[auth]:
|
||||
f.write(f'{log}\n')
|
||||
f.close()
|
||||
@@ -1,6 +1,6 @@
|
||||
'''
|
||||
Usage:
|
||||
$ python ss13_genchangelog.py html/changelogs/
|
||||
$ python ss13_genchangelog.py [--dry-run] html/changelog.html html/changelogs/
|
||||
|
||||
ss13_genchangelog.py - Generate changelog from YAML.
|
||||
|
||||
@@ -32,77 +32,100 @@ from time import time
|
||||
|
||||
today = date.today()
|
||||
|
||||
fileDateFormat = "%Y-%m"
|
||||
dateformat = "%d %B %Y"
|
||||
|
||||
opt = argparse.ArgumentParser()
|
||||
opt.add_argument('-d', '--dry-run', dest='dryRun', default=False, action='store_true', help='Only parse changelogs and, if needed, the targetFile. (A .dry_changelog.yml will be output for debugging purposes.)')
|
||||
opt.add_argument('targetFile', help='The HTML changelog we wish to update.')
|
||||
opt.add_argument('ymlDir', help='The directory of YAML changelogs we will use.')
|
||||
|
||||
args = opt.parse_args()
|
||||
archiveDir = os.path.join(args.ymlDir, 'archive')
|
||||
|
||||
all_changelog_entries = {}
|
||||
|
||||
# Do not change the order, add to the bottom of the array if necessary
|
||||
validPrefixes = [
|
||||
'bugfix',
|
||||
'wip',
|
||||
'qol',
|
||||
'tweak',
|
||||
'soundadd',
|
||||
'sounddel',
|
||||
'rscadd',
|
||||
'rscdel',
|
||||
'rscadd',
|
||||
'imageadd',
|
||||
'imagedel',
|
||||
'maptweak',
|
||||
'spellcheck',
|
||||
'experiment',
|
||||
'balance',
|
||||
'code_imp',
|
||||
'refactor',
|
||||
'config',
|
||||
'admin',
|
||||
'server'
|
||||
'experiment'
|
||||
]
|
||||
|
||||
def dictToTuples(inp):
|
||||
return [(k, v) for k, v in inp.items()]
|
||||
|
||||
old_changelog_cache = os.path.join(args.ymlDir, '.all_changelog.yml')
|
||||
changelog_cache = os.path.join(args.ymlDir, '.all_changelog.yml')
|
||||
|
||||
failed_cache_read = True
|
||||
if os.path.isfile(old_changelog_cache):
|
||||
if os.path.isfile(changelog_cache):
|
||||
try:
|
||||
print('Reading old changelog cache...')
|
||||
data = {}
|
||||
with open(old_changelog_cache,encoding='utf-8') as f:
|
||||
(_, all_changelog_entries) = yaml.load_all(f, Loader=yaml.SafeLoader)
|
||||
with open(changelog_cache) as f:
|
||||
(_, all_changelog_entries) = yaml.load_all(f)
|
||||
failed_cache_read = False
|
||||
|
||||
# Categorize changes by year and month
|
||||
# Convert old timestamps to newer format.
|
||||
new_entries = {}
|
||||
for _date in all_changelog_entries.keys():
|
||||
ty = type(_date).__name__
|
||||
formattedDate = _date.strftime(fileDateFormat)
|
||||
if not formattedDate in data:
|
||||
data[formattedDate] = {}
|
||||
data[formattedDate][_date] = all_changelog_entries[_date]
|
||||
# Write files with changes by year and month
|
||||
for month in data.keys():
|
||||
print("Writing " + month + ".yml...")
|
||||
if not os.path.exists(archiveDir):
|
||||
os.makedirs(archiveDir)
|
||||
currentFile = os.path.join(archiveDir, month + '.yml')
|
||||
with open(currentFile, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(data[month], f, default_flow_style=False)
|
||||
# Remove the old changelog cache, as we won't use it anymore
|
||||
print("Removing old changelog cache...")
|
||||
os.remove(old_changelog_cache)
|
||||
old_changelog_html = os.path.join(args.ymlDir, '..', 'changelog.html')
|
||||
if os.path.isfile(old_changelog_html):
|
||||
print("Removing old changelog html...")
|
||||
os.remove(old_changelog_html)
|
||||
# print(ty)
|
||||
if ty in ['str', 'unicode']:
|
||||
temp_data = all_changelog_entries[_date]
|
||||
_date = datetime.strptime(_date, dateformat).date()
|
||||
new_entries[_date] = temp_data
|
||||
else:
|
||||
new_entries[_date] = all_changelog_entries[_date]
|
||||
all_changelog_entries = new_entries
|
||||
except Exception as e:
|
||||
print("Failed to read old changelog cache:")
|
||||
print("Failed to read cache:")
|
||||
print(e, file=sys.stderr)
|
||||
|
||||
if args.dryRun:
|
||||
changelog_cache = os.path.join(args.ymlDir, '.dry_changelog.yml')
|
||||
|
||||
if failed_cache_read and os.path.isfile(args.targetFile):
|
||||
from bs4 import BeautifulSoup
|
||||
from bs4.element import NavigableString
|
||||
print(' Generating cache...')
|
||||
with open(args.targetFile, 'r') as f:
|
||||
soup = BeautifulSoup(f)
|
||||
for e in soup.find_all('div', {'class':'commit'}):
|
||||
entry = {}
|
||||
date = datetime.strptime(e.h2.string.strip(), dateformat).date() # key
|
||||
for authorT in e.find_all('h3', {'class':'author'}):
|
||||
author = authorT.string
|
||||
# Strip suffix
|
||||
if author.endswith('updated:'):
|
||||
author = author[:-8]
|
||||
author = author.strip()
|
||||
|
||||
# Find <ul>
|
||||
ulT = authorT.next_sibling
|
||||
while(ulT.name != 'ul'):
|
||||
ulT = ulT.next_sibling
|
||||
changes = []
|
||||
|
||||
for changeT in ulT.children:
|
||||
if changeT.name != 'li': continue
|
||||
val = changeT.decode_contents(formatter="html")
|
||||
newdat = {changeT['class'][0] + '': val + ''}
|
||||
if newdat not in changes:
|
||||
changes += [newdat]
|
||||
|
||||
if len(changes) > 0:
|
||||
entry[author] = changes
|
||||
if date in all_changelog_entries:
|
||||
all_changelog_entries[date].update(entry)
|
||||
else:
|
||||
all_changelog_entries[date] = entry
|
||||
|
||||
del_after = []
|
||||
errors = False
|
||||
print('Reading changelogs...')
|
||||
for fileName in glob.glob(os.path.join(args.ymlDir, "*.yml")):
|
||||
@@ -110,19 +133,14 @@ for fileName in glob.glob(os.path.join(args.ymlDir, "*.yml")):
|
||||
if name.startswith('.'): continue
|
||||
if name == 'example': continue
|
||||
fileName = os.path.abspath(fileName)
|
||||
formattedDate = today.strftime(fileDateFormat)
|
||||
monthFile = os.path.join(archiveDir, formattedDate + '.yml')
|
||||
print(' Reading {}...'.format(fileName))
|
||||
cl = {}
|
||||
with open(fileName, 'r') as f:
|
||||
cl = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
currentEntries = {}
|
||||
if os.path.exists(monthFile):
|
||||
with open(monthFile,'r',encoding='utf-8') as f:
|
||||
currentEntries = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
if today not in currentEntries:
|
||||
currentEntries[today] = {}
|
||||
author_entries = currentEntries[today].get(cl['author'], [])
|
||||
cl = yaml.load(f)
|
||||
f.close()
|
||||
if today not in all_changelog_entries:
|
||||
all_changelog_entries[today] = {}
|
||||
author_entries = all_changelog_entries[today].get(cl['author'], [])
|
||||
if len(cl['changes']):
|
||||
new = 0
|
||||
for change in cl['changes']:
|
||||
@@ -133,17 +151,65 @@ for fileName in glob.glob(os.path.join(args.ymlDir, "*.yml")):
|
||||
print(' {0}: Invalid prefix {1}'.format(fileName, change_type), file=sys.stderr)
|
||||
author_entries += [change]
|
||||
new += 1
|
||||
currentEntries[today][cl['author']] = author_entries
|
||||
all_changelog_entries[today][cl['author']] = author_entries
|
||||
if new > 0:
|
||||
print(' Added {0} new changelog entries.'.format(new))
|
||||
|
||||
if cl.get('delete-after', False):
|
||||
if os.path.isfile(fileName):
|
||||
print(' Deleting {0} (delete-after set)...'.format(fileName))
|
||||
os.remove(fileName)
|
||||
if args.dryRun:
|
||||
print(' Would delete {0} (delete-after set)...'.format(fileName))
|
||||
else:
|
||||
del_after += [fileName]
|
||||
|
||||
with open(monthFile, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(currentEntries, f, default_flow_style=False)
|
||||
if args.dryRun: continue
|
||||
|
||||
cl['changes'] = []
|
||||
with open(fileName, 'w') as f:
|
||||
yaml.dump(cl, f, default_flow_style=False)
|
||||
|
||||
targetDir = os.path.dirname(args.targetFile)
|
||||
|
||||
with open(args.targetFile.replace('.htm', '.dry.htm') if args.dryRun else args.targetFile, 'w') as changelog:
|
||||
with open(os.path.join(targetDir, 'templates', 'header.html'), 'r') as h:
|
||||
for line in h:
|
||||
changelog.write(line)
|
||||
|
||||
for _date in reversed(sorted(all_changelog_entries.keys())):
|
||||
entry_htm = '\n'
|
||||
entry_htm += '\t\t\t<h2 class="date">{date}</h2>\n'.format(date=_date.strftime(dateformat))
|
||||
write_entry = False
|
||||
for author in sorted(all_changelog_entries[_date].keys()):
|
||||
if len(all_changelog_entries[_date]) == 0: continue
|
||||
author_htm = '\t\t\t<h3 class="author">{author} updated:</h3>\n'.format(author=author)
|
||||
author_htm += '\t\t\t<ul class="changes bgimages16">\n'
|
||||
changes_added = []
|
||||
for (css_class, change) in (dictToTuples(e)[0] for e in all_changelog_entries[_date][author]):
|
||||
if change in changes_added: continue
|
||||
write_entry = True
|
||||
changes_added += [change]
|
||||
author_htm += '\t\t\t\t<li class="{css_class}">{change}</li>\n'.format(css_class=css_class, change=change.strip())
|
||||
author_htm += '\t\t\t</ul>\n'
|
||||
if len(changes_added) > 0:
|
||||
entry_htm += author_htm
|
||||
if write_entry:
|
||||
changelog.write(entry_htm)
|
||||
|
||||
with open(os.path.join(targetDir, 'templates', 'footer.html'), 'r') as h:
|
||||
for line in h:
|
||||
changelog.write(line)
|
||||
|
||||
|
||||
with open(changelog_cache, 'w') as f:
|
||||
cache_head = 'DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.'
|
||||
yaml.dump_all([cache_head, all_changelog_entries], f, default_flow_style=False)
|
||||
|
||||
if len(del_after):
|
||||
print('Cleaning up...')
|
||||
for fileName in del_after:
|
||||
if os.path.isfile(fileName):
|
||||
print(' Deleting {0} (delete-after set)...'.format(fileName))
|
||||
os.remove(fileName)
|
||||
|
||||
if errors:
|
||||
sys.exit(1)
|
||||
|
||||
149
tools/GenerateChangelog/ss13_genchangelog_ch.py
Normal file
149
tools/GenerateChangelog/ss13_genchangelog_ch.py
Normal file
@@ -0,0 +1,149 @@
|
||||
'''
|
||||
Usage:
|
||||
$ python ss13_genchangelog.py html/changelogs_ch/
|
||||
|
||||
ss13_genchangelog.py - Generate changelog from YAML.
|
||||
|
||||
Copyright 2013 Rob "N3X15" Nelson <nexis@7chan.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import yaml, os, glob, sys, re, time, argparse
|
||||
from datetime import datetime, date
|
||||
from time import time
|
||||
|
||||
today = date.today()
|
||||
|
||||
fileDateFormat = "%Y-%m"
|
||||
|
||||
opt = argparse.ArgumentParser()
|
||||
opt.add_argument('ymlDir', help='The directory of YAML changelogs we will use.')
|
||||
|
||||
args = opt.parse_args()
|
||||
archiveDir = os.path.join(args.ymlDir, 'archive')
|
||||
|
||||
all_changelog_entries = {}
|
||||
|
||||
# Do not change the order, add to the bottom of the array if necessary
|
||||
validPrefixes = [
|
||||
'bugfix',
|
||||
'wip',
|
||||
'qol',
|
||||
'soundadd',
|
||||
'sounddel',
|
||||
'rscadd',
|
||||
'rscdel',
|
||||
'imageadd',
|
||||
'imagedel',
|
||||
'maptweak',
|
||||
'spellcheck',
|
||||
'experiment',
|
||||
'balance',
|
||||
'code_imp',
|
||||
'refactor',
|
||||
'config',
|
||||
'admin',
|
||||
'server'
|
||||
]
|
||||
|
||||
def dictToTuples(inp):
|
||||
return [(k, v) for k, v in inp.items()]
|
||||
|
||||
old_changelog_cache = os.path.join(args.ymlDir, '.all_changelog.yml')
|
||||
|
||||
failed_cache_read = True
|
||||
if os.path.isfile(old_changelog_cache):
|
||||
try:
|
||||
print('Reading old changelog cache...')
|
||||
data = {}
|
||||
with open(old_changelog_cache,encoding='utf-8') as f:
|
||||
(_, all_changelog_entries) = yaml.load_all(f, Loader=yaml.SafeLoader)
|
||||
|
||||
# Categorize changes by year and month
|
||||
for _date in all_changelog_entries.keys():
|
||||
ty = type(_date).__name__
|
||||
formattedDate = _date.strftime(fileDateFormat)
|
||||
if not formattedDate in data:
|
||||
data[formattedDate] = {}
|
||||
data[formattedDate][_date] = all_changelog_entries[_date]
|
||||
# Write files with changes by year and month
|
||||
for month in data.keys():
|
||||
print("Writing " + month + ".yml...")
|
||||
if not os.path.exists(archiveDir):
|
||||
os.makedirs(archiveDir)
|
||||
currentFile = os.path.join(archiveDir, month + '.yml')
|
||||
with open(currentFile, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(data[month], f, default_flow_style=False)
|
||||
# Remove the old changelog cache, as we won't use it anymore
|
||||
print("Removing old changelog cache...")
|
||||
os.remove(old_changelog_cache)
|
||||
old_changelog_html = os.path.join(args.ymlDir, '..', 'changelog.html')
|
||||
if os.path.isfile(old_changelog_html):
|
||||
print("Removing old changelog html...")
|
||||
os.remove(old_changelog_html)
|
||||
except Exception as e:
|
||||
print("Failed to read old changelog cache:")
|
||||
print(e, file=sys.stderr)
|
||||
|
||||
errors = False
|
||||
print('Reading changelogs...')
|
||||
for fileName in glob.glob(os.path.join(args.ymlDir, "*.yml")):
|
||||
name, ext = os.path.splitext(os.path.basename(fileName))
|
||||
if name.startswith('.'): continue
|
||||
if name == 'example': continue
|
||||
fileName = os.path.abspath(fileName)
|
||||
formattedDate = today.strftime(fileDateFormat)
|
||||
monthFile = os.path.join(archiveDir, formattedDate + '.yml')
|
||||
print(' Reading {}...'.format(fileName))
|
||||
cl = {}
|
||||
with open(fileName, 'r') as f:
|
||||
cl = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
currentEntries = {}
|
||||
if os.path.exists(monthFile):
|
||||
with open(monthFile,'r',encoding='utf-8') as f:
|
||||
currentEntries = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
if today not in currentEntries:
|
||||
currentEntries[today] = {}
|
||||
author_entries = currentEntries[today].get(cl['author'], [])
|
||||
if len(cl['changes']):
|
||||
new = 0
|
||||
for change in cl['changes']:
|
||||
if change not in author_entries:
|
||||
(change_type, _) = dictToTuples(change)[0]
|
||||
if change_type not in validPrefixes:
|
||||
errors = True
|
||||
print(' {0}: Invalid prefix {1}'.format(fileName, change_type), file=sys.stderr)
|
||||
author_entries += [change]
|
||||
new += 1
|
||||
currentEntries[today][cl['author']] = author_entries
|
||||
if new > 0:
|
||||
print(' Added {0} new changelog entries.'.format(new))
|
||||
|
||||
if cl.get('delete-after', False):
|
||||
if os.path.isfile(fileName):
|
||||
print(' Deleting {0} (delete-after set)...'.format(fileName))
|
||||
os.remove(fileName)
|
||||
|
||||
with open(monthFile, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(currentEntries, f, default_flow_style=False)
|
||||
|
||||
if errors:
|
||||
sys.exit(1)
|
||||
@@ -47,7 +47,7 @@ if [ $retVal -ne 0 ]; then
|
||||
fi
|
||||
|
||||
#Checking for a change to html/changelogs/example.yml
|
||||
md5sum -c - <<< "0c56937110d88f750a32d9075ddaab8b *html/changelogs/example.yml"
|
||||
md5sum -c - <<< "0c56937110d88f750a32d9075ddaab8b *html/changelogs_ch/example.yml" # CHOMPedit - Better changelogs
|
||||
retVal=$?
|
||||
if [ $retVal -ne 0 ]; then
|
||||
echo -e "${RED}Do not modify the example.yml changelog file.${NC}"
|
||||
|
||||
Reference in New Issue
Block a user