Skip to content

Commit b7cec31

Browse files
Add --branch option that sets CI_BRANCH_TO_TEST (#20)
* Add --branch option that sets CI_BRANCH_TO_TEST Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
1 parent 6594571 commit b7cec31

2 files changed

Lines changed: 111 additions & 36 deletions

File tree

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pip3 install ./ros-github-scripts
1313

1414
## ros-ci-for-pr
1515

16+
### With a list of PRs
17+
1618
Creates a github gist containing a modified ros2.repos, with the source branches from one or more PRs.
1719
Optionally, runs ci.ros2.org jobs and comments the status badges on the PRs in question - if the user has build access to ci.ros2.org.
1820

@@ -32,6 +34,26 @@ ros-ci-for-pr \
3234

3335
Note that the access token must have at least the "public_repo" permission (to be able to post comments), the "gist" permission (to be able to create gists), and the "read:org" permission (to be able to create the Jenkins job).
3436

37+
### With a branch name
38+
39+
As an alternative to the above, a branch name can be provided using the `--branch` option.
40+
CI tries to check out that branch in all ROS 2 core repositories; if such a branch exists, it then merges it into the distro's target branch and tests that.
41+
This is useful when making changes to multiple repos at once, but it requires pushing branches to the actual repository and not a fork.
42+
43+
When using the `--branch` and `--comment` options, provide a list of PRs on which to comment using either `--pulls` or `--interactive`.
44+
45+
Example:
46+
47+
```
48+
export GITHUB_ACCESS_TOKEN=$GITHUB_TOKEN
49+
ros-ci-for-pr \
50+
--branch username/multi-repo-feature \
51+
--pulls ros2/repo1#123 ros2/repo2#456 ros2/repo3#789 \
52+
--packages pkg1 pkg2 pkg3 \
53+
--build \
54+
--comment
55+
```
56+
3557
## ros-github-contribution-report
3658

3759
Generates a report of merged PRs on GitHub from a set of authors, optionally filtered by time and destination, and rendered to a variety of formats.

ros_github_scripts/ci_for_pr.py

Lines changed: 89 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
import logging
1717
import os
1818
import re
19-
from typing import Dict, List
19+
from typing import Dict
20+
from typing import List
21+
from typing import Optional
2022

2123
import github
2224
from github import Github, InputFileContent
@@ -207,27 +209,35 @@ def validate_and_fetch_pull_list(
207209

208210

209211
def format_ci_details(
210-
gist_url: str,
212+
*,
213+
gist_url: Optional[str],
211214
extra_build_args: str,
212215
extra_test_args: str,
213216
target_release: str,
214-
target_pulls: List[str],
217+
target_pulls: Optional[List[str]],
218+
branch_name: Optional[str],
215219
) -> str:
216-
pull_text = ', '.join(target_pulls)
217-
return '\n'.join([
218-
f'Pulls: {pull_text}',
219-
f'Gist: {gist_url}',
220+
details = []
221+
if target_pulls:
222+
details.append(f"Pulls: {', '.join(target_pulls)}")
223+
if gist_url:
224+
details.append(f'Gist: {gist_url}')
225+
if branch_name:
226+
details.append(f'Branch: {branch_name}')
227+
return details + [
220228
f'BUILD args: {extra_build_args}',
221229
f'TEST args: {extra_test_args}',
222230
f'ROS Distro: {target_release}',
223231
'Job: {}'.format(DEFAULT_JOB),
224-
])
232+
]
225233

226234

227235
def run_jenkins_build(
236+
*,
228237
build_args: str,
229238
test_args: str,
230-
gist_url: str,
239+
gist_url: Optional[str],
240+
branch_name: Optional[str],
231241
github_login: str,
232242
github_token: str,
233243
target_release: str,
@@ -237,6 +247,8 @@ def run_jenkins_build(
237247
238248
:returns: Text containing markdown of the build status badges for the launched build.
239249
"""
250+
assert gist_url or branch_name, 'Either a gist URL or a branch name must be provided'
251+
240252
# intentionally raises key_error on unknown distro
241253
ubuntu_distro = ROS_DISTRO_TO_UBUNTU_DISTRO[target_release]
242254
rhel_distro = ROS_DISTRO_TO_RHEL_DISTRO[target_release]
@@ -264,7 +276,10 @@ def run_jenkins_build(
264276
for p in param_spec
265277
}
266278
# augment with specific values for this PR
267-
build_params['CI_ROS2_REPOS_URL'] = gist_url
279+
if gist_url:
280+
build_params['CI_ROS2_REPOS_URL'] = gist_url
281+
if branch_name:
282+
build_params['CI_BRANCH_TO_TEST'] = branch_name
268283
build_params['CI_ROS_DISTRO'] = target_release
269284
build_params['CI_BUILD_ARGS'] += f' {build_args}'
270285
build_params['CI_TEST_ARGS'] += f' {test_args}'
@@ -325,39 +340,56 @@ def comment_results(
325340

326341
def parse_args():
327342
parser = argparse.ArgumentParser(
328-
description='Generate a CI build request for Pull Request(s)')
329-
group = parser.add_mutually_exclusive_group()
330-
group.add_argument(
343+
description='Generate a CI build request for Pull Request(s)',
344+
add_help=False)
345+
346+
select_group = parser.add_argument_group(
347+
title='change selection',
348+
description='Select the PRs or branch to test.')
349+
select_group.add_argument(
350+
'--branch', type=str,
351+
help='Branch to test across the repositories in the .repos files that have it. Corresponds '
352+
'to the CI_BRANCH_TO_TEST ci.ros2.org parameter, which means that this branch gets '
353+
'merged into the distro target branch for testing. When using this option with '
354+
'--comment, the list of PRs to comment on must be specified using the --pulls or '
355+
'--interactive option.')
356+
pulls_group = select_group.add_mutually_exclusive_group()
357+
pulls_group.add_argument(
331358
'-p', '--pulls', type=str, nargs='+',
332359
help='Space-separated list of pull requests to process, in format ORG/REPO#PULLNUMBER '
333-
'(e.g. ros2/rclpy#353) or https://github.com/ORG/REPO/pull/PULLNUMBER')
334-
group.add_argument(
360+
'(e.g. ros2/rclpy#353) or https://github.com/ORG/REPO/pull/PULLNUMBER. When using '
361+
'the --branch and --comment options, comments will be posted on these PRs.')
362+
pulls_group.add_argument(
335363
'-i', '--interactive', action='store_true',
336-
help='Prompt me to select my pull requests from a list, instead of specifying.')
364+
help='Prompt me to select my pull requests from a list, instead of specifying. When using '
365+
'the --branch and --comment options, comments will be posted on these PRs.')
337366

338-
parser.add_argument(
367+
# Create a group for these so that they are displayed below the 'change selection' group
368+
group = parser.add_argument_group(title='other options')
369+
group.add_argument('-h', '--help', action='help')
370+
group.add_argument(
339371
'-k', '--packages', type=str, nargs='+', default=None,
340372
help='Space-separated list of packages to be built and tested.')
341-
parser.add_argument(
373+
group.add_argument(
342374
'-t', '--target', type=str, default=DEFAULT_TARGET,
343375
help='Target distro for PRs; assumes {}.'.format(DEFAULT_TARGET))
344-
parser.add_argument(
376+
group.add_argument(
345377
'-b', '--build', action='store_true',
346378
help='Automatically start the build job on Jenkins and print out the resulting badges. '
347379
'Only works if your GitHub user is authorized to run builds.')
348-
parser.add_argument(
380+
group.add_argument(
349381
'-c', '--comment', action='store_true',
350382
help='Automatically post a comment on the PRs being built, containing relevant content.')
351-
parser.add_argument(
383+
group.add_argument(
352384
'--only-fixes-test', action='store_true',
353385
help='The fix being tested only fixes a test, which causes CI to be shorter')
354-
parser.add_argument(
386+
group.add_argument(
355387
'--colcon-build-args', type=str, default='',
356388
help='Arbitrary colcon arguments to specify to build; must be specified with -b')
357-
parser.add_argument(
389+
group.add_argument(
358390
'--colcon-test-args', type=str, default='',
359391
help='Arbitrary colcon arguments to specify to test; must be specified with -b')
360-
parser.add_argument(
392+
group.add_argument(
361393
'--cmake-args', type=str, default='',
362394
help='Arbitrary CMake arguments to specify to build; Each argument shall be prefixed'
363395
' with -D. CMake arguments shall only be used with -b --build option.')
@@ -374,17 +406,32 @@ def main():
374406
panic('Neither environment variable GITHUB_ACCESS_TOKEN nor GITHUB_TOKEN are set')
375407
github_instance = Github(github_access_token)
376408

377-
pull_texts = parsed.pulls
409+
branch_name = parsed.branch
410+
pull_texts = None
411+
chosen_pulls = []
378412
if parsed.interactive:
379413
all_user_pulls = fetch_user_pulls(github_instance)
380414
pull_texts, chosen_pulls = prompt_pull_selection(all_user_pulls)
381-
elif not parsed.pulls:
382-
panic('You must either choose --interactive or provide --pulls')
383-
else:
415+
elif parsed.pulls:
384416
chosen_pulls = validate_and_fetch_pull_list(github_instance, parsed.pulls)
385417

386-
gist = create_ci_gist(github_instance, chosen_pulls, parsed.target)
387-
gist_url = gist.files['ros2.repos'].raw_url
418+
# Have to select PRs when not providing branch
419+
if not branch_name and not chosen_pulls:
420+
panic(
421+
'When not using --branch, you must select PRs either using --interactive '
422+
'or by providing them using --pulls')
423+
# Have to select PRs when providing branch and enabling comments
424+
if branch_name and parsed.comment and not chosen_pulls:
425+
panic(
426+
'When using --branch and --comment, you must select PRs to comment on either using '
427+
'--interactive or by providing them using --pulls')
428+
429+
# Only create a gist if we specified PRs and not a branch
430+
# We can set both options for ci.ros2.org, but it does not make sense if we select PRs
431+
gist_url = None
432+
if chosen_pulls and not branch_name:
433+
gist = create_ci_gist(github_instance, chosen_pulls, parsed.target)
434+
gist_url = gist.files['ros2.repos'].raw_url
388435

389436
if not parsed.build and \
390437
(parsed.colcon_build_args or parsed.colcon_test_args or parsed.cmake_args):
@@ -407,16 +454,22 @@ def main():
407454
comment_texts = []
408455
comment_texts.append(
409456
format_ci_details(
410-
gist_url, extra_build_args, extra_test_args, parsed.target, pull_texts))
457+
gist_url=gist_url,
458+
extra_build_args=extra_build_args,
459+
extra_test_args=extra_test_args,
460+
target_release=parsed.target,
461+
target_pulls=pull_texts,
462+
branch_name=branch_name))
411463
if parsed.build:
412464
user = github_instance.get_user().login
413465
comment_texts.append(
414466
run_jenkins_build(
415-
extra_build_args,
416-
extra_test_args,
417-
gist_url,
418-
user,
419-
github_access_token,
467+
build_args=extra_build_args,
468+
test_args=extra_test_args,
469+
gist_url=gist_url,
470+
branch_name=branch_name,
471+
github_login=user,
472+
github_token=github_access_token,
420473
target_release=parsed.target))
421474

422475
comment_results(parsed.comment, '\n'.join(comment_texts), chosen_pulls)

0 commit comments

Comments
 (0)