releasecop 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 158909c81fb2737e9a7d229325093bc2e653dc33
4
+ data.tar.gz: 6041f1fc60e6e0769a702394794bdf7a18d1fa14
5
+ SHA512:
6
+ metadata.gz: b13adbfc0815e11425e9bdef6d7b6fcff6ddf1338fb0ad10ab629fbfda535955dcdc189fd70fbdf1c511741a8d1470b25d8270ec6d2fb486a9f1484bc2d09abe
7
+ data.tar.gz: 4685de9511b70429d55e73ce5becd6d00f9324bf2893fdfd3d59294fca69b825d23cbe8355b544fd6ae1ce4180d9f0fe658059ce65cad66da482fb7369eb8161
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in releasecop.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Joey Aghion
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.
@@ -0,0 +1,49 @@
1
+ # Releasecop
2
+
3
+ Given a list of projects and environments pipelines, report which environments are "behind" and by which commits.
4
+
5
+ ## Installation
6
+
7
+ gem install releasecop
8
+
9
+ ## Usage
10
+
11
+ Open the manifest file, which defines projects to monitor:
12
+
13
+ releasecop edit
14
+
15
+ In the manifest, each project lists the repositories/branches to whch code is deployed _in order of promotion_. E.g., master branch for development, a heroku remote for staging, and a different heroku remote for production. An example manifest:
16
+
17
+ {
18
+ "projects": {
19
+ "charge": [
20
+ {"name": "master", "git": "git@github.com:artsy/charge.git"},
21
+ {"name": "staging", "git": "git@heroku.com:charge-staging.git"},
22
+ {"name": "production", "git": "git@heroku.com:charge-production.git"}
23
+ ],
24
+ "lattice": [
25
+ {"name": "master", "git": "git@github.com:artsy/lattice.git"},
26
+ {"name": "production", "git": "git@heroku.com:artsy-lattice-production.git"}
27
+ ]
28
+ }
29
+ }
30
+
31
+ To check the release status of a project:
32
+
33
+ releasecop check [PROJECT]
34
+
35
+ Example output:
36
+
37
+ charge...
38
+ staging is up-to-date with master
39
+ production is up-to-date with staging
40
+ lattice...
41
+ production is behind master by:
42
+ 4557f60 2015-02-02 upgrade to 3.9 (joeschmo19)
43
+ 2 project(s) checked. 1 environment(s) out-of-date.
44
+
45
+ To check all:
46
+
47
+ releasecop check --all
48
+
49
+ Copyright (c) 2015 Joey Aghion
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'releasecop'
4
+ Releasecop::Cli.start(ARGV)
@@ -0,0 +1,12 @@
1
+ require "releasecop/version"
2
+ require 'thor'
3
+ require 'shellwords'
4
+ require 'json'
5
+ require "releasecop/checker"
6
+ require "releasecop/cli"
7
+
8
+ module Releasecop
9
+ CONFIG_DIR = File.join(Dir.home, '.releasecop')
10
+ MANIFEST_PATH = File.join(CONFIG_DIR, 'manifest.json')
11
+ DEFAULT_MANIFEST = "{\n \"projects\": {\n }\n}"
12
+ end
@@ -0,0 +1,37 @@
1
+ module Releasecop
2
+ class Checker
3
+ attr_accessor :name, :envs
4
+
5
+ def initialize(name, envs)
6
+ self.name = name
7
+ self.envs = envs
8
+ end
9
+
10
+ # Reports status of individual project. Returns count of out-of-date environments.
11
+ def check
12
+ puts "#{name}..."
13
+ unreleased = 0
14
+ Dir.chdir(CONFIG_DIR) do
15
+ `git clone #{envs.first['git']} --bare #{name} > /dev/null 2>&1`
16
+ Dir.chdir(name) do
17
+ envs.each do |env|
18
+ `git remote add #{env['name']} #{env['git']} > /dev/null 2>&1`
19
+ `git fetch #{env['name']} > /dev/null 2>&1`
20
+ end
21
+ envs.each_cons(2) do |ahead, behind|
22
+ log = `git log #{behind['name']}/#{behind['branch'] || 'master'}..#{ahead['name']}/#{ahead['branch'] || 'master'} --pretty=format:"%h %ad %s (%an)" --date=short --no-merges`
23
+ if log == ''
24
+ puts " #{behind['name']} is up-to-date with #{ahead['name']}\n"
25
+ else
26
+ puts " #{behind['name']} is behind #{ahead['name']} by:"
27
+ log.lines.each { |l| puts " #{l}" }
28
+ unreleased += 1
29
+ end
30
+ end
31
+ end
32
+ end
33
+ unreleased
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ module Releasecop
2
+ class Cli < Thor
3
+ def self.exit_on_failure?
4
+ true
5
+ end
6
+
7
+ desc "edit", "Open manifest file for editing"
8
+ def edit
9
+ editor = ENV['EDITOR']
10
+ raise Thor::Error, "To open manifest, first set $EDITOR" if editor.nil? || editor.empty?
11
+ command = Shellwords.split(editor) + [Releasecop::MANIFEST_PATH]
12
+ initialize_manifest! unless File.exist?(Releasecop::MANIFEST_PATH)
13
+ system(*command)
14
+ end
15
+
16
+ desc "check [PROJECT]", "Check the release status of one or all projects"
17
+ option :all
18
+ def check(project = nil)
19
+ raise Thor::Error, "Must specify a PROJECT or --all" if project.nil? && !options[:all]
20
+
21
+ initialize_manifest! unless File.exist?(Releasecop::MANIFEST_PATH)
22
+ selected = options[:all] ? manifest['projects'] : manifest['projects'].select{|k,v| k == project }
23
+ raise Thor::Error, "No projects found." if selected.empty?
24
+
25
+ unreleased = 0
26
+ selected.each do |name, envs|
27
+ unreleased += Releasecop::Checker.new(name, envs).check
28
+ end
29
+
30
+ $stderr.puts "#{selected.size} project(s) checked. #{unreleased} environment(s) out-of-date."
31
+ exit 1 if unreleased > 0
32
+ end
33
+
34
+ private
35
+
36
+ def manifest
37
+ JSON.parse(File.read(Releasecop::MANIFEST_PATH))
38
+ end
39
+
40
+ def initialize_dir!
41
+ FileUtils.mkdir_p(Release::CONFIG_DIR)
42
+ end
43
+
44
+ def initialize_manifest!
45
+ initialize_dir!
46
+ File.open(Releasecop::MANIFEST_PATH, 'w') { |f| f.write(Releasecop::DEFAULT_MANIFEST) }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Releasecop
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'releasecop/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "releasecop"
8
+ spec.version = Releasecop::VERSION
9
+ spec.authors = ["Joey Aghion"]
10
+ spec.email = ["joey@aghion.com"]
11
+ spec.summary = %q{Given a list of projects and environments pipelines, report which environments are "behind" and by which commits.}
12
+ spec.homepage = "https://github.com/joeyAghion/releasecop"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "thor"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: releasecop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Joey Aghion
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description:
56
+ email:
57
+ - joey@aghion.com
58
+ executables:
59
+ - releasecop
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - bin/releasecop
69
+ - lib/releasecop.rb
70
+ - lib/releasecop/checker.rb
71
+ - lib/releasecop/cli.rb
72
+ - lib/releasecop/version.rb
73
+ - releasecop.gemspec
74
+ homepage: https://github.com/joeyAghion/releasecop
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.0.14
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Given a list of projects and environments pipelines, report which environments
98
+ are "behind" and by which commits.
99
+ test_files: []