示例#1
0
class PullRequestGithubCheckDownstreamHandler(AbstractGithubJobHandler):
    type = JobType.check_downstream
    triggers = [TheJobTriggerType.pull_request]
    event: PullRequestEvent

    # https://developer.github.com/v3/activity/events/types/#events-api-payload-28

    def __init__(self, config: ServiceConfig, job_config: JobConfig,
                 event: PullRequestEvent):
        super().__init__(config=config, job_config=job_config, event=event)
        self.event = event
        self.project: GitProject = event.get_project()
        self.package_config: PackageConfig = self.get_package_config_from_repo(
            self.project, event.base_ref, event.pr_id)
        self.package_config.upstream_project_url = event.project_url

    def run(self) -> HandlerResults:
        self.local_project = LocalProject(
            git_project=self.project,
            working_dir=self.config.command_handler_work_dir)

        self.api = PackitAPI(self.config, self.package_config,
                             self.local_project)

        self.api.sync_pr(
            pr_id=self.event.pr_id,
            dist_git_branch=self.job_config.metadata.get(
                "dist-git-branch", "master"),
            # TODO: figure out top upstream commit for source-git here
        )
        return HandlerResults(success=True, details={})
示例#2
0
def source_git_status(config: Config, source_git: str, dist_git: str):
    """Tell the synchronization status of a source-git and a dist-git repo.

    This command checks the commit history in the provided source-git
    and dist-git repos and informs about the range of commits to be
    synchronized from dist-git to source-git or the other way around,
    or informs that the repositories are in sync.

    If possible, the status command also provides instructions on how
    to synchronize the repositories.
    """
    source_git_path = pathlib.Path(source_git).resolve()
    dist_git_path = pathlib.Path(dist_git).resolve()
    package_config = get_local_package_config(
        source_git_path, package_config_path=config.package_config_path)
    api = PackitAPI(
        config=config,
        package_config=package_config,
        upstream_local_project=LocalProject(working_dir=source_git_path,
                                            offline=True),
        downstream_local_project=LocalProject(working_dir=dist_git_path,
                                              offline=True),
    )
    click.echo(api.sync_status_string(source_git=source_git,
                                      dist_git=dist_git))
示例#3
0
def get_packit_api(config: Config,
                   local_project: LocalProject,
                   dist_git_path: str = None):
    """
    Load the package config, set other options and return the PackitAPI
    """
    package_config = get_local_package_config(local_project.working_dir,
                                              try_local_dir_last=True)

    if dist_git_path:
        package_config.dist_git_clone_path = dist_git_path

    if dist_git_path and dist_git_path == local_project.working_dir:
        PackitAPI(
            config=config,
            package_config=package_config,
            upstream_local_project=None,
            downstream_local_project=local_project,
        )

    remote_urls: List[str] = []
    for remote in local_project.git_repo.remotes:
        remote_urls += remote.urls

    upstream_hostname = (get_hostname_or_none(
        url=package_config.upstream_project_url)
                         if package_config.upstream_project_url else None)

    lp_upstream = None
    lp_downstream = None

    for url in remote_urls:
        remote_hostname = get_hostname_or_none(url=url)
        if not remote_hostname:
            continue

        if upstream_hostname:
            if remote_hostname == upstream_hostname:
                lp_upstream = local_project
                logger.info("Input directory is an upstream repository.")
                break

        if package_config.dist_git_base_url and (
                remote_hostname in package_config.dist_git_base_url
                or remote_hostname in DIST_GIT_HOSTNAME_CANDIDATES):
            lp_downstream = local_project
            logger.info("Input directory is a downstream repository.")
            break
    else:
        lp_upstream = local_project
        # fallback, this is the past behavior
        logger.info("Input directory is an upstream repository.")

    api = PackitAPI(
        config=config,
        package_config=package_config,
        upstream_local_project=lp_upstream,
        downstream_local_project=lp_downstream,
    )
    return api
    def run(self) -> HandlerResults:
        # self.project is dist-git, we need to get upstream
        dg = DistGit(self.config, self.package_config)
        self.package_config.upstream_project_url = (
            dg.get_project_url_from_distgit_spec()
        )
        if not self.package_config.upstream_project_url:
            return HandlerResults(
                success=False,
                details={
                    "msg": "URL in specfile is not set. "
                    "We don't know where the upstream project lives."
                },
            )

        n, r = get_namespace_and_repo_name(self.package_config.upstream_project_url)
        up = self.project.service.get_project(repo=r, namespace=n)
        self.local_project = LocalProject(
            git_project=up, working_dir=self.config.command_handler_work_dir
        )

        self.api = PackitAPI(self.config, self.package_config, self.local_project)
        self.api.sync_from_downstream(
            # rev is a commit
            # we use branch on purpose so we get the latest thing
            # TODO: check if rev is HEAD on {branch}, warn then?
            dist_git_branch=self.distgit_event.branch,
            upstream_branch="master",  # TODO: this should be configurable
        )
        return HandlerResults(success=True, details={})
