1
0
mirror of https://github.com/openSUSE/osc.git synced 2026-03-07 17:46:12 +01:00

Merge pull request #2058 from dmach/git-obs-staging-group-rebase

Change 'git-obs staging group' to rely on the workflow-pr bot
This commit is contained in:
2026-03-06 14:40:17 +01:00
committed by GitHub
2 changed files with 306 additions and 177 deletions

View File

@@ -0,0 +1,146 @@
Feature: `git-obs staging group --no-ssh-strict-host-key-checking` command
Background:
Given I set working directory to "{context.osc.temp}"
# it's meant to work with project pull requests, but we'll work with pool/test-GitPkgA for simplicity
And I execute git-obs with args "-G alice repo fork pool/test-GitPkgA"
And I execute git-obs with args "-G alice repo clone Alice/test-GitPkgA --no-ssh-strict-host-key-checking"
And I set working directory to "{context.osc.temp}/test-GitPkgA"
And I execute "git config user.email 'alice@example.com'"
And I execute "git config user.name 'Alice'"
# Create labels
And I execute git-obs with args "api -X POST /repos/pool/test-GitPkgA/labels --data='{{"name": "staging/Backlog", "color": "#ffffff"}}'"
And I execute git-obs with args "api -X POST /repos/pool/test-GitPkgA/labels --data='{{"name": "staging/In Progress", "color": "#0000ff"}}'"
# Alice makes a new branch feature/1, no changes on top, and makes a pull request with "PR: foo/bar!1" description
And I execute "git checkout -b feature/1"
And I execute "git commit --allow-empty -m 'feature/1'"
And I execute "git push origin feature/1"
And I execute git-obs with args "-G alice pr create --title 'feature/1' --description='PR: foo/bar!1' --target-branch factory"
And I execute git-obs with args "api -X POST /repos/pool/test-GitPkgA/issues/1/labels --data='{{"labels": ["staging/Backlog"]}}'"
# Alice makes a new branch feature/2, no changes on top, and makes a pull request with "PR: foo/bar!2" description
And I execute "git checkout factory"
And I execute "git checkout -b feature/2"
And I execute "git commit --allow-empty -m 'feature/2'"
And I execute "git push origin feature/2"
And I execute git-obs with args "-G alice pr create --title 'feature/2' --description='PR: foo/bar!2' --target-branch factory"
And I execute git-obs with args "api -X POST /repos/pool/test-GitPkgA/issues/2/labels --data='{{"labels": ["staging/Backlog"]}}'"
@destructive
Scenario: Scenario 1: staging group --no-ssh-strict-host-key-checking with --target and existing PR
When I execute git-obs with args "-G alice staging group --no-ssh-strict-host-key-checking --target=pool/test-GitPkgA#1 pool/test-GitPkgA#2"
Then the exit code is 0
And stdout contains "Unable to add the 'staging/In Progress' label to pull request pool/test-GitPkgA#2"
And stdout contains "Unable to remove the 'staging/Backlog' label from pull request pool/test-GitPkgA#2"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#1"
Then the exit code is 0
And stdout contains "State : open"
And stdout contains "Description : PR: foo/bar!1"
# It should also contain the reference from #2
And stdout contains "PR: foo/bar!2"
And stdout doesn't contain "staging/In Progress"
And stdout contains "staging/Backlog"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#2"
Then the exit code is 0
And stdout contains "State : closed"
And stdout contains "Description : PR: foo/bar!2"
@destructive
Scenario: Scenario 2: staging group --no-ssh-strict-host-key-checking with --target and --remove-pr-references
When I execute git-obs with args "-G alice staging group --no-ssh-strict-host-key-checking --target=pool/test-GitPkgA#1 pool/test-GitPkgA#2 --remove-pr-references"
Then the exit code is 0
And stdout contains "Unable to add the 'staging/In Progress' label to pull request pool/test-GitPkgA#2"
And stdout contains "Unable to remove the 'staging/Backlog' label from pull request pool/test-GitPkgA#2"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#1"
Then the exit code is 0
And stdout contains "State : open"
And stdout doesn't contain "staging/In Progress"
And stdout contains "staging/Backlog"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#2"
Then the exit code is 0
And stdout contains "State : closed"
And stdout doesn't contain "PR: foo/bar!2"
@destructive
Scenario: Scenario 3: staging group --no-ssh-strict-host-key-checking without --target (creates new PR)
When I execute git-obs with args "-G alice staging group --no-ssh-strict-host-key-checking pool/test-GitPkgA#1 pool/test-GitPkgA#2"
Then the exit code is 0
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#3"
Then the exit code is 0
And stdout contains "State : open"
And stdout contains "PR: foo/bar!1"
And stdout contains "PR: foo/bar!2"
And stdout contains "Labels : staging/In Progress"
And stdout doesn't contain "staging/Backlog"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#1"
Then the exit code is 0
# PR #1 should be closed because it was merged into #3
And stdout contains "State : closed"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#2"
Then the exit code is 0
# PR #2 should be closed because it was merged into #3
And stdout contains "State : closed"
@destructive
Scenario: Scenario 4: staging group --no-ssh-strict-host-key-checking without --target and --remove-pr-references
When I execute git-obs with args "-G alice staging group --no-ssh-strict-host-key-checking pool/test-GitPkgA#1 pool/test-GitPkgA#2 --remove-pr-references"
Then the exit code is 0
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#3"
Then the exit code is 0
And stdout contains "PR: foo/bar!1"
And stdout contains "PR: foo/bar!2"
And stdout contains "Labels : staging/In Progress"
And stdout doesn't contain "staging/Backlog"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#1"
Then the exit code is 0
And stdout contains "State : closed"
And stdout doesn't contain "PR: foo/bar!1"
And I execute git-obs with args "-G alice pr get pool/test-GitPkgA#2"
Then the exit code is 0
And stdout contains "State : closed"
And stdout doesn't contain "PR: foo/bar!2"
@destructive
Scenario: Scenario 5: staging group --no-ssh-strict-host-key-checking by another user with push permissions
And I execute git-obs with args "-G alice api -X PUT /repos/Alice/test-GitPkgA/collaborators/Bob"
And I set working directory to "{context.osc.temp}"
# Bob clones Alice's fork
And I execute git-obs with args "-G bob repo clone Alice/test-GitPkgA --directory Alice-test-GitPkgA --no-ssh-strict-host-key-checking"
And I set working directory to "{context.osc.temp}/Alice-test-GitPkgA"
And I execute "git config user.email 'bob@example.com'"
And I execute "git config user.name 'Bob'"
When I execute git-obs with args "-G bob staging group --no-ssh-strict-host-key-checking pool/test-GitPkgA#1 pool/test-GitPkgA#2 --fork-owner=Alice"
Then the exit code is 0
And I execute git-obs with args "-G bob pr get pool/test-GitPkgA#3"
Then the exit code is 0
And stdout contains "State : open"
And stdout contains "Author : Bob \(bob@example.com\)"
And stdout contains "PR: foo/bar!1"
And stdout contains "PR: foo/bar!2"
And stdout contains "Labels : staging/In Progress"
And stdout doesn't contain "staging/Backlog"
@destructive
Scenario: Scenario 6: staging group --no-ssh-strict-host-key-checking by another user with push permissions to the target repository
And I execute git-obs with args "-G admin api -X PUT /repos/pool/test-GitPkgA/collaborators/Bob"
And I set working directory to "{context.osc.temp}"
# Bob clones the target repository
And I execute git-obs with args "-G bob repo clone pool/test-GitPkgA --directory pool-test-GitPkgA --no-ssh-strict-host-key-checking"
And I set working directory to "{context.osc.temp}/pool-test-GitPkgA"
# Bob's git identity
And I execute "git config user.email 'bob@example.com'"
And I execute "git config user.name 'Bob'"
When I execute git-obs with args "-G bob staging group --no-ssh-strict-host-key-checking pool/test-GitPkgA#1 pool/test-GitPkgA#2"
Then the exit code is 0
And I execute git-obs with args "-G bob pr get pool/test-GitPkgA#3"
Then the exit code is 0
And stdout contains "State : open"
# pr get output shows user login
And stdout contains "Author : Bob \(bob@example.com\)"
And stdout contains "Source : pool/test-GitPkgA"
And stdout contains "PR: foo/bar!1"
And stdout contains "PR: foo/bar!2"
And stdout contains "Labels : staging/In Progress"
And stdout doesn't contain "staging/Backlog"

