1
0
Fork 0
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:
Lukas Winkler 2019-02-03 16:33:44 +01:00
parent cd91b229ea
commit 38dfbc9ec5
11 changed files with 118 additions and 59 deletions

View file

@ -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

View file

@ -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:

View file

@ -4,6 +4,6 @@ from generator import generate_changelog
def main():
since = datetime.today() - timedelta(10)
since = datetime.today() - timedelta(5)
generate_changelog(since)

View file

@ -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:

View file

@ -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

View file

@ -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 ""

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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
View 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