puppet-autostager 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a5ed62a7740c05771fb4d9aaa8fc798fd81d8187
4
+ data.tar.gz: 8876fdfd9a24448647021ca1670a6f4e0460f6fc
5
+ SHA512:
6
+ metadata.gz: bb03600fe1631b813ec68a1c17b862f4ac3d00863784cb1ccbe5b50b7882e852b70b3153b2522a3515da59e22e0576a6c594856003bae689e04aa4096bba785b
7
+ data.tar.gz: 6ac3a4225687e4c17deeeba0d460386ac22858f5c5b300fa8356e5f457e084d5310e36f90fad61503c2402e265e59399ec35b28df5bc6ad2359eb7e555991da0
data/.editorconfig ADDED
@@ -0,0 +1,14 @@
1
+ ; This file is for unifying the coding style for different editors and IDEs.
2
+ ; Plugins are available for notepad++, emacs, vim, gedit,
3
+ ; textmate, visual studio, and more.
4
+ ;
5
+ ; See http://editorconfig.org for details.
6
+
7
+ root = true
8
+
9
+ [*]
10
+ indent_style = space
11
+ indent_size = 2
12
+ end_of_line = lf
13
+ insert_final_newline = true
14
+ trim_trailing_whitespace = true
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/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+
3
+ # Avoid diff-churn!
4
+ Style/TrailingComma:
5
+ EnforcedStyleForMultiline: comma
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ # This config supports:
2
+ #
3
+ # - https://travis-ci.org/
4
+ # - https://www.shippable.com/
5
+ language: ruby
6
+
7
+ rvm:
8
+ - 1.9.3
9
+ - 2.0.0
10
+
11
+ script:
12
+ - bundle exec rake test
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,32 @@
1
+ Contributing
2
+ ============
3
+
4
+ 1. Fork it
5
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
6
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
7
+ 4. Push to the branch (`git push origin my-new-feature`)
8
+ 5. Create new Pull Request
9
+
10
+
11
+ Diff churn
12
+ ----------
13
+
14
+ Please minimize diff churn to enhance git history commands.
15
+
16
+ * Arrays should usually be multi-line with trailing commas.
17
+
18
+ Update `.rubocop.yml` if necessary to favor minimal churn.
19
+
20
+
21
+ Linear history
22
+ --------------
23
+
24
+ Use `git rebase upstream/master` to update your branch.
25
+
26
+ * You **must** force-push after rebasing.
27
+ * We **never force-push** to master.
28
+
29
+ The primary reason for this is to maintain a clean, linear history
30
+ via "fast-forward" merges to master.
31
+ A clean, linear history in master makes it easier
32
+ to troubleshoot regressions and follow the timeline.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ source 'https://rubygems.org'
3
+
4
+ # Specify your gem's dependencies in autostager.gemspec
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Paul Morgan
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,44 @@
1
+ Autostager
2
+ ==========
3
+
4
+ Automatically stage a local directory based on Github pull request.
5
+
6
+ [![Build Status](https://api.shippable.com/projects/53f217676ac7a5580608058a/badge/master)](https://www.shippable.com/projects/53f217676ac7a5580608058a)
7
+ [![Build Status](https://travis-ci.org/jumanjihouse/autostager.svg?branch=master)](https://travis-ci.org/jumanjihouse/autostager)
8
+
9
+
10
+ Installation
11
+ ------------
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'puppet-autostager'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install puppet-autostager
24
+
25
+
26
+ Usage
27
+ -----
28
+
29
+ Create an access token as described at
30
+ https://github.com/octokit/octokit.rb#oauth-access-tokens
31
+ then export a few environment variables:
32
+
33
+ ```
34
+ export repo_slug=ISEexchange/puppet
35
+ export access_token=<your 40-char token>
36
+ export base_dir=/tmp/puppet/environments
37
+ export debug=anything
38
+ ```
39
+
40
+ Then run:
41
+
42
+ ```
43
+ autostager
44
+ ```
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ # vim: set ts=2 sw=2 ai et:
3
+
4
+ # Does the current user have root privileges?
5
+ #
6
+ # @return [Boolean] true if user can exercise root privileges;
7
+ # false if user does not have privileges OR we're on a
8
+ # non-posix platform
9
+ def got_root?
10
+ # attempt to exercise privilege
11
+ Process::Sys.setuid(0)
12
+ true
13
+ rescue Errno::EPERM
14
+ false
15
+ end
16
+
17
+ abort 'Must not run as root' if got_root?
18
+
19
+ require 'bundler/gem_tasks'
20
+ require 'bundler/setup'
21
+ require 'bundler/settings'
22
+ require 'rspec/core/rake_task'
23
+ require 'rubocop/rake_task'
24
+ require 'fileutils'
25
+
26
+ task default: [:help]
27
+
28
+ desc 'Display the list of available rake tasks'
29
+ task :help do
30
+ system('rake -T')
31
+ end
32
+
33
+ # Run unit tests before functional tests.
34
+ desc 'Run rspec tests'
35
+ task test: [
36
+ :rubocop,
37
+ :unit,
38
+ :functional,
39
+ ]
40
+
41
+ RSpec::Core::RakeTask.new(:unit) do |t|
42
+ t.pattern = 'spec/unit/**/*_spec.rb'
43
+ end
44
+
45
+ RSpec::Core::RakeTask.new(:functional) do |t|
46
+ t.pattern = 'spec/functional/**/*_spec.rb'
47
+ end
48
+
49
+ desc 'Run RuboCop'
50
+ RuboCop::RakeTask.new(:rubocop) do |t|
51
+ t.options.unshift '--display-cop-names'
52
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'English'
5
+ require 'autostager/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'puppet-autostager'
9
+ spec.version = Autostager::VERSION
10
+ spec.authors = ['Paul Morgan']
11
+ spec.email = ['jumanjiman@gmail.com']
12
+ spec.description = 'Create a puppet enviroment for each pull request'
13
+ spec.summary = 'Create a puppet enviroment for each pull request'
14
+ spec.homepage = 'https://github.com/jumanjiman/autostager'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($RS)
18
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.3'
23
+ spec.add_development_dependency 'friction'
24
+ spec.add_development_dependency 'minitest'
25
+ spec.add_development_dependency 'mocha'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'rspec-core'
28
+ spec.add_development_dependency 'rspec', '>= 3.0', '<= 4.0'
29
+ spec.add_development_dependency 'rspec-expectations'
30
+ spec.add_development_dependency 'rspec-mocks'
31
+ spec.add_development_dependency 'rubocop'
32
+ spec.add_development_dependency 'thor'
33
+
34
+ spec.add_dependency 'json'
35
+ spec.add_dependency 'octokit', '~> 3.0'
36
+ end
data/bin/autostager ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
5
+
6
+ require 'autostager'
7
+
8
+ Autostager::CLI.new.run
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ require 'autostager/logger'
3
+
4
+ module Autostager
5
+ # Start and run the autostager in a loop.
6
+ class CLI
7
+ include Autostager::Logger
8
+
9
+ # Entry point for the app.
10
+ # Stage pull requests on a 30-second loop.
11
+ def run
12
+ trap_interrupt
13
+ loop do
14
+ Autostager.run
15
+ log "Sleep for #{sleep_interval} seconds."
16
+ sleep sleep_interval
17
+ end
18
+ rescue Interrupt
19
+ log 'Exit on interrupt'
20
+ exit!(0)
21
+ end
22
+
23
+ def sleep_interval
24
+ ENV['sleep_interval'] || 30
25
+ end
26
+
27
+ def trap_interrupt
28
+ Signal.trap('INT') do
29
+ log 'Exit on interrupt'
30
+ exit!(0)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ module Autostager
4
+ # Convenience class for exception-handling.
5
+ class GitTimeout < StandardError; end
6
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ require 'syslog'
3
+
4
+ module Autostager
5
+ # Interface to Posix syslog.
6
+ module Logger
7
+ module_function
8
+
9
+ # Log a message to syslog at a specified priority level
10
+ #
11
+ # priority level must be one of:
12
+ #
13
+ # * :crit
14
+ # * :emerg emergency
15
+ # * :alert
16
+ # * :err
17
+ # * :warning
18
+ # * :notice
19
+ # * :info (default if level is not specified)
20
+ # * :debug
21
+ #
22
+ # @param msg [String] the message you want to send to syslog
23
+ # @param level [Symbol] the priority of the message
24
+ def log(msg, level = :info)
25
+ msg = safe(msg)
26
+ $stderr.puts "#{DateTime.now} #{msg}" if ENV.key?('debug')
27
+ Syslog.open($PROGRAM_NAME, Syslog::LOG_PID | Syslog::LOG_CONS) do |s|
28
+ s.send(level, '%s', msg)
29
+ end
30
+ end
31
+
32
+ # Make a string safe for syslog.
33
+ # @see http://goo.gl/hcDiqu
34
+ #
35
+ # @param [String] A string that could be unsafe.
36
+ #
37
+ # @return [String] A safe copy of the original string.
38
+ def safe(str)
39
+ URI.unescape(str)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,123 @@
1
+ # encoding: utf-8
2
+
3
+ module Autostager
4
+ # Convenience class to represent a PR in staging directory.
5
+ class PullRequest
6
+ attr_reader :name
7
+ attr_reader :web_url
8
+ attr_reader :number
9
+ attr_reader :branch
10
+ attr_reader :sha
11
+ attr_reader :clone_url
12
+ attr_reader :upstream_url
13
+ attr_reader :base_dir
14
+
15
+ include Autostager::Logger
16
+
17
+ def initialize(branch, clone_url, base_dir, name, upstream)
18
+ @branch = branch
19
+ @clone_url = clone_url
20
+ @base_dir = base_dir
21
+ @name = name
22
+ @upstream_url = upstream
23
+
24
+ @staging_dir = File.join base_dir, @name
25
+ end
26
+
27
+ def local_sha
28
+ Dir.chdir @staging_dir
29
+ `git log --pretty='%H' HEAD^1..`.chomp
30
+ end
31
+
32
+ def staged?
33
+ File.exist? @staging_dir
34
+ end
35
+
36
+ # How many commits is this branch behind?
37
+ #
38
+ # @param treeish [String] example: 'upstream/production'
39
+ #
40
+ # @return [Fixnum]
41
+ def behind(treeish)
42
+ Dir.chdir @staging_dir
43
+ `git log --oneline ..#{treeish}`.lines.count
44
+ end
45
+
46
+ # A threshold for how many commits a branch can be behind upstream.
47
+ #
48
+ # @note This number is based on the value of same name in
49
+ # spec/spec_helper.rb, so please update the value both
50
+ # here and in spec_helper.rb if you need to change the threshold.
51
+ #
52
+ # @return [Fixnum]
53
+ def behind_threshold
54
+ 10
55
+ end
56
+
57
+ # Is this branch within a reasonable number of commits with upstream?
58
+ #
59
+ # @param treeish [String] example: 'upstream/production'
60
+ #
61
+ # @return [Boolean]
62
+ def up2date?(treeish)
63
+ behind(treeish) <= behind_threshold
64
+ end
65
+
66
+ # Fast-forward this branch to origin.
67
+ # @note This fails if the branch cannot be fast-forwarded.
68
+ #
69
+ # @return [Fixnum] exit status of `git rebase`
70
+ # @return [nil] if `git rebase` fails to exit.
71
+ def rebase
72
+ log "rebase origin/#{@branch}"
73
+ Dir.chdir @staging_dir
74
+ `git rebase origin/#{@branch} &> /dev/null`
75
+ status = $CHILD_STATUS.exitstatus
76
+ update_submodules
77
+ log "#{@branch} is at revision #{local_sha}"
78
+ status
79
+ end
80
+
81
+ def reset_hard
82
+ Dir.chdir @staging_dir
83
+ `git reset --hard origin/#{@branch} &> /dev/null`
84
+ update_submodules
85
+ end
86
+
87
+ def fetch
88
+ log 'git fetch'
89
+ Dir.chdir @staging_dir
90
+ add_upstream_remote
91
+ `git fetch --all --prune &> /dev/null`
92
+ end
93
+
94
+ def update_submodules
95
+ log "update submodules in #{@staging_dir}"
96
+ `git submodule sync &> /dev/null`
97
+ `git submodule update --init --recursive &> /dev/null`
98
+ end
99
+
100
+ def remote?(s)
101
+ Dir.chdir @staging_dir
102
+ remotes = `git remote -v`.split("\n")
103
+ urls = remotes.map { |r| r.split("\t").last.split(' ').first }.uniq
104
+ urls.include?(s)
105
+ end
106
+
107
+ def add_upstream_remote
108
+ Dir.chdir @staging_dir
109
+ return if remote?(@upstream_url)
110
+ log 'add upstream remote'
111
+ `git remote add upstream #{@upstream_url} &> /dev/null`
112
+ `git fetch --prune upstream &> /dev/null`
113
+ end
114
+
115
+ def clone
116
+ log "clone to #{@staging_dir}"
117
+ FileUtils.mkdir_p @base_dir unless File.exist?(@base_dir)
118
+ `git clone -b #{@branch} #{@clone_url} #{@staging_dir} &> /dev/null`
119
+ Dir.chdir @staging_dir
120
+ update_submodules
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ module Autostager
4
+ # Meta-module to call the correct library method
5
+ # for the version of Ruby on which the autostager runs.
6
+ module Timeout
7
+ module_function
8
+
9
+ # The ruby timeout.rb library is unreliable on 1.8.7,
10
+ # so we use a gem to provide timeouts if this script
11
+ # is running on 1.8.7.
12
+ # @see http://ph7spot.com/musings/system-timer
13
+ #
14
+ # @param seconds [Fixnum] Expiration time.
15
+ # @param err [StandardErr] Raise err on expiration.
16
+ # @param block [Block] Code that is subject to expiration.
17
+ #
18
+ # @return [nil]
19
+ def timeout(seconds, err, &block)
20
+ if RUBY_VERSION =~ /1.8/
21
+ require 'system_timer'
22
+ SystemTimer.timeout_after(seconds, err) { block.call }
23
+ else
24
+ require 'timeout'
25
+ ::Timeout.timeout(seconds, err) { block.call }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ # Version constant for the gem.
3
+ module Autostager
4
+ VERSION = '0.0.1'
5
+ end
data/lib/autostager.rb ADDED
@@ -0,0 +1,173 @@
1
+ # encoding: utf-8
2
+ require 'English'
3
+ require 'fileutils'
4
+ require 'autostager/cli'
5
+ require 'autostager/git_timeout'
6
+ require 'autostager/logger'
7
+ require 'autostager/pull_request'
8
+ require 'autostager/timeout'
9
+ require 'autostager/version'
10
+ require 'octokit'
11
+ require 'pp'
12
+
13
+ # Top-level module namespace.
14
+ module Autostager
15
+ module_function
16
+
17
+ extend Autostager::Logger
18
+
19
+ def access_token
20
+ ENV['access_token']
21
+ end
22
+
23
+ # Convert a string into purely alphanumeric characters
24
+ def alphafy(a_string)
25
+ a_string.gsub(/[^a-z0-9_]/i, '_')
26
+ end
27
+
28
+ # rubocop:disable MethodLength
29
+ def stage_upstream
30
+ default_branch = @client.repo(repo_slug).default_branch
31
+ log "===> begin #{default_branch}"
32
+ p = Autostager::PullRequest.new(
33
+ default_branch,
34
+ authenticated_url("https://github.com/#{repo_slug}"),
35
+ base_dir,
36
+ default_branch,
37
+ authenticated_url("https://github.com/#{repo_slug}"),
38
+ )
39
+ p.clone unless p.staged?
40
+ p.fetch
41
+ return if p.rebase
42
+
43
+ # fast-forward failed, so raise awareness.
44
+ @client.create_issue(
45
+ repo_slug,
46
+ "Failed to fast-forward #{default_branch} branch",
47
+ ':bangbang: This probably means somebody force-pushed to the branch.',
48
+ )
49
+ end
50
+ # rubocop:enable MethodLength
51
+
52
+ # rubocop:disable MethodLength
53
+ def process_pull(pr)
54
+ log "===> #{pr.number} #{clone_dir(pr)}"
55
+ p = Autostager::PullRequest.new(
56
+ pr.head.ref,
57
+ authenticated_url(pr.head.repo.clone_url),
58
+ base_dir,
59
+ clone_dir(pr),
60
+ authenticated_url(pr.base.repo.clone_url),
61
+ )
62
+ if p.staged?
63
+ p.fetch
64
+ if pr.head.sha != p.local_sha
65
+ p.reset_hard
66
+ add_comment = true
67
+ else
68
+ log "nothing to do on #{pr.number} #{staging_dir(pr)}"
69
+ add_comment = false
70
+ end
71
+ comment_or_close(p, pr, add_comment)
72
+ else
73
+ p.clone
74
+ comment_or_close(p, pr)
75
+ end
76
+ end
77
+ # rubocop:enable MethodLength
78
+
79
+ # rubocop:disable MethodLength
80
+ def comment_or_close(p, pr, add_comment = true)
81
+ if p.up2date?("upstream/#{pr.base.repo.default_branch}")
82
+ if add_comment
83
+ comment = format(
84
+ ':bell: Staged `%s` at revision %s on %s',
85
+ clone_dir(pr),
86
+ p.local_sha,
87
+ Socket.gethostname,
88
+ )
89
+ client.add_comment repo_slug, pr.number, comment
90
+ log comment
91
+ end
92
+ else
93
+ comment = format(
94
+ ':boom: Unstaged since %s is dangerously behind upstream.',
95
+ clone_dir(pr),
96
+ )
97
+ FileUtils.rm_rf staging_dir, secure: true
98
+ client.add_comment repo_slug, pr.number, comment
99
+ client.close_issue repo_slug, pr.number
100
+ log comment
101
+ end
102
+ end
103
+ # rubocop:enable MethodLength
104
+
105
+ def authenticated_url(s)
106
+ s.dup.sub!(%r{^(https://)(.*)}, '\1' + access_token + '@\2')
107
+ end
108
+
109
+ def base_dir
110
+ ENV['base_dir'] || '/opt/puppet/environments'
111
+ end
112
+
113
+ def clone_dir(pr)
114
+ alphafy(pr.head.label)
115
+ end
116
+
117
+ def staging_dir(pr)
118
+ File.join base_dir, clone_dir(pr)
119
+ end
120
+
121
+ def repo_slug
122
+ ENV['repo_slug']
123
+ end
124
+
125
+ def client
126
+ @client ||= Octokit::Client.new(access_token: access_token)
127
+ end
128
+
129
+ # A list of directories we never discard.
130
+ def safe_dirs
131
+ [
132
+ '.',
133
+ '..',
134
+ 'production',
135
+ ]
136
+ end
137
+
138
+ # rubocop:disable MethodLength
139
+ def run
140
+ Octokit.auto_paginate = true
141
+ user = client.user
142
+ user.login
143
+
144
+ # Get open PRs.
145
+ prs = client.pulls(repo_slug)
146
+
147
+ # Set of PR clone dirs.
148
+ new_clones = prs.map { |pr| clone_dir(pr) }
149
+
150
+ # Discard directories that do not have open PRs.
151
+ if File.exist?(base_dir)
152
+ discard_dirs = Dir.entries(base_dir) - safe_dirs - new_clones
153
+ discard_dirs.map { |d| File.join(base_dir, d) }.each do |dir|
154
+ log "===> Unstage #{dir} since PR is closed."
155
+ FileUtils.rm_rf dir, secure: true
156
+ end
157
+ end
158
+
159
+ # Process current PRs.
160
+ Autostager::Timeout.timeout(120, GitTimeout) do
161
+ prs.each { |pr| process_pull pr }
162
+ end
163
+
164
+ # Handle the default branch differently because
165
+ # we only ever rebase, never force-push.
166
+ stage_upstream
167
+ rescue Octokit::Unauthorized => e
168
+ $stderr.puts e.message
169
+ $stderr.puts 'Did you export "access_token" and "repo_slug"?'
170
+ exit(1)
171
+ end
172
+ # rubocop:enable MethodLength
173
+ end
data/script/bootstrap ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ # Import smitty.
5
+ . script/functions
6
+
7
+ git remote show upstream &> /dev/null || smitty git remote add upstream https://github.com/jumanjihouse/autostager.git
8
+
9
+ rm -f Gemfile.lock
10
+ smitty bundle update 2> /dev/null || smitty bundle install --path=~/.bundle
data/script/functions ADDED
@@ -0,0 +1,10 @@
1
+ smitty() {
2
+ echo; echo
3
+ echo -e "[INFO] $@"
4
+ "$@"
5
+ }
6
+
7
+ err() {
8
+ echo "[ERROR] $@" >&2
9
+ exit 1
10
+ }
data/script/test ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ echo "===> Bundling..."
5
+ script/bootstrap
6
+
7
+ echo "===> Running rspec"
8
+ bundle exec rake test
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+ # Ensure rake finds something in this directory
3
+ # to avoid running unit tests twice.
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ require 'minitest'
3
+ require 'mocha/setup'
4
+ require 'English'
5
+ require 'tempfile'
6
+ require 'pp'
7
+
8
+ RSpec.configure do |c|
9
+ c.mock_with :mocha
10
+ c.color = true
11
+ c.formatter = 'doc'
12
+
13
+ # Allow both "should" and "expect" syntax.
14
+ # https://www.relishapp.com/rspec/rspec-expectations/docs/syntax-configuration
15
+ c.expect_with :rspec do |e|
16
+ e.syntax = [:should, :expect]
17
+ end
18
+
19
+ # Fail overall as soon as first test fails.
20
+ # Fail fast to reduce duration of test runs.
21
+ # IOW get out of the way so that the next pull request gets tested.
22
+ c.fail_fast = true
23
+
24
+ # Make it easy for spec tests to find fixtures.
25
+ c.add_setting :fixture_path, default: nil
26
+ c.fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))
27
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'friction'
4
+ require 'stringio'
5
+
6
+ # Monkey-patch kernel to capture stdout
7
+ # as workaround for friction gem. bleh.
8
+ #
9
+ # @todo submit PR against friction.
10
+ module Kernel
11
+ def capture_stdout
12
+ real_out, out = $stdout, StringIO.new
13
+ $stdout = out
14
+ yield
15
+ return out.string
16
+ ensure
17
+ $stdout = real_out
18
+ end
19
+ end
20
+
21
+ describe 'contributor friction' do
22
+ it 'there should not be any' do
23
+ out = capture_stdout { Friction.run! }
24
+ out.should =~ /Everything is in order/
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,260 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puppet-autostager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Paul Morgan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: friction
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-core
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ - - <=
105
+ - !ruby/object:Gem::Version
106
+ version: '4.0'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '3.0'
114
+ - - <=
115
+ - !ruby/object:Gem::Version
116
+ version: '4.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec-expectations
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rspec-mocks
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rubocop
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - '>='
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: thor
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: json
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - '>='
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ type: :runtime
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - '>='
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ - !ruby/object:Gem::Dependency
188
+ name: octokit
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ~>
192
+ - !ruby/object:Gem::Version
193
+ version: '3.0'
194
+ type: :runtime
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ~>
199
+ - !ruby/object:Gem::Version
200
+ version: '3.0'
201
+ description: Create a puppet enviroment for each pull request
202
+ email:
203
+ - jumanjiman@gmail.com
204
+ executables:
205
+ - autostager
206
+ extensions: []
207
+ extra_rdoc_files: []
208
+ files:
209
+ - .editorconfig
210
+ - .gitignore
211
+ - .rubocop.yml
212
+ - .travis.yml
213
+ - CONTRIBUTING.md
214
+ - Gemfile
215
+ - LICENSE.txt
216
+ - README.md
217
+ - Rakefile
218
+ - autostager.gemspec
219
+ - bin/autostager
220
+ - lib/autostager.rb
221
+ - lib/autostager/cli.rb
222
+ - lib/autostager/git_timeout.rb
223
+ - lib/autostager/logger.rb
224
+ - lib/autostager/pull_request.rb
225
+ - lib/autostager/timeout.rb
226
+ - lib/autostager/version.rb
227
+ - script/bootstrap
228
+ - script/functions
229
+ - script/test
230
+ - spec/functional/placeholder_spec.rb
231
+ - spec/spec_helper.rb
232
+ - spec/unit/friction_spec.rb
233
+ homepage: https://github.com/jumanjiman/autostager
234
+ licenses:
235
+ - MIT
236
+ metadata: {}
237
+ post_install_message:
238
+ rdoc_options: []
239
+ require_paths:
240
+ - lib
241
+ required_ruby_version: !ruby/object:Gem::Requirement
242
+ requirements:
243
+ - - '>='
244
+ - !ruby/object:Gem::Version
245
+ version: '0'
246
+ required_rubygems_version: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - '>='
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ requirements: []
252
+ rubyforge_project:
253
+ rubygems_version: 2.1.11
254
+ signing_key:
255
+ specification_version: 4
256
+ summary: Create a puppet enviroment for each pull request
257
+ test_files:
258
+ - spec/functional/placeholder_spec.rb
259
+ - spec/spec_helper.rb
260
+ - spec/unit/friction_spec.rb