docs: def deploy(stage, lambda_package, no_lambda, rebuild_deps, config_file):
      """Deploy the project to the development stage."""
      config = _load_config(config_file)
      if stage is None:
          stage = config['devstage']
  
      s3 = boto3.client('s3')
      cfn = boto3.client('cloudformation')
      region = _get_aws_region()
  
      # obtain previous deployment if it exists
      previous_deployment = None
      try:
          previous_deployment = cfn.describe_stacks(
              StackName=config['name'])['Stacks'][0]
      except botocore.exceptions.ClientError:
          pass
  
      # build lambda package if required
      built_package = False
      new_package = True
      if lambda_package is None and not no_lambda:
          print("Building lambda package...")
          lambda_package = _build(config, rebuild_deps=rebuild_deps)
          built_package = True
      elif lambda_package is None:
          # preserve package from previous deployment
          new_package = False
          lambda_package = _get_from_stack(previous_deployment, 'Parameter',
                                           'LambdaS3Key')
  
      # create S3 bucket if it doesn't exist yet
      bucket = config['aws']['s3_bucket']
      _ensure_bucket_exists(s3, bucket, region)
  
      # upload lambda package to S3
      if new_package:
          s3.upload_file(lambda_package, bucket, lambda_package)
          if built_package:
              # we created the package, so now that is on S3 we can delete it
              os.remove(lambda_package)
  
      # prepare cloudformation template
      template_body = get_cfn_template(config)
      parameters = [
          {'ParameterKey': 'LambdaS3Bucket', 'ParameterValue': bucket},
          {'ParameterKey': 'LambdaS3Key', 'ParameterValue': lambda_package},
      ]
      stages = list(config['stage_environments'].keys())
      stages.sort()
      for s in stages:
          param = s.title() + 'Version'
          if s != stage:
              v = _get_from_stack(previous_deployment, 'Parameter', param) \
                  if previous_deployment else '$LATEST'
              v = v or '$LATEST'
          else:
              v = '$LATEST'
          parameters.append({'ParameterKey': param, 'ParameterValue': v})
  
      # run the cloudformation template
      if previous_deployment is None:
          print('Deploying {}:{}...'.format(config['name'], stage))
          cfn.create_stack(StackName=config['name'], TemplateBody=template_body,
                           Parameters=parameters,
                           Capabilities=['CAPABILITY_IAM'])
          waiter = cfn.get_waiter('stack_create_complete')
      else:
          print('Updating {}:{}...'.format(config['name'], stage))
          cfn.update_stack(StackName=config['name'], TemplateBody=template_body,
                           Parameters=parameters,
                           Capabilities=['CAPABILITY_IAM'])
          waiter = cfn.get_waiter('stack_update_complete')
  
      # wait for cloudformation to do its thing
      try:
          waiter.wait(StackName=config['name'])
      except botocore.exceptions.ClientError:
          # the update failed, so we remove the lambda package from S3
          if built_package:
              s3.delete_object(Bucket=bucket, Key=lambda_package)
          raise
      else:
          if previous_deployment and new_package:
              # the update succeeded, so it is safe to delete the lambda package
              # used by the previous deployment
              old_pkg = _get_from_stack(previous_deployment, 'Parameter',
                                        'LambdaS3Key')
              s3.delete_object(Bucket=bucket, Key=old_pkg)
  
      # we are done, show status info and exit
      _print_status(config)