Skip to content

Commit acbabac

Browse files
committed
include pr title in posted comment
1 parent a18af72 commit acbabac

File tree

4 files changed

+92
-79
lines changed

4 files changed

+92
-79
lines changed

.github/actions/dataconnect-send-notifications/action.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ runs:
3030
python
3131
calculate_github_issue_for_commenting.py
3232
--issue-output-file=github_issue_number.txt
33-
--pr-output-file=github_pr_number.txt
3433
--github-repository='${{ github.repository }}'
3534
--github-ref='${{ github.ref }}'
3635
--github-event-name='${{ github.event_name }}'
@@ -43,8 +42,6 @@ runs:
4342
set -xv
4443
issue="$(cat github_issue_number.txt)"
4544
echo "issue=$issue" >> "$GITHUB_OUTPUT"
46-
pr="$(cat github_pr_number.txt)"
47-
echo "pr=$pr" >> "$GITHUB_OUTPUT"
4845
4946
- name: Post Comment on GitHub Issue
5047
if: steps.issue-id.outputs.issue != ''
@@ -57,12 +54,12 @@ runs:
5754
--github-issue='${{ steps.issue-id.outputs.issue }}'
5855
--github-workflow='${{ github.workflow }}'
5956
--github-repository='${{ github.repository }}'
57+
--github-ref='${{ github.ref }}'
6058
--github-sha='${{ github.sha }}'
6159
--github-repository-html-url='${{ github.event.repository.html_url }}'
6260
--github-run-id='${{ github.run_id }}'
6361
--github-run-number='${{ github.run_number }}'
6462
--github-run-attempt='${{ github.run_attempt }}'
65-
--triggering-pr='${{ steps.issue-id.outputs.pr }}'
6663
)
6764
6865
while read -r line; do

firebase-dataconnect/ci/calculate_github_issue_for_commenting.py

Lines changed: 9 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,117 +15,73 @@
1515
from __future__ import annotations
1616

1717
import argparse
18-
import dataclasses
1918
import logging
2019
import pathlib
2120
import re
22-
import subprocess
2321
import typing
2422

25-
if typing.TYPE_CHECKING:
26-
from collections.abc import Iterable
23+
from util import fetch_pr_info, pr_number_from_github_ref
2724

2825

2926
def main() -> None:
3027
args = parse_args()
3128
logging.basicConfig(format="%(message)s", level=logging.INFO)
3229

33-
calculated_result = calculate_github_issue(
30+
github_issue = calculate_github_issue(
3431
github_event_name=args.github_event_name,
3532
github_issue_for_scheduled_run=args.github_issue_for_scheduled_run,
3633
github_ref=args.github_ref,
3734
github_repository=args.github_repository,
3835
pr_body_github_issue_key=args.pr_body_github_issue_key,
3936
)
4037

41-
github_issue = calculated_result.issue
42-
github_pr = calculated_result.pr
43-
4438
issue_file_text = "" if github_issue is None else str(github_issue)
4539
logging.info("Writing '%s' to %s", issue_file_text, args.issue_output_file)
4640
args.issue_output_file.write_text(issue_file_text, encoding="utf8", errors="replace")
4741

48-
pr_file_text = "" if github_pr is None else str(github_pr)
49-
logging.info("Writing '%s' to %s", pr_file_text, args.pr_output_file)
50-
args.pr_output_file.write_text(pr_file_text, encoding="utf8", errors="replace")
51-
52-
53-
@dataclasses.dataclass(frozen=True)
54-
class CalculatedGitHubIssue:
55-
issue: int | None
56-
pr: int | None
57-
5842

5943
def calculate_github_issue(
6044
github_event_name: str,
6145
github_issue_for_scheduled_run: int,
6246
github_ref: str,
6347
github_repository: str,
6448
pr_body_github_issue_key: str,
65-
) -> CalculatedGitHubIssue:
49+
) -> int | None:
6650
if github_event_name == "schedule":
6751
logging.info(
6852
"GitHub Event name is: %s; using GitHub Issue: %s",
6953
github_event_name,
7054
github_issue_for_scheduled_run,
7155
)
72-
return CalculatedGitHubIssue(
73-
issue=github_issue_for_scheduled_run,
74-
pr=None, # scheduled runs are, by definition, not associated with a PR.
75-
)
56+
return github_issue_for_scheduled_run
7657

