10
10
$/LicenseInfo$
11
11
"""
12
12
13
- import contextlib
13
+ import os
14
14
import re
15
15
import subprocess
16
16
import sys
@@ -22,7 +22,7 @@ class Error(Exception):
22
22
pass
23
23
24
24
25
- def branches_for (token , commit , repo = None ):
25
+ def branches_for (repo , commit ):
26
26
"""
27
27
Use the GitHub REST API to discover which branch(es) correspond to the
28
28
passed commit hash. The commit string can actually be any of the ways git
@@ -32,21 +32,10 @@ def branches_for(token, commit, repo=None):
32
32
33
33
branches_for() generates a (possibly empty) sequence of all the branches
34
34
of the specified repo for which the specified commit is the tip.
35
-
36
- If repo is omitted or None, assume the current directory is a local clone
37
- whose 'origin' remote is the GitHub repository of interest.
38
35
"""
39
- if not repo :
40
- url = subprocess .check_output (['git' , 'remote' , 'get-url' , 'origin' ],
41
- text = True )
42
- parts = re .split (r'[:/]' , url .rstrip ())
43
- repo = '/' .join (parts [- 2 :]).removesuffix ('.git' )
44
-
45
- gh = github .MainClass .Github (token )
46
- grepo = gh .get_repo (repo )
47
- for branch in grepo .get_branches ():
36
+ for branch in repo .get_branches ():
48
37
try :
49
- delta = grepo .compare (base = commit , head = branch .name )
38
+ delta = repo .compare (base = commit , head = branch .name )
50
39
except github .GithubException :
51
40
continue
52
41
@@ -70,10 +59,59 @@ def main(*raw_args):
70
59
help = """GitHub repository name, in the form OWNER/REPOSITORY""" )
71
60
parser .add_argument ('commit' ,
72
61
help = """commit hash at the tip of the sought branch""" )
73
-
74
62
args = parser .parse_args (raw_args )
75
- with contextlib .suppress (StopIteration ):
76
- print (next (iter (branches_for (token = args .token , commit = args .commit , repo = args .repo ))).name )
63
+
64
+ # If repo is omitted or None, assume the current directory is a local clone
65
+ # whose 'origin' remote is the GitHub repository of interest.
66
+ if not args .repo :
67
+ url = subprocess .check_output (['git' , 'remote' , 'get-url' , 'origin' ],
68
+ text = True )
69
+ parts = re .split (r'[:/]' , url .rstrip ())
70
+ args .repo = '/' .join (parts [- 2 :]).removesuffix ('.git' )
71
+
72
+ gh = github .MainClass .Github (args .token )
73
+ repo = gh .get_repo (args .repo )
74
+
75
+ try :
76
+ branch = next (iter (branches_for (repo = repo , commit = args .commit ))).name
77
+ except StopIteration :
78
+ return
79
+
80
+ # If we weren't run as a GitHub action (no $GITHUB_OUTPUT), just show user
81
+ # output variables.
82
+ GITHUB_OUTPUT = os .getenv ("GITHUB_OUTPUT" )
83
+ if GITHUB_OUTPUT :
84
+ outf = open (GITHUB_OUTPUT , "a" )
85
+ else :
86
+ outf = sys .stdout
87
+
88
+ print (f"branch={ branch } " , file = outf )
89
+
90
+ # Can we find a pull request corresponding to this branch?
91
+ # (Is there a better way than just searching PRs?)
92
+ # Empirically, although get_pulls(head=branch) would seem to do exactly
93
+ # what we want, we always end up with a list of all open PRs anyway.
94
+ try :
95
+ pr = next (pr for pr in repo .get_pulls (head = branch ) if pr .head .ref == branch )
96
+ except StopIteration :
97
+ return
98
+
99
+ # pr.body is the PR's description. Look for a line embedded in that
100
+ # description containing only 'relnotes:'.
101
+ lines = iter (pr .body .splitlines ())
102
+ try :
103
+ next (line for line in lines if line .strip () == 'relnotes:' )
104
+ except StopIteration :
105
+ return
106
+
107
+ # Having found that line, the rest of the body is the release notes
108
+ # header.
109
+ outf .writelines ((
110
+ 'relnotes<<EOF\n ' ,
111
+ '\n ' .join (lines ),
112
+ '\n ' ,
113
+ 'EOF\n '
114
+ ))
77
115
78
116
79
117
if __name__ == "__main__" :
0 commit comments