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
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
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)
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)
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