示例#5
0
def test_update_on_cockpit_ostree_pr_exists(cockpit_ostree):
    upstream_path, dist_git_path = cockpit_ostree

    def mocked_new_sources(sources=None):
        if not Path(sources).is_file():
            raise RuntimeError("archive does not exist")

    flexmock(PkgTool, new_sources=mocked_new_sources)
    flexmock(PackitAPI, init_kerberos_ticket=lambda: None)

    flexmock(
        DistGit,
        push_to_fork=lambda *args, **kwargs: None,
        is_archive_in_lookaside_cache=lambda archive_path: False,
        upload_to_lookaside_cache=lambda archive, pkg_tool: None,
        download_upstream_archive=lambda: "the-archive",
    )
    pr = flexmock(url="https://example.com/pull/1")
    flexmock(DistGit).should_receive("existing_pr").and_return(pr)

    pc = get_local_package_config(str(upstream_path))
    up_lp = LocalProject(working_dir=upstream_path)
    c = get_test_config()
    api = PackitAPI(c, pc, up_lp)
    api._dg = DistGit(c, pc)
    api._dg._local_project = LocalProject(working_dir=dist_git_path)

    with cwd(upstream_path):
        assert pr == api.sync_release(
            dist_git_branch="main",
            use_local_content=False,
            version="179",
            force_new_sources=False,
            create_pr=True,
        )
class GithubPullRequestHandler(AbstractGithubJobHandler):
    name = JobType.check_downstream
    triggers = [JobTriggerType.pull_request]

    # https://developer.github.com/v3/activity/events/types/#events-api-payload-28

    def __init__(self, config: ServiceConfig, job: JobConfig,
                 pr_event: PullRequestEvent):
        super().__init__(config=config, job=job, event=pr_event)
        self.pr_event = pr_event
        self.project: GitProject = pr_event.get_project()
        self.package_config: PackageConfig = get_package_config_from_repo(
            self.project, pr_event.base_ref)
        if not self.package_config:
            raise ValueError(
                f"No config file found in {self.project.full_repo_name}")
        self.package_config.upstream_project_url = pr_event.project_url

    def run(self) -> HandlerResults:
        self.local_project = LocalProject(
            git_project=self.project,
            working_dir=self.config.command_handler_work_dir)

        self.api = PackitAPI(self.config, self.package_config,
                             self.local_project)

        self.api.sync_pr(
            pr_id=self.pr_event.pr_id,
            dist_git_branch=self.job.metadata.get("dist-git-branch", "master"),
            # TODO: figure out top upstream commit for source-git here
        )
        return HandlerResults(success=True, details={})
