diff --git a/.github/workflows/first-time-setup.yaml b/.github/workflows/first-time-setup.yaml index eb0274a865..d099dbc094 100644 --- a/.github/workflows/first-time-setup.yaml +++ b/.github/workflows/first-time-setup.yaml @@ -76,11 +76,15 @@ jobs: - name: Personalize readme for user run: | printf " - # ${{ env.USER }}'s Website + ![on-push](../../actions/workflows/on-push.yaml/badge.svg) + ![on-pull-request](../../actions/workflows/on-pull-request.yaml/badge.svg) + ![on-schedule](../../actions/workflows/on-schedule.yaml/badge.svg) - Visit **[website url](#)** 🚀 + # ${{ env.USER }}'s Website - _Built with [Lab Website Template](https://greene-lab.gitbook.io/lab-website-template-docs)_ + Visit **[website url](#)** 🚀 + + _Built with [Lab Website Template](https://greene-lab.gitbook.io/lab-website-template-docs)_ " > README.md - name: Personalize Jekyll config for user diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f35b7c7e..63d03ae9b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ Reference: common-changelog.org +## 1.3.3 - 2025-01-25 + +### Changed + +- Citation process logging enhancements. + +### Added + +- Add support for multiple authors in blog posts. +- Add GitHub Actions workflow status badges to readme. + ## 1.3.2 - 2025-01-06 ### Changed diff --git a/CITATION.cff b/CITATION.cff index f75e0394c1..32dbad975c 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,8 +1,8 @@ # citation metadata for the template itself title: "Lab Website Template" -version: 1.3.2 -date-released: 2025-01-06 +version: 1.3.3 +date-released: 2025-01-25 url: "https://github.com/greenelab/lab-website-template" authors: - family-names: "Rubinetti" diff --git a/_cite/cite.py b/_cite/cite.py index 6cd5befcd6..e277722d73 100644 --- a/_cite/cite.py +++ b/_cite/cite.py @@ -13,8 +13,9 @@ load_dotenv() -# error flag -error = False +# save errors/warnings for reporting at end +errors = [] +warnings = [] # output citations file output_file = "_data/citations.yaml" @@ -41,46 +42,46 @@ files = Path.cwd().glob(f"_data/{plugin.stem}*.*") files = list(filter(lambda p: p.suffix in [".yaml", ".yml", ".json"], files)) - log(f"Found {len(files)} {plugin.stem}* data file(s)", 1) + log(f"Found {len(files)} {plugin.stem}* data file(s)", indent=1) # loop through data files for file in files: - log(f"Processing data file {file.name}", 1) + log(f"Processing data file {file.name}", indent=1) # load data from file try: data = load_data(file) # check if file in correct format if not list_of_dicts(data): - raise Exception("File not a list of dicts") + raise Exception(f"{file.name} data file not a list of dicts") except Exception as e: - log(e, 2, "ERROR") - error = True + log(e, indent=2, level="ERROR") + errors.append(e) continue # loop through data entries for index, entry in enumerate(data): - log(f"Processing entry {index + 1} of {len(data)}, {label(entry)}", 2) + log(f"Processing entry {index + 1} of {len(data)}, {label(entry)}", level=2) # run plugin on data entry to expand into multiple sources try: expanded = import_module(f"plugins.{plugin.stem}").main(entry) # check that plugin returned correct format if not list_of_dicts(expanded): - raise Exception("Plugin didn't return list of dicts") + raise Exception(f"{plugin.stem} plugin didn't return list of dicts") # catch any plugin error except Exception as e: # log detailed pre-formatted/colored trace print(traceback.format_exc()) # log high-level error - log(e, 3, "ERROR") - error = True + log(e, indent=3, level="ERROR") + errors.append(e) continue # loop through sources for source in expanded: if plugin.stem != "sources": - log(label(source), 3) + log(label(source), level=3) # include meta info about source source["plugin"] = plugin.name @@ -90,7 +91,7 @@ sources.append(source) if plugin.stem != "sources": - log(f"{len(expanded)} source(s)", 3) + log(f"{len(expanded)} source(s)", indent=3) log("Merging sources by id") @@ -103,7 +104,7 @@ for b in range(a + 1, len(sources)): b_id = get_safe(sources, f"{b}.id", "") if b_id == a_id: - log(f"Found duplicate {b_id}", 2) + log(f"Found duplicate {b_id}", indent=2) sources[a].update(sources[b]) sources[b] = {} sources = [entry for entry in sources if entry] @@ -136,7 +137,7 @@ # Manubot doesn't work without an id if _id: - log("Using Manubot to generate citation", 1) + log("Using Manubot to generate citation", indent=1) try: # run Manubot and set citation @@ -144,13 +145,18 @@ # if Manubot cannot cite source except Exception as e: + plugin = get_safe(source, "plugin", "") + file = get_safe(source, "file", "") # if regular source (id entered by user), throw error - if get_safe(source, "plugin", "") == "sources.py": - log(e, 3, "ERROR") - error = True + if plugin == "sources.py": + log(e, indent=3, level="ERROR") + errors.append(f"Manubot could not generate citation for source {_id}") # otherwise, if from metasource (id retrieved from some third-party API), just warn else: - log(e, 3, "WARNING") + log(e, indent=3, level="WARNING") + warnings.append( + f"Manubot could not generate citation for source {_id} (from {file} with {plugin})" + ) # discard source from citations continue @@ -175,14 +181,26 @@ save_data(output_file, citations) except Exception as e: log(e, level="ERROR") - error = True + errors.append(e) -# exit at end, so user can see all errors in one run -if error: - log("Error(s) occurred above", level="ERROR") +log() + + +# exit at end, so user can see all errors/warnings in one run +if len(warnings): + log(f"{len(warnings)} warning(s) occurred above", level="WARNING") + for warning in warnings: + log(warning, indent=1, level="WARNING") + +if len(errors): + log(f"{len(errors)} error(s) occurred above", level="ERROR") + for error in errors: + log(error, indent=1, level="ERROR") + log() exit(1) + else: log("All done!", level="SUCCESS") -log("\n") +log() diff --git a/_cite/util.py b/_cite/util.py index 904ff3329b..5ccc8de7c0 100644 --- a/_cite/util.py +++ b/_cite/util.py @@ -39,20 +39,25 @@ def log(message="\n--------------------\n", indent=0, level="", newline=True): log to terminal, color determined by indent and level """ - palette = { + colors = { 0: "[orange1]", 1: "[salmon1]", 2: "[violet]", 3: "[sky_blue1]", - "ERROR": "[white on #F43F5E]", - "WARNING": "[black on #EAB308]", - "SUCCESS": "[black on #10B981]", + "ERROR": "[#F43F5E]", + "WARNING": "[#EAB308]", + "SUCCESS": "[#10B981]", "INFO": "[grey70]", } - color = get_safe(palette, level, "") or get_safe(palette, indent, "") or "[white]" + prefixes = { + "ERROR": "🚫 ERROR: ", + "WARNING": "⚠️ WARNING: ", + } + color = get_safe(colors, level, "") or get_safe(colors, indent, "") or "[white]" + prefix = get_safe(prefixes, level, "") if newline: print() - print(indent * " " + color + str(message) + "[/]", end="", flush=True) + print(indent * " " + color + prefix + str(message) + "[/]", end="", flush=True) def label(entry): @@ -179,7 +184,7 @@ def cite_with_manubot(_id): commands = ["manubot", "cite", _id, "--log-level=WARNING"] output = subprocess.Popen(commands, stdout=subprocess.PIPE).communicate() except Exception as e: - log(e, 3) + log(e, indent=3) raise Exception("Manubot could not generate citation") # parse results as json diff --git a/_includes/post-info.html b/_includes/post-info.html index c0585d702a..e1f59dd029 100644 --- a/_includes/post-info.html +++ b/_includes/post-info.html @@ -1,17 +1,25 @@