octaccord 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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +62 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +9 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.org +95 -0
  8. data/Rakefile +7 -0
  9. data/bin/octaccord +311 -0
  10. data/examples/Itr0000-template.md.erb +93 -0
  11. data/examples/octaccord-completion.zsh +11 -0
  12. data/lib/extensions.rb +2 -0
  13. data/lib/extensions/octokit.rb +16 -0
  14. data/lib/octaccord.rb +10 -0
  15. data/lib/octaccord/command.rb +16 -0
  16. data/lib/octaccord/command/add_collaborator.rb +34 -0
  17. data/lib/octaccord/command/comments.rb +50 -0
  18. data/lib/octaccord/command/completions.rb +56 -0
  19. data/lib/octaccord/command/create_iteration.rb +21 -0
  20. data/lib/octaccord/command/get_team_members.rb +18 -0
  21. data/lib/octaccord/command/info.rb +18 -0
  22. data/lib/octaccord/command/label.rb +16 -0
  23. data/lib/octaccord/command/scan.rb +122 -0
  24. data/lib/octaccord/command/show.rb +28 -0
  25. data/lib/octaccord/command/update_issues.rb +28 -0
  26. data/lib/octaccord/errors.rb +2 -0
  27. data/lib/octaccord/formatter.rb +105 -0
  28. data/lib/octaccord/formatter/comment.rb +58 -0
  29. data/lib/octaccord/formatter/debug.rb +17 -0
  30. data/lib/octaccord/formatter/issue.rb +134 -0
  31. data/lib/octaccord/formatter/list.rb +36 -0
  32. data/lib/octaccord/formatter/number.rb +14 -0
  33. data/lib/octaccord/formatter/pbl.rb +23 -0
  34. data/lib/octaccord/formatter/table.rb +17 -0
  35. data/lib/octaccord/formatter/text.rb +14 -0
  36. data/lib/octaccord/formatter/user.rb +42 -0
  37. data/lib/octaccord/iteration.rb +61 -0
  38. data/lib/octaccord/version.rb +3 -0
  39. data/octaccord.gemspec +24 -0
  40. data/spec/octaccord_spec.rb +11 -0
  41. data/spec/spec_helper.rb +2 -0
  42. metadata +130 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f41906f4168cda2e216acac50a102ad60bcfbedc
