diff --git a/cfg.production.toml b/cfg.production.toml index 5d561d8..7e004bd 100644 --- a/cfg.production.toml +++ b/cfg.production.toml @@ -18,6 +18,7 @@ ${HOMU_SSH_KEY} host = '0.0.0.0' port = 80 +base_url = "https://bors.rust-lang.org" canonical_url = "https://bors.rust-lang.org" remove_path_prefixes = ["homu"] diff --git a/cfg.sample.toml b/cfg.sample.toml index 564da0b..59d4581 100644 --- a/cfg.sample.toml +++ b/cfg.sample.toml @@ -51,6 +51,12 @@ port = 54856 # all open PRs. sync_on_start = true +# The base url used for links pointing to this homu instance. +# If base_url is not present, links will use canonical_url as a fallback. +# If neither base_url nor canonical_url are present, no links to this homu +# instance will be generated. +#base_url = "https://bors.example.com" + # The canonical URL of this homu instance. If a user reaches the instance # through a different path they will be redirected. If this is not present in # the configuration homu will still work, but no redirect will be performed. diff --git a/homu/html/queue.html b/homu/html/queue.html index 4047523..092c6ff 100644 --- a/homu/html/queue.html +++ b/homu/html/queue.html @@ -187,9 +187,14 @@

Homu queue - {% if repo_url %}{{repo_ {% for state in states %} + {% set checkbox_state = + ('checked' if state.prechecked else '') if + ((state.status == 'approved' or (state.status == 'pending' and not state.try_)) and state.rollup != 'never') + else 'disabled' + %} {{loop.index}} - + {% if multiple %} {{state.repo_label}} {% endif %} diff --git a/homu/main.py b/homu/main.py index 7a7c408..65ccaae 100644 --- a/homu/main.py +++ b/homu/main.py @@ -41,6 +41,15 @@ VARIABLES_RE = re.compile(r'\${([a-zA-Z_]+)}') +IGNORE_BLOCK_START = '' +IGNORE_BLOCK_END = '' +IGNORE_BLOCK_RE = re.compile( + r'' + r'.*' + r'', + flags=re.MULTILINE | re.DOTALL | re.IGNORECASE + ) + global_cfg = {} @@ -50,6 +59,12 @@ def suppress_pings(text): return re.sub(r'\B(@\S+)', r'`\g<1>`', text) # noqa +# Replace any text between IGNORE_BLOCK_START and IGNORE_BLOCK_END +# HTML comments with an empty string in merge commits +def suppress_ignore_block(text): + return IGNORE_BLOCK_RE.sub('', text) + + @contextmanager def buildbot_sess(repo_cfg): sess = requests.Session() @@ -356,6 +371,7 @@ def refresh(self): self.title = issue.title self.body = suppress_pings(issue.body) + self.body = suppress_ignore_block(self.body) def fake_merge(self, repo_cfg): if not repo_cfg.get('linear', False): @@ -1554,6 +1570,7 @@ def synchronize(repo_label, repo_cfg, logger, gh, states, repos, db, mergeable_q state = PullReqState(pull.number, pull.head.sha, status, db, repo_label, mergeable_que, gh, repo_cfg['owner'], repo_cfg['name'], repo_cfg.get('labels', {}), repos, repo_cfg.get('test-on-fork')) # noqa state.title = pull.title state.body = suppress_pings(pull.body) + state.body = suppress_ignore_block(state.body) state.head_ref = pull.head.repo[0] + ':' + pull.head.ref state.base_ref = pull.base.ref state.set_mergeable(None) diff --git a/homu/server.py b/homu/server.py index 6991f3f..525b494 100644 --- a/homu/server.py +++ b/homu/server.py @@ -5,7 +5,11 @@ PullReqState, parse_commands, db_query, + IGNORE_BLOCK_END, + IGNORE_BLOCK_START, INTERRUPTED_BY_HOMU_RE, + suppress_ignore_block, + suppress_pings, synchronize, LabelEvent, ) @@ -139,6 +143,10 @@ def queue(repo_label): except KeyError: abort(404, 'No such repository: {}'.format(label)) + prechecked_prs = set() + if request.query.get('prs'): + prechecked_prs = set(request.query.get('prs').split(',')) + pull_states = sorted(states) rows = [] for state in pull_states: @@ -154,6 +162,7 @@ def queue(repo_label): 'status_ext': status_ext, 'priority': state.priority, 'rollup': ROLLUP_STR.get(state.rollup, ''), + 'prechecked': str(state.num) in prechecked_prs, 'url': 'https://github.com/{}/{}/pull/{}'.format(state.owner, state.name, state.num), @@ -301,6 +310,9 @@ def rollup(user_gh, state, repo_label, repo_cfg, repo): failures.append(state.num) continue + state.body = suppress_pings(state.body) + state.body = suppress_ignore_block(state.body) + merge_msg = 'Rollup merge of #{} - {}, r={}\n\n{}\n\n{}'.format( state.num, state.head_ref, @@ -329,6 +341,20 @@ def rollup(user_gh, state, repo_label, repo_cfg, repo): body += ' - #{} ({})\n'.format(x.num, x.title) body += '\nr? @ghost' + # Set web.base_url in cfg to enable + base_url = g.cfg['web'].get('base_url') + if not base_url: + # If web.base_url is not present, fall back to using web.canonical_url + base_url = g.cfg['web'].get('canonical_url') + + if base_url: + pr_list = ','.join(str(x.num) for x in successes) + link = '{}/queue/{}?prs={}'.format(base_url, repo_label, pr_list) + body += '\n' + body += IGNORE_BLOCK_START + body += '\n[Create a similar rollup]({})\n'.format(link) + body += IGNORE_BLOCK_END + try: pull = base_repo.create_pull( title, diff --git a/homu/tests/test_pr_body.py b/homu/tests/test_pr_body.py index 06a5287..bb36bde 100644 --- a/homu/tests/test_pr_body.py +++ b/homu/tests/test_pr_body.py @@ -1,4 +1,9 @@ -from homu.main import suppress_pings +from homu.main import ( + suppress_ignore_block, + suppress_pings, + IGNORE_BLOCK_START, + IGNORE_BLOCK_END, +) def test_suppress_pings_in_PR_body(): @@ -15,3 +20,18 @@ def test_suppress_pings_in_PR_body(): ) assert suppress_pings(body) == expect + + +def test_suppress_ignore_block_in_PR_body(): + body = ( + "Rollup merge\n" + "{}\n" + "[Create a similar rollup](https://fake.xyz/?prs=1,2,3)\n" + "{}" + ) + + body = body.format(IGNORE_BLOCK_START, IGNORE_BLOCK_END) + + expect = "Rollup merge\n" + + assert suppress_ignore_block(body) == expect