示例#7
0
    def run(self):
        # rev is a commit
        # we use branch on purpose so we get the latest thing
        # TODO: check if rev is HEAD on {branch}, warn then?
        branch = nested_get(self.event, "msg", "commit", "branch")

        # self.project is dist-git, we need to get upstream

        dg = DistGit(self.config, self.package_config)
        self.package_config.upstream_project_url = (
            dg.get_project_url_from_distgit_spec())

        if not self.package_config.upstream_project_url:
            raise PackitException(
                "URL in specfile is not set. We don't know where the upstream project lives."
            )

        n, r = get_namespace_and_repo_name(
            self.package_config.upstream_project_url)
        up = self.upstream_service.get_project(repo=r, namespace=n)
        lp = LocalProject(git_project=up)

        api = PackitAPI(self.config, self.package_config, lp)
        api.sync_from_downstream(
            dist_git_branch=branch,
            upstream_branch="master",  # TODO: this should be configurable
        )
示例#8
0
文件: test_api.py 项目: xsuchy/packit
class ProposeUpdate(PackitUnittestOgr):
    def setUp(self):
        super().setUp()
        self.api = PackitAPI(
            config=self.conf, package_config=self.pc, upstream_local_project=self.lp
        )
        self.api._up = self.upstream
        self.api._dg = self.dg
        # Do not upload package, because no credentials given in CI
        flexmock(self.api).should_receive("_handle_sources").and_return(None)
        self.set_git_user()

    @unittest.skip(
        "Issue in ogr causing that User is not stored in persistent yaml files for pagure"
    )
    def test_propose_update(self):
        # change specfile little bit to have there some change
        specfile_location = os.path.join(self.lp.working_dir, "python-ogr.spec")
        with open(specfile_location, "a") as myfile:
            myfile.write("# test text")
        check_output(
            f"cd {self.lp.working_dir}; git commit -m 'test change' python-ogr.spec",
            shell=True,
        )
        self.api.sync_release("master")
示例#9
0
def test_update_on_cockpit_ostree(cockpit_ostree):
    def mocked_new_sources(sources=None):
        if not Path(sources).is_file():
            raise RuntimeError("archive does not exist")

    flexmock(FedPKG,
             init_ticket=lambda x=None: None,
             new_sources=mocked_new_sources)

    flexmock(
        DistGit,
        push_to_fork=lambda *args, **kwargs: None,
        is_archive_in_lookaside_cache=lambda archive_path: False,
    )
    flexmock(
        PackitAPI,
        push_and_create_pr=lambda pr_title, pr_description, dist_git_branch:
        None,
    )

    pc = get_local_package_config(str(cockpit_ostree))
    up_lp = LocalProject(working_dir=str(cockpit_ostree))
    c = get_test_config()

    api = PackitAPI(c, pc, up_lp)
    with cwd(cockpit_ostree):
        api.sync_release(
            "master",
            use_local_content=False,
            version="179",
            force_new_sources=False,
            create_pr=True,
        )

    assert api.dg.download_upstream_archive().is_file()
示例#10
0
    def run(self) -> HandlerResults:
        """
        Sync the upstream release to dist-git as a pull request.
        """

        self.local_project = LocalProject(
            git_project=self.project,
            working_dir=self.config.command_handler_work_dir)

        self.api = PackitAPI(self.config, self.package_config,
                             self.local_project)

        errors = []
        for branch in get_branches(
                self.job.metadata.get("dist-git-branch", "master")):
            try:
                self.api.sync_release(dist_git_branch=branch,
                                      version=self.event.tag_name)
            except Exception as ex:
                sentry_integration.send_to_sentry(ex)
                errors.append(
                    f"Propose update for branch {branch} failed: {ex}")

        if errors:
            return HandlerResults(
                success=False,
                details={
                    "msg": "Propose update failed.",
                    "errors": errors
                },
            )

        return HandlerResults(success=True, details={})
示例#11
0
def test_basic_local_update_direct_push(upstream_distgit_remote,
                                        mock_remote_functionality_upstream):
    """ basic propose-update test: mock remote API, use local upstream and dist-git """
    upstream, distgit, remote_dir = upstream_distgit_remote

    with cwd(upstream):
        c = get_test_config()

        pc = get_local_package_config(str(upstream))
        pc.upstream_project_url = str(upstream)
        pc.dist_git_clone_path = str(distgit)
        up_lp = LocalProject(working_dir=str(upstream))
        api = PackitAPI(c, pc, up_lp)
        api.sync_release("master", "0.1.0", create_pr=False)

        remote_dir_clone = Path(f"{remote_dir}-clone")
        subprocess.check_call(
            ["git", "clone", remote_dir,
             str(remote_dir_clone)],
            cwd=str(remote_dir_clone.parent),
        )

        spec = get_specfile(str(remote_dir_clone / "beer.spec"))
        assert spec.get_version() == "0.1.0"
        assert (remote_dir_clone / "README.packit").is_file()
class ProposeDownstreamHandler(JobHandler):
    type = JobType.propose_downstream
    triggers = [TheJobTriggerType.release]
    task_name = TaskName.propose_downstream

    def run(self) -> TaskResults:
        """
        Sync the upstream release to dist-git as a pull request.
        """

        self.local_project = LocalProject(
            git_project=self.project,
            working_dir=self.service_config.command_handler_work_dir,
        )

        self.api = PackitAPI(self.service_config, self.job_config,
                             self.local_project)

        errors = {}
        for branch in get_branches(*self.job_config.metadata.dist_git_branches,
                                   default="master"):
            try:
                self.api.sync_release(dist_git_branch=branch,
                                      version=self.data.tag_name)
            except Exception as ex:
                sentry_integration.send_to_sentry(ex)
                errors[branch] = str(ex)

        if errors:
            branch_errors = ""
            for branch, err in sorted(
                    errors.items(), key=lambda branch_error: branch_error[0]):
                err_without_new_lines = err.replace("\n", " ")
                branch_errors += f"| `{branch}` | `{err_without_new_lines}` |\n"

            body_msg = (
                f"Packit failed on creating pull-requests in dist-git:\n\n"
                f"| dist-git branch | error |\n"
                f"| --------------- | ----- |\n"
                f"{branch_errors}\n\n"
                "You can re-trigger the update by adding `/packit propose-update`"
                " to the issue comment.\n")

            self.project.create_issue(
                title=
                f"[packit] Propose update failed for release {self.data.tag_name}",
                body=body_msg,
            )

            return TaskResults(
                success=False,
                details={
                    "msg": "Propose update failed.",
                    "errors": errors
                },
            )

        return TaskResults(success=True, details={})
示例#13
0
def test_srpm_snapd(snapd):
    pc = get_local_package_config(str(snapd))
    up_lp = LocalProject(working_dir=str(snapd))
    c = get_test_config()
    api = PackitAPI(c, pc, up_lp)
    with cwd(snapd):
        path = api.create_srpm()
    assert path.exists()
    build_srpm(path)
示例#14
0
 def setUp(self):
     self._feature_id()
     super().setUp()
     self.api = PackitAPI(config=self.conf,
                          package_config=self.pc,
                          upstream_local_project=self.lp)
     self.api._up = self.upstream
     self.api._dg = self.dg
     self.set_git_user()
示例#15
0
def update(config, dist_git_path, upstream_git_path, dist_git_branch, repo):
    """
    Release current upstream release into Fedora
    """
    package_config = get_local_package_config(directory=repo.working_dir)
    package_config.downstream_project_url = dist_git_path
    package_config.upstream_project_url = upstream_git_path
    api = PackitAPI(config=config, package_config=package_config)
    api.sync_release(dist_git_branch)
示例#16
0
    def run(self) -> TaskResults:
        local_project = LocalProject(
            git_project=self.project,
            working_dir=self.service_config.command_handler_work_dir,
        )

        api = PackitAPI(
            config=self.service_config,
            # job_config and package_config are the same for PackitAPI
            # and we want to use job_config since people can override things in there
            package_config=self.job_config,
            upstream_local_project=local_project,
        )

        user_can_merge_pr = self.project.can_merge_pr(self.data.user_login)
        if not (user_can_merge_pr
                or self.data.user_login in self.service_config.admins):
            self.project.issue_comment(self.db_trigger.issue_id,
                                       PERMISSIONS_ERROR_WRITE_OR_ADMIN)
            return TaskResults(
                success=True,
                details={"msg": PERMISSIONS_ERROR_WRITE_OR_ADMIN})

        if not self.data.tag_name:
            msg = (
                "There was an error while proposing a new update for the Fedora package: "
                "no upstream release found.")
            self.project.issue_comment(self.db_trigger.issue_id, msg)
            return TaskResults(success=False,
                               details={"msg": "Propose update failed"})

        sync_failed = False
        for branch in self.dist_git_branches_to_sync:
            msg = (
                f"for the Fedora package `{self.job_config.downstream_package_name}`"
                f"with the tag `{self.data.tag_name}` in the `{branch}` branch.\n"
            )
            try:
                new_pr = api.sync_release(dist_git_branch=branch,
                                          version=self.data.tag_name,
                                          create_pr=True)
                msg = f"Packit-as-a-Service proposed [a new update]({new_pr.url}) {msg}"
                self.project.issue_comment(self.db_trigger.issue_id, msg)
            except PackitException as ex:
                msg = f"There was an error while proposing a new update {msg} Traceback is: `{ex}`"
                self.project.issue_comment(self.db_trigger.issue_id, msg)
                logger.error(f"Error while running a build: {ex}")
                sync_failed = True
        if sync_failed:
            return TaskResults(success=False,
                               details={"msg": "Propose update failed"})

        # Close issue if propose-update was successful in all branches
        self.project.issue_close(self.db_trigger.issue_id)

        return TaskResults(success=True, details={})
示例#17
0
def update_source_git(
    config: Config, source_git: str, dist_git: str, revision_range: str
):
    """Update a source-git repository based on a dist-git repository.

    Update a source-git repository with the selected checkout of a spec file
    and additional packaging files from a dist-git repository.

    Revision range represents part of dist-git history which is supposed
    to be synchronized. Use `HEAD~..` if you want to synchronize the last
    commit from dist-git. For more information on possible revision range
    formats, see gitrevisions(7).

    If patches or the sources file in the spec file changed, the command
    exits with return code 2. Such changes are not supported by this
    command, code changes should happen in the source-git repo.

    Inapplicable changes to the .gitignore file are ignored since the
    file may not be synchronized between dist-git and source-git.

    This command, by default, performs only local operations and uses the
    content of the source-git and dist-git repositories as it is, no checkout
    or fetch is performed.

    After the synchronization is done, packit will inform about the changes
    it has performed and about differences between source-git and dist-git
    prior to the synchronization process.

    Dist-git commit messages are preserved and used when creating new
    source-git commits.

    Examples

    Take the last commit (HEAD) of systemd dist-git repo and copy the
    spec file and other packaging files into the source-git repo:

    \b
        $ packit source-git update-source-git rpms/systemd src/systemd HEAD~..

    Synchronize changes from the last three dist-git commits:

    \b
        $ packit source-git update-source-git rpms/systemd src/systemd HEAD~3..
    """
    source_git_path = pathlib.Path(source_git).resolve()
    dist_git_path = pathlib.Path(dist_git).resolve()
    package_config = get_local_package_config(
        source_git_path, package_config_path=config.package_config_path
    )
    api = PackitAPI(
        config=config,
        package_config=package_config,
        upstream_local_project=LocalProject(working_dir=source_git_path, offline=True),
        downstream_local_project=LocalProject(working_dir=dist_git_path, offline=True),
    )
    api.update_source_git(revision_range=revision_range)
示例#18
0
def source_git_init(
    config,
    dist_git: git.Repo,
    source_git: git.Repo,
    upstream_ref: str,
    upstream_url: Optional[str],
    upstream_remote,
    pkg_tool: Optional[str],
    pkg_name: Optional[str],
    ignore_missing_autosetup: bool,
):
    """Initialize SOURCE_GIT as a source-git repo by applying downstream
    patches from DIST_GIT as Git commits on top of UPSTREAM_REF.

    SOURCE_GIT needs to be an existing clone of the upstream repository.

    UPSTREAM_REF is a tag, branch or commit from SOURCE_GIT.

    SOURCE_GIT and DIST_GIT are paths to the source-git and dist-git
    repos. Branch names can be specified, separated by colons.

    If a branch name is specified for SOURCE_GIT, the branch is checked
    out and reset to UPSTREAM_REF.

    If a branch name is specified for DIST_GIT, the branch is checked
    out before setting up the source-git repo. This branch is expected
    to exist.

    Each Git commit created in SOURCE_GIT will have a 'From-dist-git-commit'
    trailer to mark the hash of the dist-git commit from which it is created.

    To learn more about source-git, please check

        https://packit.dev/docs/source-git/

    Examples:

    \b
        $ packit source-git init v2.3.1 src/acl:rawhide rpms/acl:rawhide
        $ packit source-git init --pkg-tool centpkg v2.3.1 src/acl rpms/acl
    """
    logger.warning(
        "Generating source-git repositories is experimental, "
        "please give us feedback if it does things differently than you expect."
    )
    api = PackitAPI(config=config, package_config=None)
    api.init_source_git(
        dist_git=dist_git,
        source_git=source_git,
        upstream_ref=upstream_ref,
        upstream_url=upstream_url,
        upstream_remote=upstream_remote,
        pkg_tool=pkg_tool or config.pkg_tool,
        pkg_name=pkg_name,
        ignore_missing_autosetup=ignore_missing_autosetup,
    )
示例#19
0
文件: test_api.py 项目: xsuchy/packit
 def setUp(self):
     super().setUp()
     self.api = PackitAPI(
         config=self.conf, package_config=self.pc, upstream_local_project=self.lp
     )
     self.api._up = self.upstream
     self.api._dg = self.dg
     # Do not upload package, because no credentials given in CI
     flexmock(self.api).should_receive("_handle_sources").and_return(None)
     self.set_git_user()
示例#20
0
def test_srpm_on_cockpit_ostree(cockpit_ostree):
    upstream_path, dist_git_path = cockpit_ostree

    pc = get_local_package_config(str(upstream_path))
    up_lp = LocalProject(working_dir=str(upstream_path))
    c = get_test_config()
    api = PackitAPI(c, pc, up_lp)

    with cwd(upstream_path):
        api.create_srpm()
示例#21
0
    def run(self):
        pr_id = self.event["pull_request"]["number"]

        local_project = LocalProject(git_project=self.project)

        api = PackitAPI(self.config, self.package_config, local_project)

        api.sync_pr(
            pr_id=pr_id,
            dist_git_branch=self.job.metadata.get("dist-git-branch", "master"),
            # TODO: figure out top upstream commit for source-git here
        )
示例#22
0
class NewDistGitCommitHandler(FedmsgHandler):
    """Sync new changes to upstream after a new git push in the dist-git."""

    topic = "org.fedoraproject.prod.git.receive"
    triggers = [TheJobTriggerType.commit]
    task_name = TaskName.distgit_commit

    def __init__(
        self,
        package_config: PackageConfig,
        job_config: JobConfig,
        data: EventData,
    ):
        super().__init__(
            package_config=package_config,
            job_config=job_config,
            data=data,
        )
        self.branch = data.event_dict.get("branch")

    def run(self) -> TaskResults:
        # self.project is dist-git, we need to get upstream
        dg = DistGit(self.service_config, self.job_config)
        self.job_config.upstream_project_url = dg.get_project_url_from_distgit_spec(
        )
        if not self.job_config.upstream_project_url:
            return TaskResults(
                success=False,
                details={
                    "msg":
                    "URL in specfile is not set. "
                    "We don't know where the upstream project lives."
                },
            )

        n, r = get_namespace_and_repo_name(
            self.job_config.upstream_project_url)
        up = self.project.service.get_project(repo=r, namespace=n)
        self.local_project = LocalProject(
            git_project=up,
            working_dir=self.service_config.command_handler_work_dir)

        self.api = PackitAPI(self.service_config, self.job_config,
                             self.local_project)
        self.api.sync_from_downstream(
            # rev is a commit
            # we use branch on purpose so we get the latest thing
            # TODO: check if rev is HEAD on {branch}, warn then?
            dist_git_branch=self.branch,
            upstream_branch="master",  # TODO: this should be configurable
        )
        return TaskResults(success=True, details={})
