docs: def complete(
          response: Response,
          project: typing.Union[Project, None],
          starting: ProjectStep = None,
          force: bool = False,
          limit: int = -1
  ) -> list:
      """
      Runs the entire project, writes the results files, and returns the URL to
      the report file
  
      :param response:
      :param project:
      :param starting:
      :param force:
      :param limit:
      :return:
          Local URL to the report path
      """
  
      if project is None:
          project = cauldron.project.get_internal_project()
  
      starting_index = 0
      if starting:
          starting_index = project.steps.index(starting)
      count = 0
  
      steps_run = []
  
      for ps in project.steps:
          if 0 < limit <= count:
              break
  
          if ps.index < starting_index:
              continue
  
          if not force and not ps.is_dirty():
              if limit < 1:
                  environ.log(
                      '[{}]: Nothing to update'.format(ps.definition.name)
                  )
              continue
  
          count += 1
  
          steps_run.append(ps)
          success = source.run_step(response, project, ps, force=True)
          if not success or project.stop_condition.halt:
              return steps_run
  
      return steps_run