4
+ data.tar.gz: 3a19307ac59fbb1a20c21d1086a711ff04c5c417
5
+ SHA512:
6
+ metadata.gz: 8213ef2b4423e1cc6b0ac200a1d63d8a8f223710668ffd10773ae05f0fe3146f1561c3047e5283ada35162139298c69f8f580952994f3740dbed75f2c5845808
7
+ data.tar.gz: 24c88ad022a415bbff508c8a515f7f3c7aec1d28e2217874abaaebc8f571eee149e918e1b36b58564edc628711bd9bf402c17ab21c5cf08860c927900dbdf616
@@ -0,0 +1,62 @@
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
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ #
24
+ # Added from https://raw.github.com/github/gitignore/master/Ruby.gitignore
25
+ #
26
+ *.gem
27
+ *.rbc
28
+ /.config
29
+ /coverage/
30
+ /InstalledFiles
31
+ /pkg/
32
+ /spec/reports/
33
+ /test/tmp/
34
+ /test/version_tmp/
35
+ /tmp/
36
+
37
+ ## Specific to RubyMotion:
38
+ .dat*
39
+ .repl_history
40
+ build/
41
+
42
+ ## Documentation cache and generated files:
43
+ /.yardoc/
44
+ /_yardoc/
45
+ /doc/
46
+ /rdoc/
47
+
48
+ ## Environment normalisation:
49
+ /.bundle/
50
+ /lib/bundler/man/
51
+
52
+ # for a library or gem, you might want to ignore these files since the code is
53
+ # intended to run in multiple environments; otherwise, check them in:
54
+ # Gemfile.lock
55
+ .ruby-version
56
+ .ruby-gemset
57
+
58
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
59
+ .rvmrc
60
+
61
+ /vendor/bundle/
62
+ /attic/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in octaccord.gemspec
4
+ gemspec
5
+ gem "octokit"
6
+ gem "pit"
7
+ gem "thor"
8
+ gem "rugged"
9
+ gem 'faraday-http-cache'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Yoshinari Nomura
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,95 @@
1
+ #+TITLE: octaccord
2
+ #+AUTHOR: Nomura Laboratory, Yoshinari Nomura
3
+ #+EMAIL:
4
+ #+DATE: 2014-07-26
5
+ #+OPTIONS: H:3 num:2 toc:nil
6
+ #+OPTIONS: ^:nil @:t \n:nil ::t |:t f:t TeX:t
7
+ #+OPTIONS: skip:nil
8
+ #+OPTIONS: author:t
9
+ #+OPTIONS: email:nil
10
+ #+OPTIONS: creator:nil
11
+ #+OPTIONS: timestamp:nil
12
+ #+OPTIONS: timestamps:nil
13
+ #+OPTIONS: d:nil
14
+ #+OPTIONS: tags:t
15
+ #+TEXT:
16
+ #+DESCRIPTION:
17
+ #+KEYWORDS:
18
+ #+LANGUAGE: ja
19
+ #+LATEX_CLASS: jsarticle
20
+ #+LATEX_CLASS_OPTIONS: [a4j]
21
+ # #+LATEX_HEADER: \usepackage{plain-article}
22
+ # #+LATEX_HEADER: \renewcommand\maketitle{}
23
+ # #+LATEX_HEADER: \pagestyle{empty}
24
+ # #+LaTeX: \thispagestyle{empty}
25
+
26
+ * Octaccord
27
+ ** What is octaccord?
28
+
29
+ Octaccord is a small CLI tool to manipulate issues (tickets) for the GitHub.
30
+ It reduces some complex operations on the issues of GitHub:
31
+
32
+ + Bulk label update with complex search queries
33
+ + Pretty issue printer in many format including Markdown
34
+ + Extract statistic information to the GitHub Wiki
35
+
36
+ ** INSTALL for developers:
37
+ Current code is a very alpha and kind of proof-of-concept demonstration.
38
+ I recommend you not to install via usual gem-style procedure.
39
+
40
+ 1) Install rbenv + ruby-build
41
+ (see https://github.com/sstephenson/rbenv#basic-github-checkout for details)
42
+ #+BEGIN_SRC shell-script
43
+ $ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
44
+ $ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
45
+ # Edit your shell dot files to add some path and environment variables.
46
+ #+END_SRC
47
+
48
+ 2) Install Latest Ruby and bundler
49
+ #+BEGIN_SRC shell-script
50
+ # Install ruby 2.1.2
51
+ $ rbenv install 2.1.2
52
+
53
+ # Installation check
54
+ $ rbenv global 2.1.2
55
+ $ ruby -v # -> You will see: ruby 2.1.2...
56
+
57
+ # Install bundler for your new Ruby
58
+ $ gem install bundler
59
+
60
+ # Get back to your sytem default Ruby if you want
61
+ $ rbenv global system # say, /usr/bin/ruby
62
+ $ ruby -v
63
+ #+END_SRC
64
+
65
+ 3) Clone octaccord from github
66
+ #+BEGIN_SRC shell-script
67
+ $ git clone git@github.com:nomlab/octaccord.git ~/src/octaccord
68
+ #+END_SRC
69
+
70
+ 4) Set default ruby version in octaccord project
71
+ #+BEGIN_SRC shell-script
72
+ $ cd ~/src/octaccord
73
+ $ echo '2.1.2' > .ruby-version
74
+ $ ruby -v # -> You will see: ruby 2.1.2...
75
+ #+END_SRC
76
+
77
+ 5) Install requied gem packages in sandbox ~/src/octaccord/vendor/bundle
78
+ #+BEGIN_SRC shell-script
79
+ $ cd ~/src/octaccord
80
+ $ bundle install --path vendor/bundle
81
+ #+END_SRC
82
+
83
+ 6) Setup data-cache and auth-cache directory
84
+ #+BEGIN_SRC shell-script
85
+ $ mkdir -p ~/.cache/octaccord
86
+ $ mkdir -p ~/.pit
87
+ #+END_SRC
88
+
89
+ 7) Check if octaccord is alive.
90
+ #+BEGIN_SRC shell-script
91
+ $ ~/src/octaccord/bin/octaccord scan nomlab/octaccord
92
+ #+END_SRC
93
+
94
+ You may add ~/src/octaccord/bin directory to your $PATH for dogfooding.
95
+ If you are zsh user, [[file:examples/octaccord-completion.zsh]] would help you.
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if File.symlink?(__FILE__) and ENV["RBENV_VERSION"]
4
+ ENV["RBENV_VERSION"] = nil
5
+ shims_path = File.expand_path("shims", ENV["RBENV_ROOT"])
6
+ ENV["PATH"] = shims_path + ":" + ENV["PATH"]
7
+ exec(File.readlink(__FILE__), *ARGV)
8
+ end
9
+
10
+ ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
11
+
12
+ require 'rubygems'
13
+ require 'bundler/setup'
14
+ Bundler.require
15
+
16
+ require "time"
17
+ require "shellwords"
18
+ require "pp"
19
+
20
+ Encoding.default_external="UTF-8"
21
+
22
+ require "dbm"
23
+ class FileStore
24
+ CACHE_FILE = "#{ENV["HOME"]}/.cache/octaccord/http_cache"
25
+
26
+ def initialize
27
+ @cache = DBM.open(CACHE_FILE, 0666)
28
+ end
29
+
30
+ def read(key)
31
+ if value = @cache[key]
32
+ STDERR.puts "HIT #{key}" if $OCTACCORD_DEBUG
33
+
34
+ else
35
+ STDERR.puts "MISS #{key}" if $OCTACCORD_DEBUG
36
+ end
37
+ value
38
+ end
39
+
40
+ def write(key, value)
41
+ @cache[key] = value
42
+ end
43
+ end
44
+
45
+ class OctaccordCLI < Thor
46
+ check_unknown_options! :except => :completions
47
+ package_name 'Octaccord'
48
+
49
+ class_option :debug, :type => :boolean, :desc => "Set debug flag"
50
+
51
+ map ["--version", "-v"] => :version
52
+
53
+ default_command :help
54
+ map ["--help", "-h"] => :help
55
+
56
+ desc "version", "Show version"
57
+ def version
58
+ puts Octaccord::VERSION
59
+ end
60
+
61
+ ################################################################
62
+ ## Command: scan
63
+ ################################################################
64
+ desc "scan REPOSITORY [OPTIONS...]", "Scan issues"
65
+
66
+ long_desc <<-LONGDESC
67
+ scan and print issues in various formats
68
+ LONGDESC
69
+
70
+ method_option :format, :desc => "Set printing format", :enum => %w(debug list number pbl table text)
71
+ method_option :type, :desc => "Set issue type", :enum => %w(pr issue)
72
+ method_option :search, :desc => "Set search query"
73
+ method_option :topology, :desc => "Set information file name for topological sort", :banner => "FILE"
74
+
75
+ def scan(repos)
76
+ if options[:topology] == "-"
77
+ orig_text = $stdin.gets(nil)
78
+ elsif options[:topology]
79
+ orig_text = File.open(options[:topology]).gets(nil)
80
+ end
81
+ Octaccord::Command::Scan.new(client, repos, orig_text, **symbolize_keys(options))
82
+ end
83
+
84
+ ################################################################
85
+ ## Command: subscriptions
86
+ ################################################################
87
+ desc "subscriptions", "List your watching repositories"
88
+
89
+ long_desc <<-LONGDESC
90
+ List your watching repositories
91
+ LONGDESC
92
+
93
+ def subscriptions
94
+ client.subscriptions.each do |repos|
95
+ puts repos.full_name
96
+ end
97
+ end
98
+
99
+ ################################################################
100
+ ## Command: update_issues
101
+ ################################################################
102
+ desc "update_issues REPOSITORY [OPTIONS...] NUM...", "Update issues"
103
+
104
+ long_desc <<-LONGDESC
105
+ update issues in specified repository
106
+ LONGDESC
107
+
108
+ method_option "add-label", :desc => "Add a LABEL to issues", :banner => "LABEL"
109
+ method_option "remove-label", :desc => "Remove a LABEL from issues", :banner => "LABEL"
110
+
111
+ def update_issues(repos, *issues)
112
+ Octaccord::Command::UpdateIssues.new(client, repos, issues, **symbolize_keys(options))
113
+ end
114
+
115
+ ################################################################
116
+ ## Command: add_collaborator
117
+ ################################################################
118
+ desc "add_collaborator REPOSITORY [OPTIONS...]", "Add collaborator to a REPOSITORY"
119
+
120
+ long_desc <<-LONGDESC
121
+ add users or team members to collaborator of repository
122
+ LONGDESC
123
+
124
+ method_option :users, :desc => "Add users to collaborator of repository"
125
+ method_option :teams, :desc => "Add team members to collaborator of repository"
126
+
127
+ def add_collaborator(repos)
128
+ Octaccord::Command::AddCollaborator.new(client, repos, **symbolize_keys(options))
129
+ end
130
+
131
+ ################################################################
132
+ ## Command: comments
133
+ ################################################################
134
+ desc "comments REPOSITORY [OPTIONS...]", "List comments created in a period of time"
135
+
136
+ long_desc <<-LONGDESC
137
+ list comments created in a period of time
138
+ LONGDESC
139
+
140
+ method_option :since, :banner => "ISO8601_DATETIME", :desc => "Only comments updated at or after this time"
141
+ method_option :before, :banner => "ISO8601_DATETIME", :desc => "Only comments updated at or before this time"
142
+ def comments(repos)
143
+ since = Time.iso8601(options[:since])
144
+ before = if options[:before] then Time.iso8601(options[:before]) else Time.now end
145
+ Octaccord::Command::Comments.new(client, repos, since, before)
146
+ end
147
+
148
+ ################################################################
149
+ ## Command: completions
150
+ ################################################################
151
+ desc "completions [COMMAND]", "List available commands or options for COMMAND", :hide => true
152
+
153
+ long_desc <<-LONGDESC
154
+ List available commands or options for COMMAND
155
+ This is supposed to be a zsh compsys helper"
156
+ LONGDESC
157
+
158
+ def completions(*command)
159
+ help = self.class.commands
160
+ global_options = self.class.class_options
161
+ Octaccord::Command::Completions.new(help, global_options, command)
162
+ end
163
+
164
+ ################################################################
165
+ ## Command: create_iteration
166
+ ################################################################
167
+ desc "create_iteration REPOSITORY ITERATION_NAME", "Make new iteration record file"
168
+
169
+ long_desc <<-LONGDESC
170
+ Make a new iteration record file from skeleton
171
+ LONGDESC
172
+
173
+ method_option :start, :desc => "start date-time", :banner => "ISO8601_DATETIME"
174
+ method_option :due, :desc => "due date-time", :banner => "ISO8601_DATETIME"
175
+ method_option :manager, :desc => "set manager name", :banner => "USER"
176
+ method_option :team, :desc => "set github organization/team style team name"
177
+ method_option :template, :desc => "set ERB template", :banner => "FILE"
178
+ def create_iteration(repos, iteration_name)
179
+ Octaccord::Command::CreateIteration.new(client, repos, iteration_name, **symbolize_keys(options))
180
+ end
181
+
182
+ ################################################################
183
+ ## Command: filter
184
+ ################################################################
185
+ desc "filter", "Decorate markdown as filter"
186
+
187
+ def filter
188
+ block_finalize = false
189
+ block_inside = false
190
+ block_content = ""
191
+ block_argv = []
192
+
193
+ while line = STDIN.gets # STDIN.noecho(&:gets)
194
+ if /begin:octaccord (.*)-->/ =~ line
195
+ block_inside = true
196
+ block_argv = $1.chomp.shellsplit
197
+ print line
198
+ next
199
+ end
200
+
201
+ if /end:octaccord/ =~ line
202
+ orig_stdout = $stdout
203
+ orig_stdin = $stdin
204
+ $stdout = StringIO.new
205
+ $stdin = StringIO.new(block_content)
206
+ self.class.start(block_argv)
207
+ result = $stdout.string
208
+ $stdout = orig_stdout
209
+ $stdin = orig_stdin
210
+
211
+ print result
212
+ print line
213
+ block_inside = false
214
+ next
215
+ end
216
+
217
+ if block_inside
218
+ block_content << line
219
+ else
220
+ print line.gsub(/(^|[^\[])\#(\d+)/, '\1[#\2](../issues/\2)')
221
+ end
222
+ end
223
+ end
224
+
225
+ ################################################################
226
+ ## Command: get_team_members
227
+ ################################################################
228
+ desc "get_team_members ORGANIZATION/TEAM", "Get team members"
229
+
230
+ long_desc <<-LONGDESC
231
+ Get team members
232
+ LONGDESC
233
+
234
+ def get_team_members(teams)
235
+ Octaccord::Command::GetTeamMembers.new(client, teams, **symbolize_keys(options))
236
+ end
237
+
238
+ ################################################################
239
+ ## Command: info
240
+ ################################################################
241
+ desc "info", "Show github remote info"
242
+
243
+ def info
244
+ Octaccord::Command::Info.new(client, **symbolize_keys(options))
245
+ end
246
+
247
+ ################################################################
248
+ ## Command: show
249
+ ################################################################
250
+ desc "show REPOSITORY NUM", "Show details of issue #NUM"
251
+
252
+ def show(repos, issue)
253
+ Octaccord::Command::Show.new(client, repos, issue, **symbolize_keys(options))
254
+ end
255
+
256
+ ################################################################
257
+ ## patch to insert setup_global_options
258
+ ################################################################
259
+ no_commands do
260
+ def invoke_command(command, *args)
261
+ setup_global_options
262
+ super
263
+ end
264
+ end
265
+
266
+ ################################################################
267
+ ## private
268
+ ################################################################
269
+ private
270
+
271
+ def exit_on_error(&block)
272
+ begin
273
+ yield if block_given?
274
+ rescue Octaccord::ConfigurationError => e
275
+ STDERR.print "ERROR: #{e.message}.\n"
276
+ exit 1
277
+ end
278
+ end
279
+
280
+ attr_reader :client, :config
281
+
282
+ def setup_global_options
283
+ exit_on_error do
284
+ @config ||= Pit.get("github.com", :require => {
285
+ "login" => "Your login name here",
286
+ "password" => "Your password here"
287
+ })
288
+
289
+ $OCTACCORD_DEBUG = true if options[:debug]
290
+ @store ||= FileStore.new
291
+ @stack ||= Faraday::RackBuilder.new do |builder|
292
+ builder.response :logger if options[:debug]
293
+ builder.use Faraday::HttpCache, shared_cache: false, store: @store, serializer: YAML
294
+ builder.use Octokit::Response::RaiseError
295
+ builder.adapter Faraday.default_adapter
296
+ end
297
+
298
+ Octokit.middleware = @stack
299
+ Octokit.auto_paginate = true
300
+ @client ||= Octokit::Client.new(:login => @config["login"],
301
+ :password => @config["password"])
302
+ end
303
+ end
304
+
305
+ def symbolize_keys(hash)
306
+ Hash[hash.map {|k,v| [k.to_s.gsub('-', '_').to_sym, v]}]
307
+ end
308
+
309
+ end # class OctaccordCLI
310
+
311
+ command = OctaccordCLI.start(ARGV)