puppet-autostager 0.0.1

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.
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