diff --git a/.travis.yml b/.travis.yml
index d08c65f51..bdc1fa364 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,12 +10,11 @@ install:
   - mkdir -p $TRAVIS_BUILD_DIR/share/love/
 env:
   global:
-  - secure: "MA1+zHILO7O99n5+nj6jxuqVHUM0ZcGFfiZ9GT/4JyOG8nGkKWXopW/PbDzj\nRRFW3oknkm9jwVgCccvb2oSCPhEUVEUwcdo6xMuCFnskQNAA4q/SWAXXcZvm\nLjaJHNIb66Nnti+dhfAtfNvw8InzV7RzlmBxRrlH9M/0+X2gE5U="
-  - secure: "Ak9ffdd8c/3toP5hN+Y1YI0grtstT+pLcIyhYYUAKYnOZJNY+W+adSwIbT+D\n82KbHkntiBNZ6a5dPZ7j28bKAtIToNS0KHRqviqwpsPw8m2fJ1trbyBIuscF\nqLihmRq0ve+gWjJIDpTQh2BHTJ+9lHnDCGExkf8JCIrMK7lnU1w="
-  - secure: "trApdw22XK+5CuaDHnRnkp3qh2fRChaTSrH5mG+B+JCxpZMhT7pY98x6R/bj\nUOisRJODSxSveYWU5OgiG2YOk/LGxbc/YRRneNKUk9E+fiLySpT5dGCCrQgB\nnkM+vXOAr2wnW//0nZHC14caw5sc/yQJ6MLj1/6ofzvvffQbjNs="
-  - secure: "mp0ajWjr1kzxLdVb1wigp6ZzTQcpX9fU2WmplAjYTJnG4m58YZ3Ev+note9S\n0kfTyaQTJiUzbotxDXsUmBszCehnH7E8yP9PT1eli7bJS+b23D5dYnfaAYKf\nvf8E0JFhIvMm8MDFFnrIOESmFUNDj/T0aDN/ASu1x0QLmjRfmlA="
-  - secure: "ZcTu/33tHOnBiXqYr5ea0V2njReiHYe1LeBze8C224tU/V0ZvUaohIcJkF2E\nCb+7kLnf+HLCJtiD3XbLz6XJuwJnh80/Oq+ItwBWdWcH/AccexRFb1QKTeMR\naJvuecZ2yUxib251DYzlHnxtd1S9+M63atYWmllDpd6tM5ISbuI="
-  - secure: "OvdZg49UKSQ5zW/w/3R1coa4iIe1YWseI/7hhpOvv3ABpouI8AbPtmWFH9Ed\nIq1jTDu4Epm4dXs/wXEjcN7CXq2n8NF+a5x8SBSxmopFtjbDeOgwSHwnTxWn\nDMo5psEfZNoqMMnYQNvq0IV2W/2FPFRsIOCCg6oxgLfAJfrzKOE="
-  - secure: "rKCTAsDVeJijQglX0E48Vuqrpmx9uawA4ciObTWQ9uWhsiCZR72jg4lgh9QM\nDhSiHDRBWqC2RzuZzN2IpxAnRug8FzSecYJ9oaXvnbYJXt55UkcIv6ano1d6\nPc/VXa5kRnA8ozO9pvCnPYzT/o7mOxG/l16LOqCblXMsZf2n0IE="
   - XDG_DATA_HOME="$TRAVIS_BUILD_DIR/share"
 script: make deploy
+addons:
+  artifacts:
+    paths:
+      - ./build/hawkthorne-osx.zip
+      - ./build/hawkthorne-win-x86.zip
+      - ./build/hawkthorne.love
diff --git a/Makefile b/Makefile
index 87d932f32..e89356d23 100644
--- a/Makefile
+++ b/Makefile
@@ -57,15 +57,12 @@ bin/love.app/Contents/MacOS/love:
 # THE REST OF THESE TARGETS ARE FOR RELEASE AUTOMATION
 ######################################################
 
-CI_TARGET=test validate maps
+CI_TARGET=test validate maps productionize binaries
 
 ifeq ($(TRAVIS), true)
 ifeq ($(TRAVIS_PULL_REQUEST), false)
 ifeq ($(TRAVIS_BRANCH), release)
-CI_TARGET=clean test validate maps productionize upload appcast social
-endif
-ifeq ($(TRAVIS_BRANCH), master)
-CI_TARGET=clean test validate maps productionize upload
+CI_TARGET=clean test validate maps productionize upload social
 endif
 endif
 endif
@@ -111,16 +108,15 @@ productionize: venv
 
 binaries: build/hawkthorne-osx.zip build/hawkthorne-win-x86.zip
 
-upload: binaries venv
-	venv/bin/python scripts/upload_binaries.py
+upload: binaries post.md venv
+	venv/bin/python scripts/release.py
 
 appcast: venv build/hawkthorne-osx.zip win32/hawkthorne.exe
 	venv/bin/python scripts/sparkle.py
 	cat sparkle/appcast.json | python -m json.tool > /dev/null
 	venv/bin/python scripts/upload.py / sparkle/appcast.json
 
-social: venv post.md notes.html
-	venv/bin/python scripts/upload_release_notes.py
+social: venv notes.html post.md
 	venv/bin/python scripts/socialize.py post.md
 
 notes.html: post.md
diff --git a/requirements.txt b/requirements.txt
index 6e42001e3..605d836b9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
 tweepy==2.3.0
-requests==1.0.4
+requests==2.7.0
 jinja2==2.7.3
-boto==2.8.0
+boto==2.38.0
 markdown==2.2.1
+uritemplate.py==0.3.0
diff --git a/scripts/create_post.py b/scripts/create_post.py
index eb8d3dd7d..e4b9e43b3 100644
--- a/scripts/create_post.py
+++ b/scripts/create_post.py
@@ -1,31 +1,23 @@
-import os
-import sys
-from datetime import datetime
 import argparse
 import boto
 import requests
-import jinja2
-import json
-import time
-import subprocess
-
-import version
 
 pulls_url = "https://api.github.com/repos/hawkthorne/hawkthorne-journey/pulls"
-compare_url = "https://github.com/hawkthorne/hawkthorne-journey/compare/{}...{}"
 GITHUB_TIME = "%Y-%m-%dT%H:%M:%SZ"
 
 
 def post_content():
-    resp = requests.get(pulls_url, params={'state': 'closed', 'base': 'release'})
+    resp = requests.get(pulls_url, params={
+        'state': 'closed',
+        'base': 'release'
+    })
     pulls = resp.json()
 
     if not pulls:
         raise ValueError(('No pull request for this release, which means no'
                           'post'))
 
-    template = jinja2.Template(open('templates/post.md').read())
-    return template.render(pull=pulls[0], version=version.current_version())
+    return pulls[0]['body']
 
 
 def commithash(version):
diff --git a/scripts/productionize.py b/scripts/productionize.py
index 20238bcc2..6ee4e3545 100644
--- a/scripts/productionize.py
+++ b/scripts/productionize.py
@@ -8,7 +8,7 @@
 def create_conf_json(version):
     conf = json.load(open('src/config.json'))
 