示例#23
0
def test_basic_build(upstream_n_distgit, mock_remote_functionality_upstream):
    u, d = upstream_n_distgit

    with cwd(u):
        c = get_test_config()

        pc = get_local_package_config(str(u))
        pc.upstream_project_url = str(u)
        pc.downstream_project_url = str(d)
        up_lp = LocalProject(path_or_url=u)

        api = PackitAPI(c, pc, up_lp)
        api.build("master")
示例#24
0
    def run(self) -> HandlerResults:
        self.local_project = LocalProject(
            git_project=self.project, working_dir=self.config.command_handler_work_dir
        )

        self.api = PackitAPI(self.config, self.package_config, self.local_project)

        self.api.sync_pr(
            pr_id=self.pr_event.pr_id,
            dist_git_branch=self.job.metadata.get("dist-git-branch", "master"),
            # TODO: figure out top upstream commit for source-git here
        )
        return HandlerResults(success=True, details={})
示例#25
0
    def run(self):
        """
        Sync the upstream release to dist-git as a pull request.
        """
        version = self.event["release"]["tag_name"]

        local_project = LocalProject(git_project=self.project)

        api = PackitAPI(self.config, self.package_config, local_project)

        api.sync_release(
            dist_git_branch=self.job.metadata.get("dist-git-branch", "master"),
            version=version,
        )
示例#26
0
文件: bot_api.py 项目: jlebon/packit
 def sync_upstream_pull_request(
     self,
     package_config: PackageConfig,
     pr_id: int,
     dist_git_branch: str,
     upstream_local_project: LocalProject,
 ):
     logger.info("syncing the upstream code to downstream")
     packit_api = PackitAPI(
         config=self.config,
         package_config=package_config,
         upstream_local_project=upstream_local_project,
     )
     packit_api.sync_pr(pr_id=pr_id, dist_git_branch=dist_git_branch)
示例#27
0
class GithubReleaseHandler(AbstractGithubJobHandler):
    name = JobType.propose_downstream
    triggers = [JobTriggerType.release]
    event: ReleaseEvent

    def __init__(self, config: ServiceConfig, job: JobConfig,
                 release_event: ReleaseEvent):
        super().__init__(config=config, job=job, event=release_event)

        self.project: GitProject = release_event.get_project()
        self.package_config: PackageConfig = get_package_config_from_repo(
            self.project, release_event.tag_name)
        if not self.package_config:
            raise ValueError(
                f"No config file found in {self.project.full_repo_name}")
        self.package_config.upstream_project_url = release_event.project_url

    def run(self) -> HandlerResults:
        """
        Sync the upstream release to dist-git as a pull request.
        """

        self.local_project = LocalProject(
            git_project=self.project,
            working_dir=self.config.command_handler_work_dir)

        self.api = PackitAPI(self.config, self.package_config,
                             self.local_project)

        errors = []
        for branch in get_branches(
                self.job.metadata.get("dist-git-branch", "master")):
            try:
                self.api.sync_release(dist_git_branch=branch,
                                      version=self.event.tag_name)
            except Exception as ex:
                sentry_integration.send_to_sentry(ex)
                errors.append(
                    f"Propose update for branch {branch} failed: {ex}")

        if errors:
            return HandlerResults(
                success=False,
                details={
                    "msg": "Propose update failed.",
                    "errors": errors
                },
            )

        return HandlerResults(success=True, details={})
示例#28
0
class NewDistGitCommitHandler(FedmsgHandler):
    """ A new flag was added to a dist-git pull request """

    topic = "org.fedoraproject.prod.git.receive"
    name = JobType.sync_from_downstream
    triggers = [JobTriggerType.commit]

    def __init__(self, config: ServiceConfig, job: JobConfig,
                 distgit_event: DistGitEvent):
        super().__init__(config=config, job=job, event=distgit_event)
        self.distgit_event = distgit_event
        self.project = distgit_event.get_project()
        self.package_config = get_package_config_from_repo(
            self.project, distgit_event.ref)
        if not self.package_config:
            raise ValueError(
                f"No config file found in {self.project.full_repo_name}")

    def run(self) -> HandlerResults:
        # self.project is dist-git, we need to get upstream
        dg = DistGit(self.config, self.package_config)
        self.package_config.upstream_project_url = (
            dg.get_project_url_from_distgit_spec())
        if not self.package_config.upstream_project_url:
            return HandlerResults(
                success=False,
                details={
                    "msg":
                    "URL in specfile is not set. "
                    "We don't know where the upstream project lives."
                },
            )

        n, r = get_namespace_and_repo_name(
            self.package_config.upstream_project_url)
        up = self.project.service.get_project(repo=r, namespace=n)
        self.local_project = LocalProject(
            git_project=up, working_dir=self.config.command_handler_work_dir)

        self.api = PackitAPI(self.config, self.package_config,
                             self.local_project)
        self.api.sync_from_downstream(
            # rev is a commit
            # we use branch on purpose so we get the latest thing
            # TODO: check if rev is HEAD on {branch}, warn then?
            dist_git_branch=self.distgit_event.branch,
            upstream_branch="master",  # TODO: this should be configurable
        )
        return HandlerResults(success=True, details={})
    def run(self) -> HandlerResults:
        self.local_project = LocalProject(
            git_project=self.project,
            working_dir=self.config.command_handler_work_dir)

        self.api = PackitAPI(self.config, self.package_config,
                             self.local_project)

        collaborators = self.project.who_can_merge_pr()
        if self.event.github_login not in collaborators | self.config.admins:
            self.project.issue_comment(self.event.issue_id,
                                       PERMISSIONS_ERROR_WRITE_OR_ADMIN)
            return HandlerResults(
                success=True,
                details={"msg": PERMISSIONS_ERROR_WRITE_OR_ADMIN})

        if not self.event.tag_name:
            msg = (
                "There was an error while proposing a new update for the Fedora package: "
                "no upstream release found.")
            self.project.issue_comment(self.event.issue_id, msg)
            return HandlerResults(success=False,
                                  details={"msg": "Propose update failed"})

        sync_failed = False
        for branch in self.dist_git_branches_to_sync:
            msg = (
                f"for the Fedora package `{self.package_config.downstream_package_name}`"
                f"with the tag `{self.event.tag_name}` in the `{branch}` branch.\n"
            )
            try:
                new_pr = self.api.sync_release(dist_git_branch=branch,
                                               version=self.event.tag_name,
                                               create_pr=True)
                msg = f"Packit-as-a-Service proposed [a new update]({new_pr.url}) {msg}"
                self.project.issue_comment(self.event.issue_id, msg)
            except PackitException as ex:
                msg = f"There was an error while proposing a new update {msg} Traceback is: `{ex}`"
                self.project.issue_comment(self.event.issue_id, msg)
                logger.error(f"error while running a build: {ex}")
                sync_failed = True
        if sync_failed:
            return HandlerResults(success=False,
                                  details={"msg": "Propose update failed"})

        # Close issue if propose-update was successful in all branches
        self.project.issue_close(self.event.issue_id)

        return HandlerResults(success=True, details={})
示例#30
0
    def setUp(self):
        if (hasattr(rebasehelper, "VERSION")
                and int(rebasehelper.VERSION.split(".")[1]) >= 19):
            DataMiner.key = "rebase-helper>=0.19"
        else:
            DataMiner.key = "rebase-helper<0.19"
        DataMiner.data_type = DataTypes.Dict

        super().setUp()
        self.api = PackitAPI(config=self.conf,
                             package_config=self.pc,
                             upstream_local_project=self.lp)
        self.api._up = self.upstream
        self.api._dg = self.dg
        self.set_git_user()