docs: def create(definition: dict, version: str, parameter: tuple,
             region: str,
             disable_rollback: bool,
             dry_run: bool,
             force: bool,
             tag: List[str],
             timeout: int,
             keep_stacks: Optional[int],
             traffic: int,
             verbose: bool,
             remote: str,
             parameter_file: Optional[str]
             ):
      """
      Create a new Cloud Formation stack from the given Senza definition file
      """
      lizzy = setup_lizzy_client(remote)
      parameter = list(parameter) or []
      if parameter_file:
          parameter.extend(read_parameter_file(parameter_file))
  
      if not force:  # pragma: no cover
          # supporting artifact checking would imply copying a large amount of code
          # from senza, so it should be considered out of scope until senza
          # and lizzy client are merged
          warning("WARNING: "
                  "Artifact checking is still not supported by lizzy-client.")
  
      with Action('Requesting new stack..') as action:
          new_stack, output = lizzy.new_stack(keep_stacks, traffic,
                                              definition, version,
                                              disable_rollback, parameter,
                                              region=region,
                                              dry_run=dry_run,
                                              tags=tag)
  
      stack_id = '{stack_name}-{version}'.format_map(new_stack)
      print(output)
  
      info('Stack ID: {}'.format(stack_id))
  
      if dry_run:
          info("Post deployment steps skipped")
          exit(0)
  
      with Action('Waiting for new stack...') as action:
          if verbose:
              print()  # ensure that new states will not be printed on the same line as the action
  
          last_state = None
          for state in lizzy.wait_for_deployment(stack_id, region=region):
              if state != last_state and verbose:
                  click.echo(' {}'.format(state))
              else:
                  action.progress()
              last_state = state
  
          # TODO be prepared to handle all final AWS CF states
          if last_state == 'ROLLBACK_COMPLETE':
              fatal_error(
                  'Stack was rollback after deployment. Check your application log for possible reasons.')
          elif last_state != 'CREATE_COMPLETE':
              fatal_error('Deployment failed: {}'.format(last_state))
  
      info('Deployment Successful')
  
      if traffic is not None:
          with Action('Requesting traffic change..'):
              try:
                  lizzy.traffic(stack_id, traffic, region=region)
              except requests.ConnectionError as e:
                  connection_error(e, fatal=False)
              except requests.HTTPError as e:
                  agent_error(e, fatal=False)
  
      # TODO unit test this
      if keep_stacks is not None:
          versions_to_keep = keep_stacks + 1
          stacks_to_remove_counter = 1
          end_time = datetime.datetime.utcnow() + datetime.timedelta(seconds=timeout)
          while stacks_to_remove_counter > 0 and datetime.datetime.utcnow() <= end_time:
              try:
                  all_stacks = lizzy.get_stacks([new_stack['stack_name']],
                                                region=region)
              except requests.ConnectionError as e:
                  connection_error(e, fatal=False)
                  error("Failed to fetch old stacks. "
                        "Old stacks WILL NOT BE DELETED")
                  exit(1)
              except requests.HTTPError as e:
                  agent_error(e, fatal=False)
                  error("Failed to fetch old stacks. "
                        "Old stacks WILL NOT BE DELETED")
                  exit(1)
              else:
                  sorted_stacks = sorted(all_stacks,
                                         key=lambda stack: stack['creation_time'])
                  stacks_to_remove = sorted_stacks[:-versions_to_keep]
                  stacks_to_remove_counter = len(stacks_to_remove)
                  with Action('Deleting old stacks..'):
                      print()
                      for old_stack in stacks_to_remove:
                          old_stack_id = '{stack_name}-{version}'.format_map(
                              old_stack)
                          if old_stack['status'] in COMPLETE_STATES:
                              click.echo(' {}'.format(old_stack_id))
                              try:
                                  lizzy.delete(old_stack_id, region=region)
                                  stacks_to_remove_counter -= 1
                              except requests.ConnectionError as e:
                                  connection_error(e, fatal=False)
                              except requests.HTTPError as e:
                                  agent_error(e, fatal=False)
                          else:
                              click.echo(' > {} current status is {} trying '
                                         'again later'.format(old_stack_id,
                                                              old_stack['status']))
                  if stacks_to_remove_counter > 0:
                      time.sleep(5)
  
          if datetime.datetime.utcnow() > end_time:
              click.echo('Timeout waiting for related stacks to be ready.')