diff --git a/gitlab_release_notes/generate.py b/gitlab_release_notes/generate.py
index 9d7795b..ead1be5 100644
--- a/gitlab_release_notes/generate.py
+++ b/gitlab_release_notes/generate.py
@@ -4,98 +4,125 @@
import sys
from .version import __version__
-def generate_release_notes(project_id, endstr = '
', since=None, quiet=False, target_branch=None, **config):
+def generate_release_notes(project_id, endstr='
', since=None, target_branch=None, **config):
"""
- Generate the release notes of a gitlab project from the last release
+ Generate the release notes of a gitlab project.
Parameters
----------
project_id: int
ID of the project
+ endstr: str
+ String to use for line endings (e.g., '
' for HTML, '\n' for plain text)
+ since: Optional[str]
+ A date string (YYYY-MM-DDTHH:MM:SSZ) or a tag/reference.
+ If provided, release notes will be generated for MRs merged after this point.
+ Overrides fetching MRs since the last release.
+ target_branch: Optional[str]
+ The target branch to filter merge requests by.
config: dict
+ Additional keyword arguments for the gitlab.Gitlab client, such as:
url: Optional[str] = None,
private_token: Optional[str] = None,
- oauth_token: Optional[str] = None,
- job_token: Optional[str] = None,
- ssl_verify: Union[bool, str] = True,
- http_username: Optional[str] = None,
- http_password: Optional[str] = None,
- timeout: Optional[float] = None,
- api_version: str = '4',
- session: Optional[requests.sessions.Session] = None,
- per_page: Optional[int] = None,
- pagination: Optional[str] = None,
- order_by: Optional[str] = None,
- user_agent: str = 'python-gitlab/3.1.0',
- retry_transient_errors: bool = False,
+ # ... (other gitlab.Gitlab config options)
"""
gl = gitlab.Gitlab(**config)
project = gl.projects.get(project_id)
- if not project.mergerequests.list(get_all=False,state='merged', target_branch=target_branch):
- raise ValueError(f"There is no merged merge request for project {project_id} {project.name}")
-
- log = ""
+ # Initial check for any merged MRs (can be refined if needed)
+ # This check doesn't use target_branch yet, it's a general check.
+ # Consider if this check should also incorporate target_branch if provided.
+ # For now, keeping it as is.
+ initial_mr_check_params = {'state': 'merged', 'per_page': 1}
+ if target_branch: # Optionally make the initial check more specific
+ initial_mr_check_params['target_branch'] = target_branch
+
+ if not project.mergerequests.list(get_all=False, **initial_mr_check_params):
+ error_message = f"There are no merged merge requests for project {project_id} ({project.name})"
+ if target_branch:
+ error_message += f" on branch '{target_branch}'"
+ raise ValueError(error_message)
if since:
- log_pending = f"Changelog of {project.name} since {since}:{endstr}"
- last_date = since
- elif not project.releases.list(get_all=False):
- log_pending = f"Changelog of {project.name}:{endstr}"
- last_date = '0000-01-01T00:00:00Z'
+ log = f"Changelog of {project.name}"
+ if target_branch:
+ log += f" for branch '{target_branch}'"
+ log += f" since {since}:{endstr}"
+ last_date = since # Assuming 'since' is a date string 'YYYY-MM-DDTHH:MM:SSZ'
+ # If 'since' can be a tag, you'd need to resolve its date
else:
- last_release = project.releases.list(get_all=False)[0]
- log_pending = f"Changelog since release {last_release.name} of {project.name}:{endstr}"
- last_date = last_release.released_at
+ releases = project.releases.list()
+ if not releases:
+ log = f"Changelog of {project.name}"
+ if target_branch:
+ log += f" for branch '{target_branch}'"
+ log += f":{endstr}"
+ last_date = '0000-01-01T00:00:00Z'
+ else:
+ last_release = releases[0]
+ log = f"Changelog since release {last_release.name} of {project.name}"
+ if target_branch:
+ log += f" for branch '{target_branch}'"
+ log += f":{endstr}"
+ last_date = last_release.released_at
page = 1
- list_mrs = project.mergerequests.list(state='merged',
- get_all=False,
- order_by='updated_at',
- updated_after=last_date,
- target_branch=target_branch,
- page=page)
- if not list_mrs:
- if not quiet:
- log += log_pending
- log += f"There is no merged merge request after {last_date}{endstr}"
- return log
-
- log += log_pending
+ list_mrs_params = {
+ 'state': 'merged',
+ 'order_by': 'updated_at',
+ 'updated_after': last_date,
+ # 'scope': 'all' # Ensure we get MRs the user has access to, default is 'created_by_me' or 'assigned_to_me'
+ # The python-gitlab default for list() is all MRs the user can view.
+ }
+ if target_branch:
+ list_mrs_params['target_branch'] = target_branch
+
+ # Fetch the first page
+ list_mrs = project.mergerequests.list(page=page, get_all=False, **list_mrs_params)
+
+ found_mrs = False
while list_mrs:
+ found_mrs = True
for mr in list_mrs:
line = f" * {mr.title} (@{mr.author['username']}){endstr}"
log += line
page += 1
- list_mrs = project.mergerequests.list(state='merged',
- get_all=False,
- order_by='updated_at',
- updated_after=last_date,
- target_branch=target_branch,
- page=page
- )
+ list_mrs = project.mergerequests.list(page=page, get_all=False, **list_mrs_params)
+
+ if not found_mrs:
+ no_mrs_message = "There is no new merged merge request"
+ if target_branch:
+ no_mrs_message += f" for branch '{target_branch}'"
+ if since:
+ no_mrs_message += f" since {since}."
+ else:
+ no_mrs_message += f" after {last_date}."
+ log += no_mrs_message
+ return log
return log
def main():
import argparse
- parser = argparse.ArgumentParser(os.path.basename(sys.argv[0]),
- description="Generate release notes for a gitlab repository \
- based on merge requests titles since last release")
+ parser = argparse.ArgumentParser("Generate release notes for a gitlab repository \
+ based on merge requests titles since last release")
# Required
parser.add_argument("project_id", type=int)
# Optional
- parser.add_argument("--url", default="https://gitlab.com", required=False)
- parser.add_argument("--private_token", type=str, required=False, default=None)
- parser.add_argument('--version', action='version', version=__version__)
- parser.add_argument('--html', action='store_true')
- parser.add_argument('--since', type=datetime.date.fromisoformat, required=False, default=None)
- parser.add_argument('--target_branch', type=str, required=False, default=None)
- parser.add_argument('--quiet', action='store_true')
+ parser.add_argument("--url", default="https://gitlab.com", required=False, help="GitLab base URL, e.g., https://gitlab.com")
+ parser.add_argument("--private_token", type=str, required=False, default=None, help="GitLab private token")
+ parser.add_argument('--version', action='version', version=__version__, help="Show the version and exit")
+ parser.add_argument('--html', action='store_true', help="Generate HTML output")
+ # Add CLI arguments for since and target_branch if you want to use them from CLI
+ parser.add_argument("--since", type=str, required=False, default=None,
+ help="Generate notes since this date (YYYY-MM-DDTHH:MM:SSZ) or tag.")
+ parser.add_argument("--target_branch", type=str, required=False, default=None,
+ help="Filter merge requests by target branch.")
+
args = parser.parse_args()
@@ -103,16 +130,18 @@ def main():
endstr = '
'
else:
endstr = '\n'
- notes = generate_release_notes(args.project_id,
- url=args.url,
- endstr=endstr,
- since=args.since,
- target_branch=args.target_branch,
- quiet=args.quiet,
- private_token=args.private_token,
- )
- if notes:
- print(notes)
+
+ # Pass since and target_branch to generate_release_notes
+ notes = generate_release_notes(
+ args.project_id,
+ url=args.url,
+ endstr=endstr,
+ private_token=args.private_token,
+ since=args.since,
+ target_branch=args.target_branch
+ )
+ print(notes)
+
if __name__ == "__main__":
main()