def METHOD_NAME(self, dry_run: bool, defer: Optional[Callable] = None) -> None:
    gql_api = gql.get_api()
    roles = self.get_roles(gql_api.query)
    if not roles:
        logging.debug("No roles found.")
        return
    self.settings = self.get_integration_settings(gql_api.query)
    secret = self.secret_reader.read_all_secret(self.settings.credentials)
    # APIs
    state_obj = init_state(integration=self.name, secret_reader=self.secret_reader)
    internal_groups_client = InternalGroupsClient(
        secret["api_url"],
        secret["issuer_url"],
        secret["client_id"],
        secret["client_secret"],
    )
    if defer:
        defer(state_obj.cleanup)
        defer(internal_groups_client.close)
    # run
    desired_groups = self.fetch_desired_state(
        roles,
        contact_list=self.settings.contact_list,
        owners=[
            Entity(
                type=EntityType.SERVICE_ACCOUNT,
                # OIDC service accounts are named service-account-<client_id>
                id=f'service-account-{secret["client_id"]}',
            )
        ],
    )
    group_names = self.get_managed_groups(state_obj)
    # take desired groups into account to support overtaking existing ones
    group_names.update(g.name for g in desired_groups)
    current_groups = self.fetch_current_state(
        internal_groups_client, group_names=group_names
    )
    try:
        self.reconcile(
            dry_run=dry_run,
            internal_groups_client=internal_groups_client,
            desired_groups=desired_groups,
            current_groups=current_groups,
        )
    finally:
        self.set_managed_groups(dry_run=dry_run, state_obj=state_obj)