Example #1
0
def test_upsert_change_request_ref_only_existing_revision(
    client,
    db_session,
    default_repo,
    default_revision,
    default_change_request,
    default_user,
    mocker,
):
    auth.set_current_tenant(
        auth.Tenant(access={default_repo.id: Permission.write}))

    assert ChangeRequest.query.count() == 1

    data = upsert_change_request(
        default_repo,
        default_change_request.provider,
        default_change_request.external_id,
        data={
            "message": "Hello",
            "parent_ref": default_change_request.parent_ref
        },
    ).json()

    assert ChangeRequest.query.count() == 1
    cr = ChangeRequest.query.get(data["id"])
    assert cr.parent_ref == default_change_request.parent_ref
    assert cr.parent_revision_sha is default_change_request.parent_revision_sha
Example #2
0
def test_upsert_change_request_already_exists(
    client,
    db_session,
    default_login,
    default_repo,
    default_repo_write_tenant,
    default_change_request,
):
    cr = upsert_change_request(
        default_change_request.repository,
        default_change_request.provider,
        default_change_request.external_id,
    ).json()

    assert cr["id"] == str(default_change_request.id)
    assert ChangeRequest.query.count() == 1
Example #3
0
def test_upsert_change_request_different_repos(
    client,
    db_session,
    default_repo,
    default_revision,
    default_change_request,
    default_user,
    mocker,
):
    """
    Check that two change requests from different repos can have the same external id
    """
    new_repo = factories.RepositoryFactory(public=True)

    auth.set_current_tenant(
        auth.Tenant(access={
            default_repo.id: Permission.write,
            new_repo.id: Permission.write
        }))

    default_change_request.external_id = "id"
    default_change_request.provider = RepositoryProvider.github.value
    db_session.add(default_change_request)
    db_session.commit()

    mock_identify_revision = mocker.patch(
        "zeus.utils.revisions.identify_revision")
    mock_identify_revision.return_value = factories.RevisionFactory(
        repository=new_repo, sha="1234567")
    assert ChangeRequest.query.count() == 1

    cr = upsert_change_request(
        new_repo,
        default_change_request.provider,
        default_change_request.external_id,
        data={
            "message": "Hello",
            "parent_revision_sha": default_revision.sha
        },
    ).json()

    assert ChangeRequest.query.count() == 2
    new_change_request = ChangeRequest.query.filter(
        ChangeRequest.id != default_change_request.id).first()
    assert cr["id"] == str(new_change_request.id)
