anchor.diff:      Teams = Array.empty
       UploadTimeout = TimeSpan.FromMinutes 2.
       AppId = String.Empty
  +    VersionId = String.Empty
  +}
  +
  +/// The default HockeyAppVersion parameters to create a version
  +let HockeyAppVersionDefaults = {
  +    ApiToken = String.Empty
  +    AppId = String.Empty
  +    Version = String.Empty
  +    UploadTimeout = TimeSpan.FromMinutes 2.
   }
   
   /// [omit]
   let private nl = Environment.NewLine
   
   /// [omit]
  -let private validateParams param =
  +let private validateParams param:HockeyAppUploadParams =
       if param.ApiToken = "" then failwith "You must provide your API token"
       if param.File = "" then failwith "You must provide an app file to upload"
       if not <| File.Exists param.File then
  
positive.code: 
      [<JsonProperty("Public_Url")>]
      PublicUrl : string
  }
  
  /// The HockeyApp parameter type
  /// Based on http://support.hockeyapp.net/kb/api/api-apps#upload-app
  [<CLIMutable>]
  type HockeyAppUploadParams = {
      /// (Required) API token
      ApiToken: string
  
      /// (Required) file data for the build (.ipa or .apk)
      File: string
  
      /// file data for dsym (IOS: *.dysm.zip or Android: mapping.txt)
      Dsym: string
  
      /// Release notes for the build
      Notes: string
  
      /// Release notes type for the build
      NotesType: NoteType
  
      /// Set the release type of the app
      ReleaseType: ReleaseType
  
      /// Set the owner of the app
      OwnerId: string
  
      /// Set the notify option
      Notify: NotifyOption
  
      /// Set version as mandatory
      Mandatory: MandatoryOption
  
      /// Set to true to enable the private download page (default is false)
      Private: bool
  
      /// Set to the git commit sha for this build
      CommitSHA: string
  
      /// Set to the URL of the build job on your build server
      BuildServerUrl: string
  
      /// Set to your source repository
      RepositoryUrl: string
  
      /// Release download status (can only be set with full-access tokens)
      DownloadStatus: DownloadStatusOption
  
      /// Restrict download to specific teams
      Teams: string[]
  
      /// Set maximum upload delay
      UploadTimeout: TimeSpan
  
      /// Set to your App Id (required for UWP apps targeting windows phone)
      AppId: string
  }
  
  /// The default HockeyApp parameters
  let HockeyAppUploadDefaults = {
      ApiToken = String.Empty
      File = String.Empty
  
negative.code:     if not (String.IsNullOrEmpty param.CommitSHA) then yield sprintf "-F \"commit_sha=%s\"" param.CommitSHA
      if not (String.IsNullOrEmpty param.BuildServerUrl) then yield sprintf "-F \"build_server_url=%s\"" param.BuildServerUrl
      if not (String.IsNullOrEmpty param.RepositoryUrl) then yield sprintf "-F \"repository_url=%s\"" param.RepositoryUrl
  
      if not (String.IsNullOrEmpty param.AppId) && (String.IsNullOrEmpty param.VersionId) then 
          yield sprintf "https://rink.hockeyapp.net/api/2/apps/%s/app_versions/upload" param.AppId
      else if not (String.IsNullOrEmpty param.AppId) && not (String.IsNullOrEmpty param.VersionId) then
          yield sprintf "https://rink.hockeyapp.net/api/2/apps/%s/app_versions/%s" param.AppId param.VersionId
      else
          yield "https://rink.hockeyapp.net/api/2/apps/upload"
  }
  
  /// [omit]
  let private toVersionCurlArgs (param:HockeyAppVersionParams) = seq {
      yield (String.Format("-sL -w \"{0}%{{http_code}}{0}\"", Regex.Escape(nl)))
      yield "-X POST"
      yield "-H \"Content-Type: application/json\""
      yield sprintf "-d '{\"bundle_version\":\"%s\"}'" param.Version
      yield sprintf "-H \"X-HockeyAppToken:%s\"" param.ApiToken
      yield sprintf "https://rink.hockeyapp.net/api/2/apps/%s/app_versions/new" param.AppId
  }
  
  /// [omit]
  let private processHockeyAppCmd<'TParam, 'TResponse when 'TParam :> BaseHockeyAppParams> defaults
      (setParams: 'TParam -> 'TParam) 
      (validateParam: 'TParam -> 'TParam) 
      (toCurlArgs: 'TParam -> seq<string>) =
      let p = defaults
              |> setParams
              |> validateParam
  
      p
      |> toCurlArgs
  