-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2698 from nf-core/dev
dev -> master for 2.12
- Loading branch information
Showing
199 changed files
with
5,036 additions
and
3,659 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
[run] | ||
omit = nf_core/pipeline-template/* | ||
omit = nf_core/*-template/* | ||
source = nf_core | ||
relative_files = True | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,17 @@ | ||
{ | ||
$schema: "https://docs.renovatebot.com/renovate-schema.json", | ||
extends: ["github>nf-core/ops//.github/renovate/default.json5"], | ||
ignorePaths: ["**/nf_core/pipeline-template/modules/nf-core/**"], | ||
baseBranches: ["dev"], | ||
packageRules: [ | ||
{ | ||
matchDatasources: ["docker"], | ||
matchPackageNames: ["python"], | ||
versioning: "pep440", | ||
}, | ||
{ | ||
matchDatasources: ["docker"], | ||
registryUrls: ["docker.io"], | ||
}, | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
""" | ||
Taken from https://github.com/MultiQC/MultiQC/blob/main/.github/workflows/changelog.py and updated for nf-core | ||
To be called by a CI action. Assumes the following environment variables are set: | ||
PR_TITLE, PR_NUMBER, GITHUB_WORKSPACE. | ||
Adds a line into the CHANGELOG.md: | ||
* Looks for the section to add the line to, based on the PR title, e.g. `Template:`, `Modules:`. | ||
* All other change will go under the "### General" section. | ||
* If an entry for the PR is already added, it will not run. | ||
Other assumptions: | ||
- CHANGELOG.md has a running section for an ongoing "dev" version | ||
(i.e. titled "## nf-core vX.Ydev"). | ||
""" | ||
|
||
import os | ||
import re | ||
import sys | ||
from pathlib import Path | ||
from typing import List | ||
|
||
REPO_URL = "https://github.com/nf-core/tools" | ||
|
||
# Assumes the environment is set by the GitHub action. | ||
pr_title = os.environ["PR_TITLE"] | ||
pr_number = os.environ["PR_NUMBER"] | ||
comment = os.environ.get("COMMENT", "") | ||
workspace_path = Path(os.environ.get("GITHUB_WORKSPACE", "")) | ||
|
||
assert pr_title, pr_title | ||
assert pr_number, pr_number | ||
|
||
# Trim the PR number added when GitHub squashes commits, e.g. "Template: Updated (#2026)" | ||
pr_title = pr_title.removesuffix(f" (#{pr_number})") | ||
|
||
changelog_path = workspace_path / "CHANGELOG.md" | ||
|
||
if any( | ||
line in pr_title.lower() | ||
for line in [ | ||
"skip changelog", | ||
"skip change log", | ||
"no changelog", | ||
"no change log", | ||
"bump version", | ||
] | ||
): | ||
print("Skipping changelog update") | ||
sys.exit(0) | ||
|
||
|
||
def _determine_change_type(pr_title) -> tuple[str, str]: | ||
""" | ||
Determine the type of the PR: Template, Download, Linting, Modules, Subworkflows, or General | ||
Returns a tuple of the section name and the module info. | ||
""" | ||
sections = { | ||
"Template": "### Template", | ||
"Download": "### Download", | ||
"Linting": "### Linting", | ||
"Modules": "### Modules", | ||
"Subworkflows": "### Subworkflows", | ||
} | ||
current_section_header = "### General" | ||
current_section = "General" | ||
|
||
# Check if the PR in any of the sections. | ||
for section, section_header in sections.items(): | ||
# check if the PR title contains any of the section headers, with some loose matching, e.g. removing plural and suffixes | ||
if re.sub(r"s$", "", section.lower().replace("ing", "")) in pr_title.lower(): | ||
current_section_header = section_header | ||
current_section = section | ||
print(f"Detected section: {current_section}") | ||
return current_section, current_section_header | ||
|
||
|
||
# Determine the type of the PR | ||
section, section_header = _determine_change_type(pr_title) | ||
|
||
# Remove section indicator from the PR title. | ||
pr_title = re.sub(rf"{section}[:\s]*", "", pr_title, flags=re.IGNORECASE) | ||
|
||
# Prepare the change log entry. | ||
pr_link = f"([#{pr_number}]({REPO_URL}/pull/{pr_number}))" | ||
|
||
# Handle manual changelog entries through comments. | ||
if comment := comment.removeprefix("@nf-core-bot changelog").strip(): | ||
print(f"Adding manual changelog entry: {comment}") | ||
pr_title = comment | ||
new_lines = [ | ||
f"- {pr_title} {pr_link}\n", | ||
] | ||
|
||
print(f"Adding new lines into section '{section}':\n" + "".join(new_lines)) | ||
|
||
# Finally, updating the changelog. | ||
# Read the current changelog lines. We will print them back as is, except for one new | ||
# entry, corresponding to this new PR. | ||
with changelog_path.open("r") as f: | ||
orig_lines = f.readlines() | ||
updated_lines: List[str] = [] | ||
|
||
|
||
def _skip_existing_entry_for_this_pr(line: str, same_section: bool = True) -> str: | ||
if line.strip().endswith(pr_link): | ||
print(f"Found existing entry for this pull request #{pr_number}:") | ||
existing_lines = [line] | ||
if new_lines and new_lines == existing_lines and same_section: | ||
print(f"Found existing identical entry for this pull request #{pr_number} in the same section:") | ||
print("".join(existing_lines)) | ||
sys.exit(0) # Just leaving the CHANGELOG intact | ||
else: | ||
print( | ||
f"Found existing entry for this pull request #{pr_number}. It will be replaced and/or moved to proper section" | ||
) | ||
print("".join(existing_lines)) | ||
for _ in range(len(existing_lines)): | ||
try: | ||
line = orig_lines.pop(0) | ||
except IndexError: | ||
break | ||
return line | ||
|
||
|
||
# Find the next line in the change log that matches the pattern "# nf-core/tools v.*dev" | ||
# If it doesn't exist, exist with code 1 (let's assume that a new section is added | ||
# manually or by CI when a release is pushed). | ||
# Else, find the next line that matches the `section` variable, and insert a new line | ||
# under it (we also assume that section headers are added already). | ||
inside_version_dev = False | ||
already_added_entry = False | ||
while orig_lines: | ||
line = orig_lines.pop(0) | ||
|
||
# If the line already contains a link to the PR, don't add it again. | ||
line = _skip_existing_entry_for_this_pr(line, same_section=False) | ||
|
||
if line.startswith("# ") and not line.strip() == "# nf-core/tools: Changelog": # Version header, e.g. "# v2.12dev" | ||
print(f"Found version header: {line.strip()}") | ||
updated_lines.append(line) | ||
|
||
# Parse version from the line `# v2.12dev` or | ||
# `# [v2.11.1 - Magnesium Dragon Patch](https://github.com/nf-core/tools/releases/tag/2.11) - [2023-12-20]` ... | ||
if not (m := re.match(r".*(v\d+\.\d+(dev)?).*", line)): | ||
print(f"Cannot parse version from line {line.strip()}.", file=sys.stderr) | ||
sys.exit(1) | ||
version = m.group(1) | ||
|
||
if not inside_version_dev: | ||
if not version.endswith("dev"): | ||
print( | ||
"Can't find a 'dev' version section in the changelog. Make sure " | ||
"it's created, and all the required sections, e.g. `### Template` are created under it .", | ||
file=sys.stderr, | ||
) | ||
sys.exit(1) | ||
inside_version_dev = True | ||
else: | ||
if version.endswith("dev"): | ||
print( | ||
f"Found another 'dev' version section in the changelog, make" | ||
f"sure to change it to a 'release' stable version tag. " | ||
f"Line: {line.strip()}", | ||
file=sys.stderr, | ||
) | ||
sys.exit(1) | ||
# We are past the dev version, so just add back the rest of the lines and break. | ||
while orig_lines: | ||
line = orig_lines.pop(0) | ||
line = _skip_existing_entry_for_this_pr(line, same_section=False) | ||
if line: | ||
updated_lines.append(line) | ||
break | ||
continue | ||
print(f"Found line: {line.strip()}") | ||
print(f"inside_version_dev: {inside_version_dev}") | ||
print(f"section_header: {section_header}") | ||
if inside_version_dev and line.lower().startswith(section_header.lower()): # Section of interest header | ||
print(f"Found section header: {line.strip()}") | ||
if already_added_entry: | ||
print( | ||
f"Already added new lines into section {section}, is the section duplicated?", | ||
file=sys.stderr, | ||
) | ||
sys.exit(1) | ||
updated_lines.append(line) | ||
# Collecting lines until the next section. | ||
section_lines: List[str] = [] | ||
while True: | ||
line = orig_lines.pop(0) | ||
if line.startswith("#"): | ||
print(f"Found the next section header: {line.strip()}") | ||
# Found the next section header, so need to put all the lines we collected. | ||
updated_lines.append("\n") | ||
_updated_lines = [_l for _l in section_lines + new_lines if _l.strip()] | ||
updated_lines.extend(_updated_lines) | ||
updated_lines.append("\n") | ||
if new_lines: | ||
print(f"Updated {changelog_path} section '{section}' with lines:\n" + "".join(new_lines)) | ||
else: | ||
print(f"Removed existing entry from {changelog_path} section '{section}'") | ||
already_added_entry = True | ||
# Pushing back the next section header line | ||
orig_lines.insert(0, line) | ||
break | ||
# If the line already contains a link to the PR, don't add it again. | ||
line = _skip_existing_entry_for_this_pr(line, same_section=True) | ||
section_lines.append(line) | ||
else: | ||
updated_lines.append(line) | ||
|
||
|
||
def collapse_newlines(lines: List[str]) -> List[str]: | ||
updated = [] | ||
for idx in range(len(lines)): | ||
if idx != 0 and not lines[idx].strip() and not lines[idx - 1].strip(): | ||
continue | ||
updated.append(lines[idx]) | ||
return updated | ||
|
||
|
||
updated_lines = collapse_newlines(updated_lines) | ||
|
||
|
||
# Finally, writing the updated lines back. | ||
with changelog_path.open("w") as f: | ||
f.writelines(updated_lines) |
Oops, something went wrong.