code: def _create_or_update_version(app_name, version, app_spec, try_update=True):
      
      # This has a race condition since the app could have been created or
      # published since we last looked.
      try:
          app_id = dxpy.api.app_new(app_spec)["id"]
          return app_id
      except dxpy.exceptions.DXAPIError as e:
          # TODO: detect this error more reliably
          if e.name == 'InvalidInput' and e.msg == 'Specified name and version conflict with an existing alias':
              print('App %s/%s already exists' % (app_spec["name"], version), file=sys.stderr)
              # The version number was already taken, so app/new doesn't work.
              # However, maybe it hasn't been published yet, so we might be able
              # to app-xxxx/update it.
              app_describe = dxpy.api.app_describe("app-" + app_name, alias=version)
              if app_describe.get("published", 0) > 0:
                  return None
              return _update_version(app_name, version, app_spec, try_update=try_update)
          raise e
docs: Creates a new version of the app. Returns an app_id, or None if the app has
      already been created and published.