|
1 | 1 | import subprocess |
2 | 2 | import re |
3 | 3 | import argparse |
| 4 | +import sys |
4 | 5 |
|
5 | | -def get_git_log(tag): |
6 | | - # try to find previous tag; fall back to the second-latest tag if needed |
| 6 | +def run_cmd(cmd): |
| 7 | + """Run shell command and return stdout as string.""" |
7 | 8 | try: |
8 | | - prev_tag = subprocess.check_output( |
9 | | - "git tag --sort=-creatordate", shell=True, text=True |
10 | | - ).strip().split("\n") |
11 | | - # take the tag immediately before the given one |
12 | | - if tag in prev_tag: |
13 | | - idx = prev_tag.index(tag) |
14 | | - previous = prev_tag[idx + 1] if idx + 1 < len(prev_tag) else None |
15 | | - else: |
16 | | - previous = prev_tag[1] if len(prev_tag) > 1 else None |
17 | | - except Exception: |
18 | | - previous = None |
| 9 | + return subprocess.check_output(cmd, shell=True, text=True, encoding="utf-8", errors="ignore").strip() |
| 10 | + except subprocess.CalledProcessError as e: |
| 11 | + return "" |
| 12 | + |
| 13 | +def get_latest_tag(): |
| 14 | + tags = run_cmd("git tag --sort=-creatordate").split("\n") |
| 15 | + return tags[0] if tags and tags[0] else None |
| 16 | + |
| 17 | +def branch_exists(branch): |
| 18 | + result = run_cmd(f"git rev-parse --verify {branch}") |
| 19 | + return bool(result) |
| 20 | + |
| 21 | +def tag_exists(tag): |
| 22 | + result = run_cmd(f"git rev-parse --verify refs/tags/{tag}") |
| 23 | + return bool(result) |
19 | 24 |
|
20 | | - format_str = "%h||%s||%an" |
21 | | - if previous: |
22 | | - cmd = f'git log {previous}..{tag} --pretty=format:"{format_str}"' |
| 25 | +def get_git_log(tag): |
| 26 | + """Generate git log range depending on tag availability.""" |
| 27 | + tags = [t for t in run_cmd("git tag --sort=-creatordate").split("\n") if t] |
| 28 | + latest_tag = tags[0] if tags else None |
| 29 | + |
| 30 | + if tag_exists(tag): |
| 31 | + # Tag exists: find the one before it |
| 32 | + if tag in tags: |
| 33 | + idx = tags.index(tag) |
| 34 | + previous = tags[idx + 1] if idx + 1 < len(tags) else None |
| 35 | + else: |
| 36 | + previous = tags[1] if len(tags) > 1 else None |
| 37 | + cmd = f'git log {previous}..{tag} --pretty=format:"%h||%s||%an"' if previous else f'git log {tag} --pretty=format:"%h||%s||%an" -n 50' |
23 | 38 | else: |
24 | | - # fallback: just commits reachable from tag |
25 | | - cmd = f'git log {tag} --pretty=format:"{format_str}" -n 50' |
| 39 | + # Tag does not exist -> generate diff between latest tag and main |
| 40 | + print(f"[WARN] Tag '{tag}' not found, generating changelog between latest tag '{latest_tag}' and 'main'") |
| 41 | + if not latest_tag: |
| 42 | + cmd = f'git log main --pretty=format:"%h||%s||%an" -n 50' |
| 43 | + else: |
| 44 | + cmd = f'git log {latest_tag}..main --pretty=format:"%h||%s||%an"' |
26 | 45 |
|
27 | 46 | print(f"[DEBUG] Running: {cmd}") |
28 | | - output = subprocess.check_output(cmd, shell=True, text=True, encoding="utf-8", errors="ignore") |
| 47 | + output = run_cmd(cmd) |
29 | 48 | return [line.strip() for line in output.split("\n") if line.strip()] |
30 | 49 |
|
31 | 50 | def extract_pr_info(message): |
32 | 51 | pr_match = re.search(r"(?:#|PR\s*)(\d+)", message) |
33 | 52 | pr_number = pr_match.group(1) if pr_match else None |
34 | | - # Strip out PR refs and noise |
35 | 53 | clean = re.sub(r"\(?#\d+\)?|Merge pull request.*|from.*|PR\s*\d+", "", message) |
36 | 54 | clean = clean.strip().capitalize() |
37 | 55 | return clean, pr_number |
|
0 commit comments