def _sync_simulator(pull_request_rules, owner, repo, pull_number, token): try: if token: auth = github.GithubTokenAuth(owner, token) else: auth = github.get_auth(owner) with github.get_client(auth=auth) as client: try: data = client.item( f"/repos/{owner}/{repo}/pulls/{pull_number}") except http.HTTPNotFound: raise PullRequestUrlInvalid( message= f"Pull request {owner}/{repo}/pulls/{pull_number} not found" ) sub = asyncio.run( subscription.Subscription.get_subscription( client.auth.owner_id)) ctxt = context.Context( client, data, sub, [{ "event_type": "mergify-simulator", "data": [] }], ) match = pull_request_rules.get_pull_request_rule(ctxt) return actions_runner.gen_summary(ctxt, match) except exceptions.MergifyNotInstalled: raise PullRequestUrlInvalid( message=f"Mergify not installed on repository '{owner}/{repo}'")
async def _simulator(redis_cache, pull_request_rules, owner, repo, pull_number, token): try: if token: auth = github.GithubTokenAuth(token) else: auth = github.get_auth(owner) async with github.aget_client(auth=auth) as client: try: data = await client.item(f"/repos/{owner}/{repo}/pulls/{pull_number}") except http.HTTPNotFound: raise PullRequestUrlInvalid( message=f"Pull request {owner}/{repo}/pulls/{pull_number} not found" ) sub = await subscription.Subscription.get_subscription( redis_cache, data["base"]["user"]["id"] ) installation = context.Installation( data["base"]["user"]["id"], owner, sub, client, redis_cache, ) repository = context.Repository(installation, data["base"]["repo"]) ctxt = await repository.get_pull_request_context(data["number"], data) ctxt.sources = [{"event_type": "mergify-simulator", "data": []}] match = await pull_request_rules.get_pull_request_rule(ctxt) return await actions_runner.gen_summary(ctxt, pull_request_rules, match) except exceptions.MergifyNotInstalled: raise PullRequestUrlInvalid( message=f"Mergify not installed on repository '{owner}/{repo}'" )
async def asyncSetUp(self): super(FunctionalTestBase, self).setUp() self.existing_labels: typing.List[str] = [] self.protected_branches: typing.Set[str] = set() self.pr_counter: int = 0 self.git_counter: int = 0 self.cassette_library_dir = os.path.join(CASSETTE_LIBRARY_DIR_BASE, self.__class__.__name__, self._testMethodName) # Recording stuffs if RECORD: if os.path.exists(self.cassette_library_dir): shutil.rmtree(self.cassette_library_dir) os.makedirs(self.cassette_library_dir) self.recorder = vcr.VCR( cassette_library_dir=self.cassette_library_dir, record_mode="all" if RECORD else "none", match_on=["method", "uri"], ignore_localhost=True, filter_headers=[ ("Authorization", "<TOKEN>"), ("X-Hub-Signature", "<SIGNATURE>"), ("User-Agent", None), ("Accept-Encoding", None), ("Connection", None), ], before_record_response=self.response_filter, ) if RECORD: github.CachedToken.STORAGE = {} else: # Never expire token during replay mock.patch.object(github_app, "get_or_create_jwt", return_value="<TOKEN>").start() mock.patch.object( github.GithubAppInstallationAuth, "get_access_token", return_value="<TOKEN>", ).start() # NOTE(sileht): httpx pyvcr stubs does not replay auth_flow as it directly patch client.send() # So anything occurring during auth_flow have to be mocked during replay def get_auth(owner_name=None, owner_id=None, auth=None): if auth is None: auth = github.get_auth(owner_name, owner_id) auth.installation = { "id": config.INSTALLATION_ID, } auth.permissions_need_to_be_updated = False auth.owner_id = config.TESTING_ORGANIZATION_ID auth.owner = config.TESTING_ORGANIZATION return auth def github_aclient(owner_name=None, owner_id=None, auth=None): return github.AsyncGithubInstallationClient( get_auth(owner_name, owner_id, auth)) mock.patch.object(github, "aget_client", github_aclient).start() mock.patch.object(branch_updater.gitter, "Gitter", self.get_gitter).start() mock.patch.object(duplicate_pull.gitter, "Gitter", self.get_gitter).start() if not RECORD: # NOTE(sileht): Don't wait exponentialy during replay mock.patch.object(context.Context._ensure_complete.retry, "wait", None).start() # Web authentification always pass mock.patch("hmac.compare_digest", return_value=True).start() branch_prefix_path = os.path.join(self.cassette_library_dir, "branch_prefix") if RECORD: self.BRANCH_PREFIX = datetime.datetime.utcnow().strftime( "%Y%m%d%H%M%S") with open(branch_prefix_path, "w") as f: f.write(self.BRANCH_PREFIX) else: with open(branch_prefix_path, "r") as f: self.BRANCH_PREFIX = f.read() self.master_branch_name = self.get_full_branch_name("master") self.git = self.get_gitter(LOG) await self.git.init() self.addAsyncCleanup(self.git.cleanup) await root.startup() self.app = httpx.AsyncClient(app=root.app, base_url="http://localhost") await self.clear_redis_cache() self.redis_cache = utils.create_aredis_for_cache(max_idle_time=0) self.subscription = subscription.Subscription( self.redis_cache, config.TESTING_ORGANIZATION_ID, self.SUBSCRIPTION_ACTIVE, "You're not nice", frozenset( getattr(subscription.Features, f) for f in subscription.Features.__members__) if self.SUBSCRIPTION_ACTIVE else frozenset(), ) await self.subscription._save_subscription_to_cache() self.user_tokens = user_tokens.UserTokens( self.redis_cache, config.TESTING_ORGANIZATION_ID, { "mergify-test1": config.ORG_ADMIN_GITHUB_APP_OAUTH_TOKEN, "mergify-test3": config.ORG_USER_PERSONAL_TOKEN, }, ) await self.user_tokens.save_to_cache() # Let's start recording cassette = self.recorder.use_cassette("http.json") cassette.__enter__() self.addCleanup(cassette.__exit__) self.client_integration = github.aget_client( config.TESTING_ORGANIZATION, config.TESTING_ORGANIZATION_ID) self.client_admin = github.AsyncGithubInstallationClient( auth=github.GithubTokenAuth(token=config.ORG_ADMIN_PERSONAL_TOKEN)) self.client_fork = github.AsyncGithubInstallationClient( auth=github.GithubTokenAuth(token=self.FORK_PERSONAL_TOKEN)) self.addAsyncCleanup(self.client_integration.aclose) self.addAsyncCleanup(self.client_admin.aclose) self.addAsyncCleanup(self.client_fork.aclose) await self.client_admin.item("/user") await self.client_fork.item("/user") if RECORD: assert self.client_admin.auth.owner == "mergify-test1" assert self.client_fork.auth.owner == "mergify-test2" else: self.client_admin.auth.owner = "mergify-test1" self.client_fork.auth.owner = "mergify-test2" self.url_main = f"/repos/mergifyio-testing/{self.REPO_NAME}" self.url_fork = f"/repos/{self.client_fork.auth.owner}/{self.REPO_NAME}" self.git_main = f"{config.GITHUB_URL}/mergifyio-testing/{self.REPO_NAME}" self.git_fork = ( f"{config.GITHUB_URL}/{self.client_fork.auth.owner}/{self.REPO_NAME}" ) self.installation_ctxt = context.Installation( config.TESTING_ORGANIZATION_ID, config.TESTING_ORGANIZATION, self.subscription, self.client_integration, self.redis_cache, ) self.repository_ctxt = context.Repository(self.installation_ctxt, self.REPO_NAME, self.REPO_ID) real_get_subscription = subscription.Subscription.get_subscription async def fake_retrieve_subscription_from_db(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return self.subscription return subscription.Subscription( redis_cache, owner_id, False, "We're just testing", set(), ) async def fake_subscription(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return await real_get_subscription(redis_cache, owner_id) return subscription.Subscription( redis_cache, owner_id, False, "We're just testing", set(), ) mock.patch( "mergify_engine.subscription.Subscription._retrieve_subscription_from_db", side_effect=fake_retrieve_subscription_from_db, ).start() mock.patch( "mergify_engine.subscription.Subscription.get_subscription", side_effect=fake_subscription, ).start() async def fake_retrieve_user_tokens_from_db(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return self.user_tokens return user_tokens.UserTokens(redis_cache, owner_id, {}) real_get_user_tokens = user_tokens.UserTokens.get async def fake_user_tokens(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return await real_get_user_tokens(redis_cache, owner_id) return user_tokens.UserTokens(redis_cache, owner_id, {}) mock.patch( "mergify_engine.user_tokens.UserTokens._retrieve_from_db", side_effect=fake_retrieve_user_tokens_from_db, ).start() mock.patch( "mergify_engine.user_tokens.UserTokens.get", side_effect=fake_user_tokens, ).start() self._event_reader = EventReader(self.app) await self._event_reader.drain() # NOTE(sileht): Prepare a fresh redis await self.clear_redis_stream()
async def asyncSetUp(self) -> None: super(FunctionalTestBase, self).setUp() # NOTE(sileht): don't preempted bucket consumption # Otherwise preemption doesn't occur at the same moment during record # and replay. Making some tests working during record and failing # during replay. config.BUCKET_PROCESSING_MAX_SECONDS = 100000 config.API_ENABLE = True self.existing_labels: typing.List[str] = [] self.pr_counter: int = 0 self.git_counter: int = 0 mock.patch.object(branch_updater.gitter, "Gitter", self.get_gitter).start() mock.patch.object(duplicate_pull.gitter, "Gitter", self.get_gitter).start() # Web authentification always pass mock.patch("hmac.compare_digest", return_value=True).start() self.main_branch_name = self.get_full_branch_name("main") self.git = self.get_gitter(LOG) await self.git.init() self.addAsyncCleanup(self.git.cleanup) self.redis_links = redis_utils.RedisLinks(max_idle_time=0) await self.clear_redis() installation_json = await github.get_installation_from_account_id( config.TESTING_ORGANIZATION_ID) self.client_integration = github.aget_client(installation_json) self.client_admin = github.AsyncGithubInstallationClient( auth=github.GithubTokenAuth(token=config.ORG_ADMIN_PERSONAL_TOKEN, )) self.client_fork = github.AsyncGithubInstallationClient( auth=github.GithubTokenAuth(token=self.FORK_PERSONAL_TOKEN, )) self.addAsyncCleanup(self.client_integration.aclose) self.addAsyncCleanup(self.client_admin.aclose) self.addAsyncCleanup(self.client_fork.aclose) await self.client_admin.item("/user") await self.client_fork.item("/user") self.url_origin = ( f"/repos/mergifyio-testing/{self.RECORD_CONFIG['repository_name']}" ) self.url_fork = f"/repos/mergify-test2/{self.RECORD_CONFIG['repository_name']}" self.git_origin = f"{config.GITHUB_URL}/mergifyio-testing/{self.RECORD_CONFIG['repository_name']}" self.git_fork = ( f"{config.GITHUB_URL}/mergify-test2/{self.RECORD_CONFIG['repository_name']}" ) self.installation_ctxt = context.Installation( installation_json, self.subscription, self.client_integration, self.redis_links, ) self.repository_ctxt = await self.installation_ctxt.get_repository_by_id( github_types.GitHubRepositoryIdType( self.RECORD_CONFIG["repository_id"])) # NOTE(sileht): We mock this method because when we replay test, the # timing maybe not the same as when we record it, making the formatted # elapsed time different in the merge queue summary. def fake_pretty_datetime(dt: datetime.datetime) -> str: return "<fake_pretty_datetime()>" mock.patch( "mergify_engine.date.pretty_datetime", side_effect=fake_pretty_datetime, ).start() self._event_reader = EventReader(self.app, self.RECORD_CONFIG["repository_id"]) await self._event_reader.drain() # Track when worker work real_consume_method = worker.StreamProcessor.consume self.worker_concurrency_works = 0 async def tracked_consume( inner_self: worker.StreamProcessor, bucket_org_key: worker_lua.BucketOrgKeyType, owner_id: github_types.GitHubAccountIdType, owner_login_for_tracing: github_types.GitHubLoginForTracing, ) -> None: self.worker_concurrency_works += 1 try: await real_consume_method(inner_self, bucket_org_key, owner_id, owner_login_for_tracing) finally: self.worker_concurrency_works -= 1 worker.StreamProcessor.consume = tracked_consume # type: ignore[assignment] def cleanup_consume() -> None: worker.StreamProcessor.consume = real_consume_method # type: ignore[assignment] self.addCleanup(cleanup_consume)