Example #4
0
    def post(self, hook):
        current_app.logger.info("travis.received-webhook")

        payload = request.form.get("payload")
        if not payload:
            current_app.logger.error("travis.webhook-missing-payload")
            return Response(status=400)

        signature = request.headers.get("Signature")
        if not signature:
            current_app.logger.error("travis.webhook-missing-signature")
            return Response(status=400)

        try:
            signature = b64decode(signature)
        except ValueError:
            current_app.logger.error("travis.webhook-invalid-signature", exc_info=True)
            return Response(status=400)

        api_domain = (hook.config or {}).get("domain", "api.travis-ci.org")
        public_key = get_travis_public_key(api_domain)
        try:
            verify_signature(public_key, signature, payload.encode("utf-8"))
        except InvalidSignature:
            current_app.logger.error("travis.webhook-invalid-signature", exc_info=True)
            return Response(status=400)

        try:
            payload = json.loads(payload)
        except (TypeError, ValueError):
            current_app.logger.error("travis.webhook-invalid-payload", exc_info=True)
            return Response(status=400)

        data = {"ref": payload["commit"], "url": payload["build_url"]}

        domain = urlparse(data["url"]).netloc

        try:
            if payload["pull_request"]:
                data["label"] = "PR #{} - {}".format(
                    payload["pull_request_number"], payload["pull_request_title"]
                )

                upsert_change_request(
                    repository=hook.repository,
                    provider="github",
                    external_id=str(payload["pull_request_number"]),
                    data={
                        "parent_revision_sha": payload["base_commit"],
                        "head_revision_sha": payload["head_commit"],
                        "message": payload["pull_request_title"],
                    },
                )

            response = upsert_build(
                hook=hook, external_id=str(payload["id"]), data=data
            )
            build = Build.query.get(response.json()["id"])
            for job_payload in payload["matrix"]:
                upsert_job(
                    build=build,
                    hook=hook,
                    external_id=str(job_payload["id"]),
                    data={
                        "status": (
                            "finished"
                            if job_payload["status"] is not None
                            else "in_progress"
                        ),
                        "result": get_result(job_payload["state"]),
                        "allow_failure": bool(job_payload["allow_failure"]),
                        "label": get_job_label(job_payload),
                        "url": "https://{domain}/{owner}/{name}/jobs/{job_id}".format(
                            domain=domain,
                            owner=payload["repository"]["owner_name"],
                            name=payload["repository"]["name"],
                            job_id=job_payload["id"],
                        ),
                        "started_at": (
                            dateutil.parser.parse(job_payload["started_at"])
                            if job_payload["started_at"]
                            else None
                        ),
                        "finished_at": (
                            dateutil.parser.parse(job_payload["finished_at"])
                            if job_payload["finished_at"]
                            else None
                        ),
                    },
                )
        except ApiError:
            current_app.logger.error("travis.webhook-unexpected-error", exc_info=True)
            raise

        return Response(status=200)
Example #5
0
 def post(self, hook, cr_xid):
     return upsert_change_request(provider=hook.provider,
                                  external_id=cr_xid,
                                  data=request.get_json() or {})
def process_travis_webhook(hook_id: str, payload: dict, timestamp_ms: int):
    # TODO(dcramer): we want to utilize timestamp_ms to act as a version and
    # ensure we dont process older updates after newer updates are already present
    with nplusone.ignore("eager_load"):
        hook = (Hook.query.unrestricted_unsafe().options(
            joinedload("repository")).get(hook_id))

    auth.set_current_tenant(
        auth.Tenant(access={hook.repository_id: Permission.admin}))

    data = {"ref": payload["commit"], "url": payload["build_url"]}

    domain = urlparse(data["url"]).netloc

    try:
        if payload["pull_request"]:
            data["label"] = "PR #{} - {}".format(
                payload["pull_request_number"], payload["pull_request_title"])

            upsert_change_request(
                repository=hook.repository,
                provider="github",
                external_id=str(payload["pull_request_number"]),
                data={
                    "parent_revision_sha": payload["base_commit"],
                    "head_revision_sha": payload["head_commit"],
                    "message": payload["pull_request_title"],
                },
            )

        response = upsert_build(hook=hook,
                                external_id=str(payload["id"]),
                                data=data)
        build = Build.query.get(response.json()["id"])
        for job_payload in payload["matrix"]:
            upsert_job(
                build=build,
                hook=hook,
                external_id=str(job_payload["id"]),
                data={
                    "status": ("finished" if job_payload["status"] is not None
                               else "in_progress"),
                    "result":
                    get_result(job_payload["state"]),
                    "allow_failure":
                    bool(job_payload["allow_failure"]),
                    "label":
                    get_job_label(job_payload),
                    "url":
                    "https://{domain}/{owner}/{name}/jobs/{job_id}".format(
                        domain=domain,
                        owner=payload["repository"]["owner_name"],
                        name=payload["repository"]["name"],
                        job_id=job_payload["id"],
                    ),
                    "started_at":
                    (dateutil.parser.parse(job_payload["started_at"])
                     if job_payload["started_at"] else None),
                    "finished_at":
                    (dateutil.parser.parse(job_payload["finished_at"])
                     if job_payload["finished_at"] else None),
                },
            )
    except ApiError:
        current_app.logger.error("travis.webhook-unexpected-error",
                                 exc_info=True)
        raise