View File

@@ -51,14 +51,14 @@ class StagingGroupCommand(osc.commandline_git.GitObsCommand):
).completer = osc.commandline_git.complete_pr
self.add_argument(
"--cache-dir",
help="Path to a git cache.",
"--no-ssh-strict-host-key-checking",
action="store_true",
help="Set 'StrictHostKeyChecking no' ssh option",
)
self.add_argument(
"--keep-temp-dir",
action="store_true",
help="Don't delete the temporary directory with git checkouts",
"--cache-dir",
help="Path to a git cache.",
)
def run(self, args):
@@ -82,207 +82,190 @@ class StagingGroupCommand(osc.commandline_git.GitObsCommand):
self.print_gitea_settings()
with TemporaryDirectory(prefix="git-obs-staging_", dir=".", delete=not args.keep_temp_dir) as temp_dir:
user_obj = gitea_api.User.get(self.gitea_conn)
pr_obj_list = []
pr_references = []
target_owner = None
target_repo = None
target_branch = None
for owner, repo, number in args.pr_list:
pr_obj = gitea_api.PullRequest.get(self.gitea_conn, owner, repo, number)
if args.target:
target_owner, target_repo, target_number = args.target
pr_obj = gitea_api.PullRequest.get(self.gitea_conn, target_owner, target_repo, target_number)
# # to update a pull request, we either need to be its creator or an admin in the repo
# if not (pr_obj._data["base"]["repo"]["permissions"]["admin"] or pr_obj.user == user_obj.login):
# raise gitea_api.GitObsRuntimeError(f"You don't have sufficient permissions to modify pull request {target_owner}/{target_repo}#{target_number}")
if pr_obj.state != "open":
# we don't care about the state of the package pull requests - they can be merged already
raise gitea_api.GitObsRuntimeError(f"Pull request {owner}/{repo}#{number} is not open (the state is '{pr_obj.state}')")
# get pull request data from gitea
pr_map = {}
for owner, repo, number in args.pr_list:
pr = gitea_api.StagingPullRequestWrapper(self.gitea_conn, owner, repo, number, topdir=temp_dir, cache_directory=cache_dir)
pr_map[(owner.lower(), repo.lower(), number)] = pr
# test that all PRs go to the same branch
if target_owner is None:
target_owner = pr_obj.base_owner
else:
assert target_owner == pr_obj.base_owner, f"{target_owner} != {pr_obj.base_owner}"
# run checks
target_owner = None
target_repo = None
target_branch = None
for owner, repo, number in args.pr_list:
pr = pr_map[(owner.lower(), repo.lower(), number)]
if target_repo is None:
target_repo = pr_obj.base_repo
else:
assert target_repo == pr_obj.base_repo, f"{target_repo} != {pr_obj.base_repo}"
if pr.pr_obj.state != "open":
# we don't care about the state of the package pull requests - they can be merged already
raise gitea_api.GitObsRuntimeError(f"Pull request {owner}/{repo}#{number} is not open (the state is '{pr.pr_obj.state}')")
if target_branch is None:
target_branch = pr_obj.base_branch
else:
assert target_branch == pr_obj.base_branch, f"{target_branch} != {pr_obj.base_branch}"
# if not (pr.pr_obj._data["base"]["repo"]["permissions"]["admin"] or pr.pr_obj.user == user_obj.login):
# raise gitea_api.GitObsRuntimeError(f"You don't have sufficient permissions to modify pull request {owner}/{repo}#{number}")
if gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL not in pr_obj.labels:
raise gitea_api.GitObsRuntimeError(f"Pull request {owner}/{repo}#{number} is missing the '{gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL}' label.")
if gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL not in pr.pr_obj.labels:
raise gitea_api.GitObsRuntimeError(f"Pull request {owner}/{repo}#{number} is missing the '{gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL}' label.")
pr_obj_list.append(pr_obj)
pr_references.extend(pr_obj.parse_pr_references())
# test that all PRs go to the same branch
if target_owner is None:
target_owner = pr.pr_obj.base_owner
else:
assert target_owner == pr.pr_obj.base_owner, f"{target_owner} != {pr.pr_obj.base_owner}"
# deduplicate entries
pr_references = sorted(set(pr_references))
if target_repo is None:
target_repo = pr.pr_obj.base_repo
else:
assert target_repo == pr.pr_obj.base_repo, f"{target_repo} != {pr.pr_obj.base_repo}"
# create title
if args.title:
title = args.title
else:
updated_packages = sorted([i[1] for i in pr_references])
# TODO: it would be nice to mention the target OBS project
# we keep only the first ``max_packages``, because the title might get too long quite easily
max_packages = 5
updated_packages_str = ", ".join(sorted(updated_packages)[:max_packages])
if len(updated_packages) > max_packages:
updated_packages_str += f" + {len(updated_packages) - max_packages} more"
title = f"Update packages: {updated_packages_str}"
if target_branch is None:
target_branch = pr.pr_obj.base_branch
else:
assert target_branch == pr.pr_obj.base_branch, f"{target_branch} != {pr.pr_obj.base_branch}"
if args.target:
target_owner, target_repo, target_number = args.target
target_pr_obj = gitea_api.PullRequest.get(self.gitea_conn, target_owner, target_repo, target_number)
# clone the git repos, cache submodule data
for owner, repo, number in args.pr_list:
pr = pr_map[(owner.lower(), repo.lower(), number)]
pr.clone()
# extend the 'PR: ' references in the target pull request
target_pr_obj._data["body"] = gitea_api.PullRequest.add_pr_references(target_pr_obj.body, pr_references)
# run checks #2
for owner, repo, number in args.pr_list:
pr = pr_map[(owner.lower(), repo.lower(), number)]
if not pr.package_pr_map:
# TODO: we don't know if the submodules are packages or not, we should cross-reference those with _manifest
raise gitea_api.GitObsRuntimeError(f"Pull request {owner}/{repo}#{number} doesn't have any submodules changed.")
# update description of the target pull request in Gitea
# it is crucial to allow maintainer edits so the bot can push the related PRs
target_pr_obj = gitea_api.PullRequest.set(
self.gitea_conn,
target_pr_obj.base_owner,
target_pr_obj.base_repo,
int(target_pr_obj.number),
title=title,
description=target_pr_obj.body,
allow_maintainer_edit=True,
)
if not args.target:
target_repo_full_name = f"{target_owner}/{target_repo}".lower()
# determine fork_owner and fork_repo for pull request creation
has_push_access = False
user_repos = gitea_api.Repo.list_my_repos(self.gitea_conn)
for repo in user_repos:
repo_name = repo._data["full_name"]
if target_repo_full_name == repo_name.lower() and repo.can_push:
has_push_access = True
print(f"You have push access to the target repository {target_owner}/{target_repo}, the pull request will be created from a branch in the target repository.")
break
if has_push_access and not args.fork_owner:
fork_owner = target_owner
fork_repo = target_repo
else:
fork_owner = args.fork_owner if args.fork_owner else user_obj.login
fork_repo = None
forks = gitea_api.Fork.list(self.gitea_conn, target_owner, target_repo)
for repo in forks:
if repo.owner.lower() == fork_owner.lower():
fork_repo = repo.repo
break
if not fork_repo:
raise gitea_api.GitObsRuntimeError(f"Cannot find a matching fork of {target_owner}/{target_repo} for user {fork_owner}")
# dates in ISO 8601 format cannot be part of a valid branch name, we need a custom format
fork_branch = args.fork_branch if args.fork_branch else f"for/{target_branch}/group-{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}"
clone_dir = gitea_api.Repo.clone(
# update labels
try:
gitea_api.PullRequest.add_labels(
self.gitea_conn,
fork_owner,
fork_repo,
directory=os.path.join(temp_dir, f"{fork_owner}_{fork_repo}"),
add_remotes=True,
cache_directory=cache_dir,
ssh_private_key_path=self.gitea_conn.login.ssh_key,
)
clone_git = gitea_api.Git(clone_dir)
clone_git._run_git(["fetch", "origin", f"{target_branch}:{fork_branch}", "--force", "--update-head-ok", "--depth=1"])
clone_git.switch(fork_branch)
clone_git.push(remote="origin", branch=fork_branch, set_upstream=True, force=args.force)
# target project pull request wasn't specified, let's create it
desc = ""
updated_packages = []
for owner, repo, number in args.pr_list:
pr = pr_map[(owner.lower(), repo.lower(), number)]
for (pkg_owner, pkg_repo, pkg_number), pr_obj in pr.package_pr_map.items():
desc += f"PR: {pkg_owner}/{pkg_repo}!{pkg_number}\n"
updated_packages.append(os.path.basename(pr.submodules_by_owner_repo[pkg_owner.lower(), pkg_repo.lower()]["path"]))
# TODO: it would be nice to mention the target OBS project
# we keep only the first ``max_packages``, because the title might get too long quite easily
max_packages = 5
updated_packages_str = ", ".join(sorted(updated_packages)[:max_packages])
if len(updated_packages) > max_packages:
updated_packages_str += f" + {len(updated_packages) - max_packages} more"
title = args.title if args.title else f"Update packages: {updated_packages_str}"
pr_obj = gitea_api.PullRequest.create(
self.gitea_conn,
target_owner=target_owner,
target_repo=target_repo,
target_branch=target_branch,
source_owner=fork_owner,
# source_repo is not required because the information lives in Gitea database
source_branch=fork_branch,
title=title,
description=desc,
target_pr_obj.base_owner,
target_pr_obj.base_repo,
int(target_pr_obj.number),
labels=[gitea_api.StagingPullRequestWrapper.INPROGRESS_LABEL],
)
target_number = pr_obj.number
except Exception as e:
print(f"Unable to add the '{gitea_api.StagingPullRequestWrapper.INPROGRESS_LABEL}' label to pull request {pr_obj.id}: {e}")
# clone the target git repo, cache submodule data
target = gitea_api.StagingPullRequestWrapper(self.gitea_conn, target_owner, target_repo, target_number, topdir=temp_dir, cache_directory=cache_dir)
target.clone()
try:
if gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL in target_pr_obj.labels:
gitea_api.PullRequest.remove_labels(
self.gitea_conn,
target_pr_obj.base_owner,
target_pr_obj.base_repo,
int(target_pr_obj.number),
labels=[gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL],
)
except Exception as e:
print(f"Unable to remove the '{gitea_api.StagingPullRequestWrapper.BACKLOG_LABEL}' label from pull request {pr_obj.id}: {e}")
else:
has_push_access = False
if target.pr_obj.head_can_push:
print(f"You have push access to the head repository of the target pull request {target_owner}/{target_repo}#{target_number}, the pull request will be updated by pushing to the head branch.")
has_push_access = True
if not args.fork_owner:
target_repo_obj = gitea_api.Repo.get(self.gitea_conn, target_owner, target_repo)
# determine if we have write access to the target repo and create the branch there if possible
if target_repo_obj.can_push:
print(f"You have push access to the target repository {target_owner}/{target_repo}, the pull request will be created from a branch in the target repository.")
has_push_access = True
if target.pr_obj._data['head']['repo']['fork'] and has_push_access:
# if the head repo is a fork and we have push access to it, we can push directly to the head branch
target.git._run_git(["remote", "set-url", "fork", target.pr_obj._data['head']['repo']['ssh_url']])
fork_branch = args.fork_branch if args.fork_branch else f"for/{target_branch}/group-{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}"
# locally merge package pull requests to the target project pull request (don't change anything on server yet)
updated_packages = []
for owner, repo, number in args.pr_list:
pr = pr_map[(owner.lower(), repo.lower(), number)]
target.merge(pr)
for (pkg_owner, pkg_repo, pkg_number), pr_obj in pr.package_pr_map.items():
updated_packages.append(os.path.basename(pr.submodules_by_owner_repo[pkg_owner.lower(), pkg_repo.lower()]["path"]))
if target.pr_obj._data['head']['repo']['fork']:
remote="fork"
if has_push_access:
fork_owner = target_owner
fork_repo = target_repo
else:
remote="origin"
user_obj = gitea_api.User.get(self.gitea_conn)
fork_owner = args.fork_owner if args.fork_owner else user_obj.login
# push to git repo associated with the target pull request
print(f"Pushing changes to {remote} on pull/{target.pr_obj.number}:{target.pr_obj.head_branch}")
target.git.push(remote=remote, branch=f"pull/{target.pr_obj.number}:{target.pr_obj.head_branch}")
# update target pull request
if args.target:
# we keep only the first ``max_packages``, because the title might get too long quite easily
max_packages = 5
updated_packages_str = ", ".join(sorted(updated_packages)[:max_packages])
if len(updated_packages) > max_packages:
updated_packages_str += f" + {len(updated_packages) - max_packages} more"
title = args.title if args.title else f"{target.pr_obj.title}, {updated_packages_str}"
fork_repo = None
forks = gitea_api.Fork.list(self.gitea_conn, target_owner, target_repo)
for repo in forks:
if repo.owner.lower() == fork_owner.lower():
fork_repo = repo.repo
if not fork_repo:
raise gitea_api.GitObsRuntimeError(f"Cannot find a matching fork of {target_owner}/{target_repo} for user {fork_owner}")
# if args.target is not set, we've created a new pull request with all 'PR:' references included
# if args.target is set (which is the case here), we need to update the description with the newly added 'PR:' references
target.pr_obj.set(self.gitea_conn, target_owner, target_repo, target_number, title=title, description=target.pr_obj.body)
# create the branch
if has_push_access:
gitea_api.Branch.create(self.gitea_conn, target_owner, target_repo, old_ref_name=target_branch, new_branch_name=fork_branch)
else:
fork_repo_obj = gitea_api.Repo.get(self.gitea_conn, fork_owner, fork_repo)
with TemporaryDirectory(prefix="git-obs-staging_", dir=".") as temp_dir:
# we need to create a branch that matches the target branch using git; Gitea doesn't have any API for that
clone_dir = gitea_api.Repo.clone(
self.gitea_conn,
fork_owner,
fork_repo,
directory=os.path.join(temp_dir, f"{fork_owner}_{fork_repo}"),
add_remotes=False,
cache_directory=cache_dir,
ssh_private_key_path=self.gitea_conn.login.ssh_key,
ssh_strict_host_key_checking=not(args.no_ssh_strict_host_key_checking),
)
clone_git = gitea_api.Git(clone_dir)
clone_git._run_git(["fetch", "origin", f"{target_branch}:{fork_branch}", "--force", "--update-head-ok", "--depth=1"])
clone_git.switch(fork_branch)
clone_git.add_remote("fork", fork_repo_obj.ssh_url)
clone_git.push(remote="fork", branch=fork_branch, set_upstream=True, force=args.force)
for owner, repo, number in args.pr_list:
pr = pr_map[(owner.lower(), repo.lower(), number)]
if args.remove_pr_references:
try:
# apply the removed 'PR:' reference to the package pull request
pr.pr_obj.set(self.gitea_conn, owner, repo, number, description=pr.pr_obj.body)
except Exception as e:
print(f"Unable to remove 'PR:' references from pull request {owner}/{repo}#{number}: {e}")
# target project pull request wasn't specified, let's create it
desc = gitea_api.PullRequest.add_pr_references("", pr_references)
target_pr_obj = gitea_api.PullRequest.create(
self.gitea_conn,
target_owner=target_owner,
target_repo=target_repo,
target_branch=target_branch,
source_owner=fork_owner,
# source_repo is not required because the information lives in Gitea database
source_branch=fork_branch,
title=title,
description=desc,
labels=[gitea_api.StagingPullRequestWrapper.INPROGRESS_LABEL],
)
# close the pull request that was merged into the target
# it is crucial to allow maintainer edits so the bot can push the related PRs
target_pr_obj = gitea_api.PullRequest.set(
self.gitea_conn,
target_pr_obj.base_owner,
target_pr_obj.base_repo,
int(target_pr_obj.number),
allow_maintainer_edit=True,
)
for pr_obj in pr_obj_list:
if args.remove_pr_references:
try:
gitea_api.PullRequest.close(self.gitea_conn, owner, repo, number)
# remove the 'PR:' references from the original pull request
refs = pr_obj.parse_pr_references()
body = gitea_api.PullRequest.remove_pr_references(pr_obj.body, refs)
pr_obj.set(self.gitea_conn, pr_obj.base_owner, pr_obj.base_repo, pr_obj.number, description=body)
except Exception as e:
print(f"Unable to close pull request {owner}/{repo}#{number}: {e}")
print(f"Unable to remove 'PR:' references from pull request {pr_obj.id}: {e}")
try:
# close the pull request that was merged into the target
gitea_api.PullRequest.close(self.gitea_conn, pr_obj.base_owner, pr_obj.base_repo, pr_obj.number)
except Exception as e:
print(f"Unable to close pull request {pr_obj.id}: {e}")
print()
print(target.pr_obj.to_human_readable_string())
print(target_pr_obj.to_human_readable_string())
print()
print("Staging project pull requests have been successfully merged")
if args.keep_temp_dir:
print()
print(f"Temporary files are available here: {temp_dir}")