7758
logging.info("Extracting PR number from string: %s", github_ref)
7859
pr_number = pr_number_from_github_ref(github_ref)
7960
if pr_number is None:
8061
logging.info("No PR number extracted")
81-
return CalculatedGitHubIssue(None, None)
62+
return None
8263
typing.assert_type(pr_number, int)
8364

8465
logging.info("PR number extracted: %s", pr_number)
8566
logging.info("Loading body text of PR: %s", pr_number)
86-
pr_body_text = load_pr_body(
67+
pr_info = fetch_pr_info(
8768
pr_number=pr_number,
8869
github_repository=github_repository,
8970
)
9071

9172
logging.info("Looking for GitHub Issue key in PR body text: %s=NNNN", pr_body_github_issue_key)
9273
github_issue = github_issue_from_pr_body(
93-
pr_body=pr_body_text,
74+
pr_body=pr_info.body,
9475
issue_key=pr_body_github_issue_key,
9576
)
9677

9778
if github_issue is None:
9879
logging.info("No GitHub Issue key found in PR body")
99-
return CalculatedGitHubIssue(issue=None, pr=pr_number)
80+
return None
10081
typing.assert_type(github_issue, int)
10182

10283
logging.info("Found GitHub Issue key in PR body: %s", github_issue)
103-
return CalculatedGitHubIssue(issue=github_issue, pr=pr_number)
104-
105-
106-
def pr_number_from_github_ref(github_ref: str) -> int | None:
107-
match = re.fullmatch("refs/pull/([0-9]+)/merge", github_ref)
108-
return int(match.group(1)) if match else None
109-
110-
111-
def load_pr_body(pr_number: int, github_repository: str) -> str:
112-
gh_args = log_pr_body_gh_args(pr_number=pr_number, github_repository=github_repository)
113-
gh_args = tuple(gh_args)
114-
logging.info("Running command: %s", subprocess.list2cmdline(gh_args))
115-
return subprocess.check_output(gh_args, encoding="utf8", errors="replace") # noqa: S603
116-
117-
118-
def log_pr_body_gh_args(pr_number: int, github_repository: str) -> Iterable[str]:
119-
yield "gh"
120-
yield "issue"
121-
yield "view"
122-
yield str(pr_number)
123-
yield "--json"
124-
yield "body"
125-
yield "--jq"
126-
yield ".body"
127-
yield "-R"
128-
yield github_repository
84+
return github_issue
12985

13086

13187
def github_issue_from_pr_body(pr_body: str, issue_key: str) -> int | None:
@@ -139,7 +95,6 @@ def github_issue_from_pr_body(pr_body: str, issue_key: str) -> int | None:
13995

14096
class ParsedArgs(typing.Protocol):
14197
issue_output_file: pathlib.Path
142-
pr_output_file: pathlib.Path
14398
github_ref: str
14499
github_repository: str
145100
github_event_name: str
@@ -155,12 +110,6 @@ def parse_args() -> ParsedArgs:
155110
help="The file to which to write the calculated issue number"
156111
"if no issue number was found, then an empty file will be written",
157112
)
158-
arg_parser.add_argument(
159-
"--pr-output-file",
160-
required=True,
161-
help="The file to which to write the calculated triggering PR number"
162-
"if no PR was found, then an empty file will be written",
163-
)
164113
arg_parser.add_argument(
165114
"--github-ref",
166115
required=True,
@@ -192,7 +141,6 @@ def parse_args() -> ParsedArgs:
192141

193142
parse_result = arg_parser.parse_args()
194143
parse_result.issue_output_file = pathlib.Path(parse_result.issue_output_file)
195-
parse_result.pr_output_file = pathlib.Path(parse_result.pr_output_file)
196144
return typing.cast("ParsedArgs", parse_result)
197145

198146

firebase-dataconnect/ci/post_comment_for_job_results.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import tempfile
2323
import typing
2424

25+
from util import fetch_pr_info, pr_number_from_github_ref
26+
2527
if typing.TYPE_CHECKING:
2628
from collections.abc import Iterable, Sequence
2729

@@ -49,17 +51,23 @@ def main() -> None:
4951

5052

5153
def generate_message_lines(data: ParsedArgs) -> Iterable[str]:
52-
pr: int | None
53-
if len(data.triggering_pr) == 0:
54-
pr = None
54+
logging.info("Extracting PR number from string: %s", data.github_ref)
55+
pr_number = pr_number_from_github_ref(data.github_ref)
56+
pr_title: str | None
57+
if pr_number is None:
58+
logging.info("No PR number extracted")
59+
pr_title = None
5560
else:
56-
try:
57-
pr = int(data.triggering_pr)
58-
except ValueError:
59-
logging.warning("WARNING: unable to parse PR number as an int: %s", data.triggering_pr)
60-
pr = None
61+
pr_info = fetch_pr_info(
62+
pr_number=pr_number,
63+
github_repository=data.github_repository,
64+
)
65+
pr_title = pr_info.title
6166

62-
yield f"Posting from Pull Request {data.github_repository_html_url}/pull/{pr}"
67+
if pr_number is not None:
68+
yield (
69+
f"Posting from Pull Request {data.github_repository_html_url}/pull/{pr_number} ({pr_title})"
70+
)
6371

6472
yield f"Result of workflow '{data.github_workflow}' at {data.github_sha}:"
6573

@@ -125,13 +133,13 @@ class ParsedArgs(typing.Protocol):
125133
job_results: Sequence[JobResult]
126134
github_issue: int
127135
github_repository: str
136+
github_ref: str
128137
github_workflow: str
129138
github_sha: str
130139
github_repository_html_url: str
131140
github_run_id: str
132141
github_run_number: str
133142
github_run_attempt: str
134-
triggering_pr: str
135143

136144

137145
class ParseError(Exception):
@@ -154,14 +162,14 @@ def parse_args() -> ParsedArgs:
154162
help="The GitHub Issue number to which to post a comment",
155163
)
156164
arg_parser.add_argument(
157-
"--triggering-pr",
165+
"--github-repository",
158166
required=True,
159-
help="The GitHub Pull Request number that triggered the workflow, or empty if not applicable.",
167+
help="The value of ${{ github.repository }} in the workflow",
160168
)
161169
arg_parser.add_argument(
162-
"--github-repository",
170+
"--github-ref",
163171
required=True,
164-
help="The value of ${{ github.repository }} in the workflow",
172+
help="The value of ${{ github.ref }} in the workflow",
165173
)
166174
arg_parser.add_argument(
167175
"--github-workflow",

firebase-dataconnect/ci/util.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import annotations
16+
17+
import dataclasses
18+
import json
19+
import logging
20+
import re
21+
import subprocess
22+
import typing
23+
24+
if typing.TYPE_CHECKING:
25+
from collections.abc import Iterable
26+
27+
28+
@dataclasses.dataclass(frozen=True)
29+
class GitHubPrInfo:
30+
title: str
31+
body: str
32+
33+
34+
def fetch_pr_info(pr_number: int, github_repository: str) -> GitHubPrInfo:
35+
gh_args = _fetch_pr_gh_args(pr_number=pr_number, github_repository=github_repository)
36+
gh_args = tuple(gh_args)
37+
logging.info("Running command: %s", subprocess.list2cmdline(gh_args))
38+
output_str = subprocess.check_output(gh_args, encoding="utf8", errors="replace") # noqa: S603
39+
logging.info("%s", output_str)
40+
output = json.loads(output_str)
41+
return GitHubPrInfo(
42+
title=output["title"],
43+
body=output["body"],
44+
)
45+
46+
47+
def _fetch_pr_gh_args(pr_number: int, github_repository: str) -> Iterable[str]:
48+
yield "gh"
49+
yield "issue"
50+
yield "view"
51+
yield str(pr_number)
52+
yield "--json"
53+
yield "title,body"
54+
yield "-R"
55+
yield github_repository
56+
57+
58+
def pr_number_from_github_ref(github_ref: str) -> int | None:
59+
match = re.fullmatch("refs/pull/([0-9]+)/merge", github_ref)
60+
return int(match.group(1)) if match else None

0 commit comments

Comments
 (0)