gitcamp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 gitcamp.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Simpleweb Ltd.
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,24 @@
1
+ ## Gitcamp
2
+
3
+ Gitcamp is a handy command line tool for syncing GitHub issues & milestones with Basecamp todo lists, and visa-versa.
4
+
5
+ ### Requirements
6
+
7
+ You'll need to have Rubygems installed. If you're on a Mac then you've probably already got it.
8
+
9
+ Run
10
+
11
+ $ gem -v
12
+
13
+ to check. If not, you'll need to [install it](http://rubygems.org/pages/download).
14
+
15
+
16
+ ### Installation
17
+
18
+ $ gem install gitcamp
19
+
20
+ ### Usage
21
+
22
+ Creating a todo list in Basecamp
23
+
24
+ $ gitcamp todolist
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/gitcamp ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gitcamp'
4
+ Gitcamp::Cli.start
data/gitcamp.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/gitcamp/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Paul Springett"]
6
+ gem.email = ["paul@simpleweb.co.uk"]
7
+ gem.description = %q{Gitcamp is a handy command line tool for syncing GitHub issues & milestones with Basecamp todo lists, and visa-versa.}
8
+ gem.summary = %q{Gitcamp is a handy command line tool for syncing GitHub issues & milestones with Basecamp todo lists, and visa-versa.}
9
+ gem.homepage = "http://github.com/simpleweb/gitcamp"
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 = "gitcamp"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Gitcamp::VERSION
17
+
18
+ gem.add_dependency 'thor', '~> 0.18.1'
19
+ gem.add_dependency 'octokit', '~> 1.24.0'
20
+ gem.add_dependency 'highline', '~> 1.6.19'
21
+ gem.add_dependency 'json', '~> 1.7.7'
22
+ gem.add_dependency 'basecamp', '~> 0.0.9'
23
+
24
+ gem.add_development_dependency 'rake', '~> 10.0.4'
25
+ gem.add_development_dependency 'rspec', '~> 2.13.0'
26
+ end
data/lib/gitcamp.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'gitcamp/version'
2
+ require 'thor'
3
+ require 'octokit'
4
+ require 'highline'
5
+ require 'basecamp'
6
+ require 'hashie/mash'
7
+
8
+ require 'gitcamp/config'
9
+ require 'gitcamp/github/auth'
10
+ require 'gitcamp/basecamp/auth'
11
+ require 'gitcamp/basecamp/todo'
12
+ require 'gitcamp/cli'
13
+
14
+ module Basecamp
15
+ module API
16
+ Classic = ::Basecamp
17
+ end
18
+ end
@@ -0,0 +1,60 @@
1
+ module Gitcamp
2
+ module Basecamp
3
+ class Auth < Thor
4
+
5
+ include Thor::Actions
6
+ attr_reader :username
7
+
8
+ desc 'login', 'authenticate with Basecamp and store credentials'
9
+ def login
10
+ say 'Authenticating with Basecamp', Thor::Shell::Color::YELLOW
11
+
12
+ netrc = Netrc.read
13
+
14
+ domain = 'simple-web.basecamphq.com'
15
+ if netrc[domain]
16
+ @username, token = netrc[domain]
17
+
18
+ Basecamp::API::Classic.establish_connection!(domain, token, 'X', true)
19
+
20
+ begin
21
+ Basecamp::API::Classic::Person.me
22
+ say "Authenticated as #{@username}", Thor::Shell::Color::GREEN
23
+ rescue Octokit::Unauthorized => ex
24
+ puts "Failed to authenticate you with those Basecamp credentials"
25
+ exit false
26
+ end
27
+ else
28
+ @username = ask 'Username:'
29
+ password = ask_password 'Password:'
30
+
31
+ Basecamp::API::Classic.establish_connection!(domain, @username, password, true)
32
+
33
+ begin
34
+ Basecamp::API::Classic::Person.me
35
+ say "Authenticated as #{@username}", Thor::Shell::Color::GREEN
36
+ rescue Octokit::Unauthorized => ex
37
+ puts "Failed to authenticate you with those Basecamp credentials"
38
+ exit false
39
+ end
40
+
41
+ token = Basecamp::API::Classic::Person.me.token
42
+
43
+ unless netrc[domain]
44
+ netrc[domain] = @username, token
45
+ netrc.save
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def ask_password(message)
53
+ HighLine.new.ask(message) do |q|
54
+ q.echo = false
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,52 @@
1
+ module Gitcamp
2
+ module Basecamp
3
+ class Todo
4
+ attr_reader :list, :issue, :item, :title, :description
5
+
6
+ def initialize(options = {})
7
+ unless options[:issue]
8
+ raise ArgumentError, 'no GitHub Issue given'
9
+ end
10
+
11
+ @list = options[:list]
12
+ @issue = options[:issue]
13
+
14
+ @title = @issue.title.gsub(/\[[\d\.]*\]\s+/, '')
15
+ @title = "##{issue.number} #{@title}"
16
+ end
17
+
18
+ def save
19
+ find_or_build_todo
20
+
21
+ if item.save
22
+ say "Processed todo #{title} in Basecamp"
23
+ end
24
+
25
+ create_or_update_comment
26
+ end
27
+
28
+ private
29
+
30
+ def find_or_build_todo
31
+ todo_items = Basecamp::API::Classic::TodoItem.find(:all, :params => { :todo_list_id => list.id })
32
+ @item = todo_items.find { |tdi| tdi.content =~ %r{\A##{issue.number}} }
33
+
34
+ if @item
35
+ @item.content = @title
36
+ else
37
+ @item = Basecamp::API::Classic::TodoItem.new(:content => @title, :notify => false, :todo_list_id => list.id)
38
+ end
39
+ end
40
+
41
+ def create_or_update_comment
42
+ return if issue.body.blank?
43
+
44
+ comment = @item.comments.find { |cm| cm.body =~ %r{\A\[##{issue.number}\]} }
45
+ comment ||= Basecamp::API::Classic::Comment.new(:todo_item_id => item.id, :use_textile => true)
46
+
47
+ comment.body = "[##{issue.number}] *Description:* #{issue.body}"
48
+ comment.save
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,82 @@
1
+ require 'highline/import'
2
+ require 'basecamp'
3
+
4
+ module Gitcamp
5
+ class Cli < Thor
6
+ include Thor::Actions
7
+
8
+ desc 'todolist', 'creates BaseCamp todo list from a milestone of GitHub issues'
9
+ def todolist
10
+
11
+ # Authenicate with Github
12
+ auth = Gitcamp::Github::Auth.new
13
+ @github = auth.login
14
+
15
+ # What repo are we working from?
16
+ repo = ask 'Enter a GitHub repo name (eg. owner/repo) to pick milestones from:'
17
+
18
+ # Get all milestones
19
+ milestones = @github.list_milestones(repo)
20
+
21
+ # Ask user to select a milestone to use
22
+ choose do |menu|
23
+ menu.prompt = 'Which milestone do you want to import?'
24
+ milestones.each do |milestone|
25
+ menu.choice "#{milestone.title} (#{milestone.open_issues} open issues)" do
26
+ @milestone = milestone
27
+ end
28
+ end
29
+ end
30
+
31
+ say "Chosen milestone: #{@milestone.title}"
32
+
33
+ # Authenticate with Basecamp
34
+ auth = Gitcamp::Basecamp::Auth.new
35
+ auth.login
36
+
37
+ # Get all active projects
38
+ projects = Basecamp::API::Classic::Project.all.select { |project| project.status == 'active' }
39
+
40
+ # Ask user to select a project
41
+ choose do |menu|
42
+ menu.prompt = 'Which project do you want to create the TODO list in?'
43
+ projects.each do |project|
44
+ menu.choice "#{project.name}" do
45
+ @project = project
46
+ end
47
+ end
48
+ end
49
+
50
+ say "Chosen project: #{@project.name}"
51
+
52
+ # Confirm pending operation to user?
53
+ if yes? "Are you sure you want to create a Todo list named '#{@milestone.title}' in the #{@project.name} Basecamp project and add the #{@milestone.open_issues} issues as Todo items? (y/n)", Thor::Shell::Color::CYAN
54
+
55
+ # Try to find an existing TodoList in Basecamp
56
+ todo_lists = Basecamp::API::Classic::TodoList.all(@project.id)
57
+ todo_list = todo_lists.find { |tdl| tdl.name == @milestone.title }
58
+
59
+ # If it doesn't exist, create one
60
+ unless todo_list
61
+ todo_list = Basecamp::API::Classic::TodoList.new(:name => @milestone.title, :description => @milestone.description, :project_id => @project.id)
62
+ todo_list.save
63
+
64
+ say "Created todo list: #{todo_list.name}"
65
+ else
66
+ say "Using existing todo list: #{todo_list.name}"
67
+ end
68
+
69
+ issues = @github.list_issues(repo, :milestone => @milestone.number)
70
+ issues.each do |issue|
71
+ todo = Gitcamp::Basecamp::Todo.new(list: todo_list, issue: issue)
72
+ todo.save
73
+ end
74
+
75
+ else
76
+ say 'No action taken, exiting'
77
+ exit true
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,4 @@
1
+ Octokit.configure do |c|
2
+ c.client_id = '8bb9517f617ab5a78f6e'
3
+ c.client_secret = '419463b8afd8100914f80eb1b87cf8faec381b8a'
4
+ end
@@ -0,0 +1,52 @@
1
+ module Gitcamp
2
+ module Github
3
+ class Auth < Thor
4
+ include Thor::Actions
5
+ attr_reader :username, :client
6
+
7
+ desc 'login', 'authenticate with GitHub, store credentials and generate with token'
8
+ def login
9
+ say 'Authenticating with GitHub', Thor::Shell::Color::YELLOW
10
+
11
+ netrc = Netrc.read
12
+
13
+ if netrc['api.github.com']
14
+ @username, oauth_token = netrc['api.github.com']
15
+ else
16
+ @username = ask('Username:')
17
+ password = ask_password('Password:')
18
+
19
+ begin
20
+ client = Octokit::Client.new(:login => @username, :password => password)
21
+ rescue Octokit::Unauthorized => ex
22
+ puts "Failed to authenticate you with those GitHub credentials"
23
+ exit false
24
+ end
25
+
26
+ auth = client.create_authorization(:scopes => %w[repo])
27
+ oauth_token = auth.token
28
+
29
+ unless netrc['api.github.com']
30
+ netrc['api.github.com'] = @username, auth.token
31
+ netrc.save
32
+ end
33
+ end
34
+
35
+ client = Octokit::Client.new(:login => @username, :oauth_token => oauth_token)
36
+
37
+ say "Authenticated as #{@username}", Thor::Shell::Color::GREEN
38
+
39
+ client
40
+ end
41
+
42
+ private
43
+
44
+ def ask_password(message)
45
+ HighLine.new.ask(message) do |q|
46
+ q.echo = false
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Gitcamp
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitcamp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paul Springett
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.18.1
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.18.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: octokit
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.24.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.24.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: highline
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.6.19
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.6.19
62
+ - !ruby/object:Gem::Dependency
63
+ name: json
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.7.7
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.7.7
78
+ - !ruby/object:Gem::Dependency
79
+ name: basecamp
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.0.9
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.0.9
94
+ - !ruby/object:Gem::Dependency
95
+ name: rake
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 10.0.4
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 10.0.4
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 2.13.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 2.13.0
126
+ description: Gitcamp is a handy command line tool for syncing GitHub issues & milestones
127
+ with Basecamp todo lists, and visa-versa.
128
+ email:
129
+ - paul@simpleweb.co.uk
130
+ executables:
131
+ - gitcamp
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - .gitignore
136
+ - Gemfile
137
+ - LICENSE
138
+ - README.md
139
+ - Rakefile
140
+ - bin/gitcamp
141
+ - gitcamp.gemspec
142
+ - lib/gitcamp.rb
143
+ - lib/gitcamp/basecamp/auth.rb
144
+ - lib/gitcamp/basecamp/todo.rb
145
+ - lib/gitcamp/cli.rb
146
+ - lib/gitcamp/config.rb
147
+ - lib/gitcamp/github/auth.rb
148
+ - lib/gitcamp/version.rb
149
+ homepage: http://github.com/simpleweb/gitcamp
150
+ licenses: []
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ none: false
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ requirements: []
168
+ rubyforge_project:
169
+ rubygems_version: 1.8.24
170
+ signing_key:
171
+ specification_version: 3
172
+ summary: Gitcamp is a handy command line tool for syncing GitHub issues & milestones
173
+ with Basecamp todo lists, and visa-versa.
174
+ test_files: []
175
+ has_rdoc: