Skip to content

Commit 07ab62f

Browse files
Merge pull request #13 from secondlife/relnotes
For a tag build with a PR, make which-branch dig out relnotes.
2 parents 341e75b + b863d3f commit 07ab62f

File tree

3 files changed

+64
-22
lines changed

3 files changed

+64
-22
lines changed

which-branch/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ This is necessary for a release action because release actions are driven by a t
1111
| Output | Description |
1212
| ------ | ----------- |
1313
| branch | name of the branch whose tip is `github.sha`, or empty string |
14-
14+
| relnotes | for a tag build, if the branch has a Pull Request, the release notes from the PR description |

which-branch/action.yaml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ outputs:
1111
branch:
1212
description: "Branch whose tip is used for this build"
1313
value: ${{ steps.which-branch.outputs.branch }}
14+
relnotes:
15+
description: "For a tag build with a PR, PR description after 'relnotes:'"
16+
value: ${{ steps.which-branch.outputs.relnotes }}
1417

1518
runs:
1619
using: composite
@@ -25,10 +28,11 @@ runs:
2528
# For a pull request, GITHUB_HEAD_REF is the branch name.
2629
# For a branch build, GITHUB_REF_NAME is the branch name.
2730
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
31+
echo "branch=$branch" >> "$GITHUB_OUTPUT"
2832
else
2933
# For a tag build, have to discover which branch corresponds.
3034
pip3 install PyGithub
31-
branch="$(python '${{ github.action_path }}/which_branch.py' \
32-
-t "${{ inputs.token }}" -r "${{github.repository }}" "${{ github.sha }}")"
35+
# which_branch.py sets output vars in GITHUB_OUTPUT
36+
python '${{ github.action_path }}/which_branch.py' \
37+
-t "${{ inputs.token }}" -r "${{github.repository }}" "${{ github.sha }}"
3338
fi
34-
echo "branch=$branch" >> "$GITHUB_OUTPUT"

which-branch/which_branch.py

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
$/LicenseInfo$
1111
"""
1212

13-
import contextlib
13+
import os
1414
import re
1515
import subprocess
1616
import sys
@@ -22,7 +22,7 @@ class Error(Exception):
2222
pass
2323

2424

25-
def branches_for(token, commit, repo=None):
25+
def branches_for(repo, commit):
2626
"""
2727
Use the GitHub REST API to discover which branch(es) correspond to the
2828
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):
3232
3333
branches_for() generates a (possibly empty) sequence of all the branches
3434
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.
3835
"""
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():
4837
try:
49-
delta = grepo.compare(base=commit, head=branch.name)
38+
delta = repo.compare(base=commit, head=branch.name)
5039
except github.GithubException:
5140
continue
5241

@@ -70,10 +59,59 @@ def main(*raw_args):
7059
help="""GitHub repository name, in the form OWNER/REPOSITORY""")
7160
parser.add_argument('commit',
7261
help="""commit hash at the tip of the sought branch""")
73-
7462
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+
))
77115

78116

79117
if __name__ == "__main__":

0 commit comments

Comments
 (0)