       return
 
     if release?
-      deleteExistingAsset release, (error) ->
+      deleteExistingAssets release, (error) ->
         callback(error, release)
       return
 

    createBuildRelease (error, release) ->
      return done(error) if error?

      for {assetName, sourceName} in assets
        assetPath = path.join(buildDir, assetName)
        zipApp sourceName, assetName, assetPath, (error) ->
          return done(error) if error?
          uploadAsset release, assetName, assetPath, (error) ->
            return done(error) if error?
            publishRelease release, (error) ->
              return done(error) if error?
              getAtomDraftRelease (error, release) ->
                return done(error) if error?
                deleteExistingAsset release, assetName, (error) ->
                  return done(error) if error?
                  uploadAsset(release, assetName, assetPath, done)

logError = (message, error, details) ->
  grunt.log.error(message)
  grunt.log.error(error.message ? error) if error?
  grunt.log.error(details) if details

zipApp = (sourceName, assetName, assetPath, callback) ->
  fs.removeSync(assetPath)

  options = {cwd: path.dirname(assetPath), maxBuffer: Infinity}
  child_process.exec "zip -r --symlinks #{assetName} #{sourceName}", options, (error, stdout, stderr) ->
    if error?
      logError("Zipping #{sourceName} failed", error, stderr)
    callback(error)

getRelease = (callback) ->
  options =

      else
        callback(null, release)

uploadAssets = (release, buildDir, assets, callback) ->
  upload = (release, assetName, assetPath, callback) ->
    options =
      uri: release.upload_url.replace(/\{.*$/, "?name=#{assetName}")
      method: 'POST'
      headers: _.extend({
        'Content-Type': 'application/zip'
        'Content-Length': fs.getSizeSync(assetPath)
        }, defaultHeaders)

    assetRequest = request options, (error, response, body='') ->
      if error? or response.statusCode >= 400
        logError("Upload release asset #{assetName} failed", error, body)
        callback(error ? new Error(response.statusCode))
      else
        callback(null, release)

    fs.createReadStream(assetPath).pipe(assetRequest)

  tasks = []
  for {assetName, sourceName} in assets
    assetPath = path.join(buildDir, assetName)
    tasks.push(upload.bind(this, release, assetName, assetPath))
  async.parallel(tasks, callback)

publishRelease = (release, callback) ->
  options =
