mirror of
https://github.com/Findus23/new-github-changelog-generator.git
synced 2024-08-27 19:52:18 +02:00
support multiple repositories
This commit is contained in:
parent
cd91b229ea
commit
38dfbc9ec5
11 changed files with 118 additions and 59 deletions
|
@ -2,5 +2,6 @@ from .author import Author
|
|||
from .event import Event
|
||||
from .config import config
|
||||
from .issue import Issue
|
||||
from .repo import Repo
|
||||
from .api import GithubAPI
|
||||
from .generator import generate_changelog
|
|
@ -17,6 +17,7 @@ class GithubAPI:
|
|||
self.s.headers.update({'Authorization': 'token {}'.format(token)})
|
||||
else:
|
||||
warn("use Token!", stacklevel=2) # TODO
|
||||
self.s.headers.update({'User-Agent': 'github-changelog-generator'})
|
||||
|
||||
def call(self, url, parameters=None):
|
||||
if "//" not in url:
|
||||
|
|
|
@ -4,6 +4,6 @@ from generator import generate_changelog
|
|||
|
||||
|
||||
def main():
|
||||
since = datetime.today() - timedelta(10)
|
||||
since = datetime.today() - timedelta(5)
|
||||
|
||||
generate_changelog(since)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os.path
|
||||
import sys
|
||||
|
||||
import pkg_resources
|
||||
import yaml
|
||||
|
@ -9,13 +10,17 @@ class Config:
|
|||
|
||||
def __init__(self):
|
||||
with open(self.get_config_path(), 'r') as stream:
|
||||
config = yaml.safe_load(stream)
|
||||
self.api_token = config["api_token"] # type:str
|
||||
self.labels_to_ignore = set(config["labels_to_ignore"])
|
||||
self.sort_by_labels = config["sort_by_labels"]
|
||||
self.is_matomo = config["is_matomo"] # type:bool
|
||||
if self.is_matomo:
|
||||
self.compare_config()
|
||||
try:
|
||||
config = yaml.safe_load(stream)
|
||||
self.api_token = config["api_token"] # type:str
|
||||
self.labels_to_ignore = set(config["labels_to_ignore"])
|
||||
self.sort_by_labels = config["sort_by_labels"] # type:list
|
||||
self.repositories = config["repositories"] # type:list
|
||||
self.is_matomo = config["is_matomo"] # type:bool
|
||||
if self.is_matomo:
|
||||
self.compare_config()
|
||||
except KeyError as e:
|
||||
sys.exit("required option '{}' is missing from the config".format(e.args[0]))
|
||||
|
||||
def get_config_path(self) -> str:
|
||||
for path in self.config_paths:
|
||||
|
|
|
@ -1,4 +1,19 @@
|
|||
api_token: null
|
||||
repositories:
|
||||
- matomo-org/matomo
|
||||
- matomo-org/tag-manager
|
||||
- matomo-org/matomo-log-analytics
|
||||
- matomo-org/matomo-php-tracker
|
||||
- matomo-org/referrer-spam-blacklist
|
||||
- matomo-org/tracker-proxy
|
||||
- matomo-org/device-detector
|
||||
- matomo-org/searchengine-and-social-list
|
||||
- matomo-org/component-network
|
||||
- matomo-org/component-ini
|
||||
- matomo-org/component-decompress
|
||||
- matomo-org/component-cache
|
||||
- matomo-org/matomo-package
|
||||
- matomo-org/matomo-icons
|
||||
labels_to_ignore:
|
||||
- wontfix
|
||||
- not-in-changelog
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from typing import List
|
||||
|
||||
from generator import Issue
|
||||
from generator import Repo
|
||||
|
||||
|
||||
class BaseFormatter:
|
||||
def __init__(self, issues: List[Issue]):
|
||||
self.issues = issues
|
||||
def __init__(self, repos: List[Repo]):
|
||||
self.repos = repos
|
||||
|
||||
def __str__(self) -> str:
|
||||
return ""
|
||||
|
|
|
@ -7,21 +7,26 @@ class HTMLFormatter(BaseFormatter):
|
|||
|
||||
def __str__(self) -> str:
|
||||
text = "<div>\n"
|
||||
for issue in self.issues:
|
||||
text += "\t<li><a href='{url}'>#{id}</a> {title}</li>".format(
|
||||
url=issue.url,
|
||||
id=issue.number,
|
||||
title=html.escape(issue.title)
|
||||
)
|
||||
if issue.authors:
|
||||
text += " [by {}]".format(
|
||||
", ".join(
|
||||
"<a href='{url}'>@{name}</a>".format(
|
||||
url=author.profile_url,
|
||||
name=html.escape(author.username)
|
||||
) for author in issue.authors
|
||||
for repo in self.repos:
|
||||
if repo.issues:
|
||||
text += "<h3><a href='{}'>{}</a></h3>\n".format(repo.absolute_url, repo.path)
|
||||
text += "<ul>\n"
|
||||
for issue in repo.issues:
|
||||
text += "\t<li><a href='{url}'>#{id}</a> {title}".format(
|
||||
url=issue.url,
|
||||
id=issue.number,
|
||||
title=html.escape(issue.title)
|
||||
)
|
||||
)
|
||||
text += "\n"
|
||||
if issue.authors:
|
||||
text += " [by {}]".format(
|
||||
", ".join(
|
||||
"<a href='{url}'>@{name}</a>".format(
|
||||
url=author.profile_url,
|
||||
name=html.escape(author.username)
|
||||
) for author in issue.authors
|
||||
)
|
||||
)
|
||||
text += "</li>\n"
|
||||
text += "</ul>"
|
||||
text += "</div>"
|
||||
return text
|
||||
|
|
|
@ -7,20 +7,23 @@ class MarkdownFormatter(BaseFormatter):
|
|||
|
||||
def __str__(self) -> str:
|
||||
text = ""
|
||||
for issue in self.issues:
|
||||
text += "\t- [#{id}]({url}) {title}".format(
|
||||
url=issue.url,
|
||||
id=issue.number,
|
||||
title=html.escape(issue.title)
|
||||
)
|
||||
if issue.authors:
|
||||
text += " [by {}]".format(
|
||||
", ".join(
|
||||
"[@{name}]({url})".format(
|
||||
url=author.profile_url,
|
||||
name=html.escape(author.username)
|
||||
) for author in issue.authors
|
||||
for repo in self.repos:
|
||||
if repo.issues:
|
||||
text += "### [{}]({})\n".format(repo.path, repo.absolute_url)
|
||||
for issue in repo.issues:
|
||||
text += " - [#{id}]({url}) {title}".format(
|
||||
url=issue.url,
|
||||
id=issue.number,
|
||||
title=html.escape(issue.title)
|
||||
)
|
||||
)
|
||||
text += "\n"
|
||||
if issue.authors:
|
||||
text += " [by {}]".format(
|
||||
", ".join(
|
||||
"[@{name}]({url})".format(
|
||||
url=author.profile_url,
|
||||
name=html.escape(author.username)
|
||||
) for author in issue.authors
|
||||
)
|
||||
)
|
||||
text += "\n"
|
||||
return text
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
from generator import GithubAPI, config, Issue
|
||||
from generator.formatters import MarkdownFormatter
|
||||
from generator import GithubAPI, config, Issue, Repo
|
||||
from generator.formatters import HTMLFormatter, MarkdownFormatter
|
||||
|
||||
api = GithubAPI(token=config.api_token)
|
||||
|
||||
|
@ -14,18 +15,35 @@ def getissueorder(issue: Issue):
|
|||
return order, issue.number
|
||||
|
||||
|
||||
def generate_changelog(since: datetime):
|
||||
issues = api.fetch_issues_since("matomo-org/matomo", since)
|
||||
issues = list(issues) # enumerate iterable
|
||||
for issue in issues:
|
||||
if issue.pull_request:
|
||||
issue.add_pr_data(api.fetch_pr_details(issue))
|
||||
issue.compare_close_date(since)
|
||||
issues = [i for i in issues if i.should_be_included] # remove all filtered issues
|
||||
for issue in issues:
|
||||
for event in api.fetch_events(issue):
|
||||
if event.author_should_be_listed:
|
||||
issue.authors.add(event.author)
|
||||
def generate_statistics(repos: List[Repo]):
|
||||
unique_authors = set()
|
||||
num_issues = 0
|
||||
for repo in repos:
|
||||
for issue in repo.issues:
|
||||
num_issues += 1
|
||||
unique_authors.update(issue.authors)
|
||||
print("{num} Tickets closed by {contr} contributors".format(num=num_issues, contr=len(unique_authors)))
|
||||
|
||||
issues.sort(key=getissueorder)
|
||||
print(MarkdownFormatter(issues))
|
||||
|
||||
def generate_changelog(since: datetime):
|
||||
repos = []
|
||||
for repo_url in config.repositories:
|
||||
repo = Repo(repo_url)
|
||||
issues = api.fetch_issues_since(repo_url, since)
|
||||
issues = list(issues) # enumerate iterable
|
||||
for issue in issues:
|
||||
if issue.pull_request:
|
||||
issue.add_pr_data(api.fetch_pr_details(issue))
|
||||
issue.compare_close_date(since)
|
||||
issues = [i for i in issues if i.should_be_included] # remove all filtered issues
|
||||
for issue in issues:
|
||||
for event in api.fetch_events(issue):
|
||||
if event.author_should_be_listed:
|
||||
issue.authors.add(event.author)
|
||||
|
||||
issues.sort(key=getissueorder)
|
||||
repo.issues = issues
|
||||
repos.append(repo)
|
||||
|
||||
print(HTMLFormatter(repos))
|
||||
generate_statistics(repos)
|
||||
|
|
|
@ -8,7 +8,7 @@ class Issue():
|
|||
def __init__(self, api):
|
||||
self.number = api["number"] # type:int
|
||||
self.title = api["title"] # type:str
|
||||
self.url = api["url"] # type:str
|
||||
self.url = api["html_url"] # type:str
|
||||
self.labels = [l["name"] for l in api["labels"]] # type:List[str]
|
||||
self.closed_at = datetime.strptime(api["closed_at"], "%Y-%m-%dT%H:%M:%SZ")
|
||||
self.pull_request = "pull_request" in api
|
||||
|
@ -20,7 +20,8 @@ class Issue():
|
|||
self.merged = None # type:bool
|
||||
self.authors = set() # type:set
|
||||
self.creator = Author(api["user"])
|
||||
self.authors.add(self.creator)
|
||||
if self.pull_request:
|
||||
self.authors.add(self.creator)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Issue #{}>".format(self.number)
|
||||
|
|
10
generator/repo.py
Normal file
10
generator/repo.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
class Repo(object):
|
||||
BASE_URL = "https://github.com/"
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.issues = []
|
||||
|
||||
@property
|
||||
def absolute_url(self):
|
||||
return self.BASE_URL + self.path
|
Loading…
Reference in a new issue