heroku-headless 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in heroku-headless-deploy.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Pete Hodgson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # HerokuHeadless
2
+
3
+ ## What?
4
+ Push from your git repo to a heroku app without any external configuration.
5
+
6
+ ## Why?
7
+ Heroku's workflow is geared towards pushing to a heroku app from a dev workstation. This gem makes it easy to push to a heroku app as part of a CI/CD setup.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'heroku-headless'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install heroku-headless
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/heroku-headless/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Pete Hodgson"]
6
+ gem.email = ["phodgson@thoughtworks.com"]
7
+ gem.description = %q{Push from your git repo to a heroku app without any external configuration.}
8
+ gem.summary = %q{Heroku's workflow is geared towards pushing to a heroku app from a dev workstation. This gem makes it easy to push to a heroku app as part of a CI/CD setup.}
9
+ gem.homepage = "https://github.com/moredip/heroku-headless"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "heroku-headless"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = HerokuHeadless::VERSION
17
+
18
+ gem.add_runtime_dependency "heroku-api"
19
+ end
@@ -0,0 +1,7 @@
1
+ require "heroku-headless/version"
2
+
3
+ require "heroku-headless/documents_actions"
4
+ require "heroku-headless/creates_uuids"
5
+ require "heroku-headless/talks_to_heroku"
6
+
7
+ require "heroku-headless/deployer"
@@ -0,0 +1,8 @@
1
+ module HerokuHeadless
2
+ module CreatesUUIDs
3
+ def generate_lowercase_uuid
4
+ `uuidgen`.chomp.downcase
5
+ end
6
+ module_function :generate_lowercase_uuid
7
+ end
8
+ end
@@ -0,0 +1,95 @@
1
+ require 'pathname'
2
+ require 'tmpdir'
3
+
4
+ module HerokuHeadless
5
+ class Deployer
6
+ include DocumentsActions
7
+ include TalksToHeroku
8
+
9
+ def self.deploy(app_name)
10
+ new(app_name,CreatesUUIDs.generate_lowercase_uuid).deploy
11
+ end
12
+
13
+ def initialize( app_name, uid )
14
+ @app_name = app_name
15
+ @uid = uid
16
+ end
17
+
18
+ def deploy
19
+ prep_temp_dir
20
+ setup_ssh_key
21
+ do_action('push git to heroku'){ push_head_to_app }
22
+
23
+ ensure
24
+ cleanup
25
+ end
26
+
27
+ private
28
+
29
+ def prep_temp_dir
30
+ @tmpdir = Pathname.new( Dir.tmpdir ).join('heroku-deployer').join(@uid)
31
+ @tmpdir.mkpath
32
+ end
33
+
34
+ def cleanup
35
+ do_action( 'removing ssh key' ){ remove_ssh_key }
36
+ do_action( 'removing temp dir' ){ remove_temp_dir }
37
+ end
38
+
39
+ def remove_temp_dir
40
+ @tmpdir.rmtree
41
+ end
42
+
43
+ def setup_ssh_key
44
+ do_action( 'creating ssh key' ){ create_ssh_key }
45
+ do_action( 'adding ssh key' ){ add_ssh_key }
46
+ end
47
+
48
+ def create_ssh_key
49
+ `ssh-keygen -t rsa -N "" -C #{ssh_key_name} -f #{ssh_key_path}`
50
+ end
51
+
52
+ def ssh_key_path
53
+ @tmpdir.join('id_rsa')
54
+ end
55
+
56
+ def ssh_key_name
57
+ "deployer-#{@uid}"
58
+ end
59
+
60
+ def public_ssh_key
61
+ ssh_key_path.sub_ext('.pub').read
62
+ end
63
+
64
+ def add_ssh_key
65
+ heroku.post_key(public_ssh_key)
66
+ end
67
+
68
+ def remove_ssh_key
69
+ heroku.delete_key(ssh_key_name)
70
+ end
71
+
72
+ def push_head_to_app
73
+ setup_custom_git_ssh
74
+ push_git
75
+ end
76
+
77
+ def setup_custom_git_ssh
78
+ custom_git_ssh_path.open('w') do |f|
79
+ f.write <<-EOF
80
+ #!/bin/sh
81
+ exec ssh -o StrictHostKeychecking=no -o CheckHostIP=no -o UserKnownHostsFile=/dev/null -i #{ssh_key_path.expand_path} -- "$@"
82
+ EOF
83
+ end
84
+ custom_git_ssh_path.chmod( 0740 )
85
+ end
86
+
87
+ def push_git
88
+ system( {'GIT_SSH'=>custom_git_ssh_path.to_s}, "git push git@heroku.com:#{@app_name}.git HEAD:master" )
89
+ end
90
+
91
+ def custom_git_ssh_path
92
+ @tmpdir.join('git-ssh')
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ require "heroku-headless/talks_to_heroku"
2
+
3
+ module HerokuHeadless
4
+ class DisposableAppDeleter
5
+ include TalksToHeroku
6
+
7
+ def self.delete_all
8
+ new.delete_all_apps
9
+ end
10
+
11
+ def delete_all_apps
12
+ apps = heroku.get_apps.body.map{ |h| h['name'] }
13
+ disposable_apps = apps.select{ |x| x.start_with?( 'disposable' ) }
14
+ disposable_apps.each do |app|
15
+ puts "deleting #{app}"
16
+ heroku.delete_app app
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,54 @@
1
+ require "heroku-headless"
2
+
3
+ module HerokuHeadless
4
+ class DisposableDeployer
5
+ include TalksToHeroku
6
+ include DocumentsActions
7
+
8
+ def go
9
+ source_secrets
10
+ do_deploy
11
+ rescue
12
+ cleanup_after_failure
13
+ raise
14
+ ensure
15
+ cleanup
16
+ end
17
+
18
+ private
19
+
20
+ def do_deploy
21
+ do_action('creating app'){ create_app }
22
+ puts "created http://#{@app_name}.herokuapp.com"
23
+
24
+ deploy_app
25
+
26
+ end
27
+
28
+ def create_app
29
+ app_name = "disposable-#{deploy_uuid}"[0,30]
30
+ heroku.post_app( name: app_name )
31
+ @app_name = app_name
32
+ end
33
+
34
+ def deploy_app
35
+ Deployer.new(@app_name,deploy_uuid).deploy
36
+ end
37
+
38
+ def cleanup
39
+ # nothing to be done for now
40
+ end
41
+
42
+ def cleanup_after_failure
43
+ destroy_app
44
+ end
45
+
46
+ def destroy_app
47
+ heroku.delete_app( @app_name ) if @app_name
48
+ end
49
+
50
+ def deploy_uuid
51
+ @deploy_uuid ||= CreatesUUIDs.generate_lowercase_uuid
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ module HerokuHeadless
2
+ module DocumentsActions
3
+ def do_action(description)
4
+ print " " + description + " ..."
5
+ yield
6
+ puts " DONE"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'heroku-api'
2
+
3
+ module HerokuHeadless
4
+ module TalksToHeroku
5
+ def heroku
6
+ @heroku ||= Heroku::API.new()
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module HerokuHeadless
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroku-headless
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pete Hodgson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: heroku-api
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Push from your git repo to a heroku app without any external configuration.
31
+ email:
32
+ - phodgson@thoughtworks.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - LICENSE
40
+ - README.md
41
+ - Rakefile
42
+ - heroku-headless.gemspec
43
+ - lib/heroku-headless.rb
44
+ - lib/heroku-headless/creates_uuids.rb
45
+ - lib/heroku-headless/deployer.rb
46
+ - lib/heroku-headless/disposable_app_deleter.rb
47
+ - lib/heroku-headless/disposable_deployer.rb
48
+ - lib/heroku-headless/documents_actions.rb
49
+ - lib/heroku-headless/talks_to_heroku.rb
50
+ - lib/heroku-headless/version.rb
51
+ homepage: https://github.com/moredip/heroku-headless
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.24
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Heroku's workflow is geared towards pushing to a heroku app from a dev workstation.
75
+ This gem makes it easy to push to a heroku app as part of a CI/CD setup.
76
+ test_files: []
77
+ has_rdoc: