Skip to content

Commit ddf6b09

Browse files
Merge pull request #8 from secondlife/which-branch
Add which-branch action so tag builds can identify corresponding branch.
2 parents 5c68b68 + 6220d58 commit ddf6b09

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ would require a full viewer rebuild before retrying the failing operation.
1919
[sign-pkg-mac](sign-pkg-mac/README.md)
2020

2121
[sign-pkg-windows](sign-pkg-windows/README.md)
22+
23+
[which-branch](which-branch/README.md)

which-branch/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## which-branch
2+
3+
Discover and report which repository branch corresponds to `github.repository`'s `github.sha`.
4+
5+
This is necessary for a release action because release actions are driven by a tag, which means that `github.ref_name` reports the tag rather than the corresponding branch.
6+
7+
| Input | Description |
8+
| ----- | ----------- |
9+
| token | GitHub Personal Access Token with which to query the REST API |
10+
11+
| Output | Description |
12+
| ------ | ----------- |
13+
| branch | name of the branch whose tip is `github.sha`, or empty string |
14+

which-branch/action.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: which-branch
2+
description:
3+
"Discover and report which repository branch corresponds to `github.repository`'s `github.sha`."
4+
5+
inputs:
6+
token:
7+
description: "GitHub Personal Access Token with which to query the REST API"
8+
required: true
9+
10+
outputs:
11+
branch:
12+
description: "Branch whose tip is used for this build"
13+
value: ${{ steps.which-branch.outputs.branch }}
14+
15+
runs:
16+
using: composite
17+
steps:
18+
- name: Install Python dependencies
19+
shell: bash
20+
run: pip3 install PyGithub
21+
22+
- name: Determine which branch
23+
id: which-branch
24+
shell: bash
25+
run: |
26+
branch="$(python '${{ github.action_path }}/which_branch.py' \
27+
-t "${{ inputs.token }}" -r "${{github.repository }}" "${{ github.sha }}")"
28+
echo "branch=$branch" >> "$GITHUB_OUTPUT"

which-branch/which_branch.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env python3
2+
"""\
3+
@file which_branch.py
4+
@author Nat Goodspeed
5+
@date 2023-11-14
6+
@brief Discover which git branch(es) correspond to a given commit hash.
7+
8+
$LicenseInfo:firstyear=2023&license=viewerlgpl$
9+
Copyright (c) 2023, Linden Research, Inc.
10+
$/LicenseInfo$
11+
"""
12+
13+
import contextlib
14+
import re
15+
import subprocess
16+
import sys
17+
18+
import github
19+
20+
21+
class Error(Exception):
22+
pass
23+
24+
25+
def branches_for(token, commit, repo=None):
26+
"""
27+
Use the GitHub REST API to discover which branch(es) correspond to the
28+
passed commit hash. The commit string can actually be any of the ways git
29+
permits to identify a commit:
30+
31+
https://git-scm.com/docs/gitrevisions#_specifying_revisions
32+
33+
branches_for() generates a (possibly empty) sequence of all the branches
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+
"""
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():
48+
try:
49+
delta = grepo.compare(base=commit, head=branch.name)
50+
except github.GithubException:
51+
continue
52+
53+
if delta.ahead_by == 0 and delta.behind_by == 0:
54+
yield branch
55+
56+
57+
def main(*raw_args):
58+
from argparse import ArgumentParser
59+
parser = ArgumentParser(description= # noqa: E251
60+
"%(prog)s reports the branch(es) for which the specified commit hash is the tip.", # noqa: E128
61+
epilog="""\
62+
When GitHub Actions launches a tag build, it checks out the specific changeset
63+
identified by the tag, and so 'git branch' reports detached HEAD. But we use
64+
tag builds to build a GitHub 'release' of the tip of a particular branch, and
65+
it's useful to be able to identify which branch that is.
66+
""")
67+
parser.add_argument('-t', '--token', required=True,
68+
help="""GitHub REST API access token""")
69+
parser.add_argument('-r', '--repo',
70+
help="""GitHub repository name, in the form OWNER/REPOSITORY""")
71+
parser.add_argument('commit',
72+
help="""commit hash at the tip of the sought branch""")
73+
74+
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)
77+
78+
79+
if __name__ == "__main__":
80+
try:
81+
sys.exit(main(*sys.argv[1:]))
82+
except Error as err:
83+
sys.exit(str(err))

0 commit comments

Comments
 (0)