-    if os.environ.get('TRAVIS_BRANCH', '') == 'master':
+    if os.environ.get('TRAVIS_BRANCH', '') != 'release':
         return
 
     conf.update({
@@ -35,10 +35,10 @@ def create_conf_lua(version):
 
 
 def main():
-    if os.environ.get('TRAVIS_BRANCH', '') == 'master':
-        v = "0.0.0"
-    else:
+    if os.environ.get('TRAVIS_BRANCH', '') == 'release':
         v = version.next_version()
+    else:
+        v = "0.0.0"
 
     logging.info("Creating osx/Info.plist")
     create_info_plist(v)
diff --git a/scripts/s3upload.py b/scripts/s3upload.py
deleted file mode 100644
index 39016a7f6..000000000
--- a/scripts/s3upload.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import argparse
-import os
-import boto
-
-conn = boto.connect_s3()
-
-parser = argparse.ArgumentParser(description="Upload files to S3")
-parser.add_argument("path", help="File to upload")
-parser.add_argument("version", help="Version to upload")
-args = parser.parse_args()
-name = os.path.basename(args.path)
-
-bucket = conn.get_bucket('hawkthorne.journey.builds', validate=False)
-key = bucket.new_key(os.path.join(args.version, name))
-
-key.set_contents_from_filename(os.path.abspath(args.path))
-
-
-
-
diff --git a/scripts/socialize.py b/scripts/socialize.py
index 28fdbb461..dd624e6dd 100644
--- a/scripts/socialize.py
+++ b/scripts/socialize.py
@@ -83,6 +83,7 @@ def update_twitter(version, post_url):
 def update_reddit(title, post, community=False):
     if 'TRAVIS' not in os.environ:
         logging.info('[DRYRUN] Posting {}'.format(title))
+        logging.info(post)
         return
 
     r = Reddit(os.environ['BRITTA_BOT_USER'])
@@ -110,7 +111,9 @@ def main():
     args = parser.parse_args()
     
     v = version.current_version()
-    post = args.input.read()
+    body = args.input.read()
+    template = open('templates/post.md').read()
+    post = template.format(body=body, version=v)
 
     post_url = update_reddit(title.format(v), post,
                              community=version.is_release())
diff --git a/scripts/upload_binaries.py b/scripts/upload_binaries.py
deleted file mode 100644
index ef09de23d..000000000
--- a/scripts/upload_binaries.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import os
-import boto
-import logging
-from boto.s3 import key
-
-import upload
-import version
-
-releases = [
-    'hawkthorne-win-x86.zip',
-    'hawkthorne-osx.zip',
-    'hawkthorne.love',
-]
-
-files = [
-    "DevIL.dll",
-    "love.dll",
-    "lua51.dll",
-    "mpg123.dll",
-    "msvcp110.dll",
-    "msvcr110.dll",
-    "OpenAL32.dll",
-    "SDL2.dll",
-    "hawkthorne.exe",
-]
-
-
-def main():
-    logging.basicConfig(level=logging.INFO)
-    c = boto.connect_s3()
-    b = c.get_bucket('files.projecthawkthorne.com')
-
-    branch = os.environ.get('TRAVIS_BRANCH', '')
-
-    v = 'v' + version.next_version()
-
-    if branch == 'master':
-        path = os.path.join('releases', 'tip')
-    else:
-        path = os.path.join('releases', 'v' + version.next_version())
-
-    for item in releases:
-        upload.upload_path(b, path, os.path.join('build', item))
-
-    if branch != 'release':
-        logging.info('[DRYRUN] Upload windows files')
-        logging.info('[DRYRUN] Create release symlinks')
-        return
-
-    for f in files:
-        wpath = os.path.join(path, "win")
-        upload.upload_path(b, wpath, os.path.join('win32', f))
-
-    for item in releases:
-        k = b.get_key("releases/latest/{}".format(item))
-        k.set_redirect("/releases/{}/{}".format(v, item))
-        k.set_acl('public-read')
-
-
-if __name__ == "__main__":
-    main()
-
diff --git a/scripts/version.py b/scripts/version.py
index 63a4458cf..d6dc25a20 100644
--- a/scripts/version.py
+++ b/scripts/version.py
@@ -1,33 +1,30 @@
 """
 Bump the version number
 """
-import os
-import boto
 import argparse
 import requests
-import json
-
-s3 = boto.connect_s3()
 
 
 def current_version():
     x, y, z = current_version_tuple()
-    return "{0}.{1}.{2}".format(x,y,z) 
+    return "{0}.{1}.{2}".format(x, y, z)
 
 
 def next_bugfix_version():
     x, y, z = current_version_tuple()
-    return "{0}.{1}.{2}".format(x,y,int(z) + 1) 
+    return "{0}.{1}.{2}".format(x, y, int(z) + 1)
 
 
 def next_minor_version():
     x, y, z = current_version_tuple()
-    return "{0}.{1}.0".format(x,int(y)+1) 
+    return "{0}.{1}.0".format(x, int(y)+1)
+
 
 def next_major_version():
     x, y, z = current_version_tuple()
     return "{0}.0.0".format(int(x)+1)
 
+
 def next_version():
     if is_major():
         return next_major_version()
@@ -39,20 +36,20 @@ def next_version():
 
 def prev_version():
     x, y, z = current_version_tuple()
-    return "{0}.{1}.{2}".format(x,y,int(z) - 1) 
+    return "{0}.{1}.{2}".format(x, y, int(z) - 1)
 
 
 def current_version_tuple():
-    bucket = s3.get_bucket("files.projecthawkthorne.com", validate=False)
-    key = bucket.get_key("releases/latest/hawkthorne-osx.zip")
-    redirect = key.get_redirect()
-    _, _, version, _ = redirect.split('/')
-    return tuple(version.replace('v', '').split('.'))
+    url = ("https://api.github.com/repos/hawkthorne/"
+           "hawkthorne-journey/releases/latest")
+    resp = requests.get(url)
+    tag_name = resp.json()['tag_name']
+    return tuple(tag_name.replace('v', '').split('.'))
 
 
 def is_release():
-    pulls_url = "https://api.github.com/repos/hawkthorne/hawkthorne-journey/pulls"
-    resp = requests.get(pulls_url, params={'state': 'closed', 'base': 'release'})
+    url = "https://api.github.com/repos/hawkthorne/hawkthorne-journey/pulls"
+    resp = requests.get(url, params={'state': 'closed', 'base': 'release'})
 
     if not resp.ok:
         return False
@@ -64,9 +61,10 @@ def is_release():
 
     return 'release' in pulls[0].get('title', '').lower()
 
+
 def is_major():
-    pulls_url = "https://api.github.com/repos/hawkthorne/hawkthorne-journey/pulls"
-    resp = requests.get(pulls_url, params={'state': 'closed', 'base': 'release'})
+    url = "https://api.github.com/repos/hawkthorne/hawkthorne-journey/pulls"
+    resp = requests.get(url, params={'state': 'closed', 'base': 'release'})
 
     if not resp.ok:
         return False
diff --git a/templates/post.md b/templates/post.md
index 8a20ae4b6..8e0dba35f 100644
--- a/templates/post.md
+++ b/templates/post.md
@@ -1,10 +1,10 @@
-{{ pull.body }}
+{body}
 
 **DOWNLOAD**
 
-- [OS X](http://files.projecthawkthorne.com/releases/v{{version}}/hawkthorne-osx.zip)
-- [Windows](http://files.projecthawkthorne.com/releases/v{{version}}/hawkthorne-win-x86.zip)
-- [hawkthorne.love](http://files.projecthawkthorne.com/releases/v{{version}}/hawkthorne.love)
+- [OS X](http://files.projecthawkthorne.com/releases/v{version}/hawkthorne-osx.zip)
+- [Windows](http://files.projecthawkthorne.com/releases/v{version}/hawkthorne-win-x86.zip)
+- [hawkthorne.love](http://files.projecthawkthorne.com/releases/v{version}/hawkthorne.love)
   You'll need to install the [love](http://love2d.org) framework as well.
 
 **How can I help?**
@@ -14,5 +14,3 @@
 - [Record music and sound effects](https://github.com/hawkthorne/hawkthorne-journey/blob/master/CONTRIBUTING.md#music-and-sound-effects)
 - [Draw sprites and tile sets](https://github.com/hawkthorne/hawkthorne-journey/blob/master/CONTRIBUTING.md#sprites)
 - [Create new costumes and characters](https://github.com/hawkthorne/hawkthorne-journey/blob/master/CONTRIBUTING.md#characters-and-costumes)
-
-[Full CHANGELOG on GitHub]({{pull.html_url}})