From 52afe426c22dfe6a4dcc9cdd15aff793e5e9149b Mon Sep 17 00:00:00 2001 From: "Glenn Y. Rolland" Date: Wed, 29 Jun 2016 10:36:20 +0200 Subject: [PATCH] Add support for project name. Better rendering style. --- .gitignore | 2 + Gemfile | 1 + bin/aoidos | 132 ++++++++++++++++++++++++++++++++--------------------- report.ods | Bin 4320 -> 0 bytes 4 files changed, 84 insertions(+), 51 deletions(-) delete mode 100644 report.ods diff --git a/.gitignore b/.gitignore index b844b14..762d557 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ Gemfile.lock +*.ods +*.ods# diff --git a/Gemfile b/Gemfile index bbbfd0d..2ed7b52 100644 --- a/Gemfile +++ b/Gemfile @@ -5,3 +5,4 @@ gem 'thor' gem 'minedig', git: "https://github.com/siman-man/minedig" gem 'rspreadsheet' gem 'pry' +gem 'semantic' diff --git a/bin/aoidos b/bin/aoidos index 5af3aa1..098c85b 100755 --- a/bin/aoidos +++ b/bin/aoidos @@ -5,64 +5,94 @@ require 'minedig' require 'yaml' require 'rspreadsheet' require 'pry' +require 'thor' +require 'semantic' -credential_file = ENV['HOME'] + '/.aoidos/redmine.yml' - -unless File.exist? credential_file - sample_content = "home: 'http://redmine.example.com'\nkey: REDMINE_API_KEY" - raise Errno::ENOENT, "Please create %s file with:\n%s" % [ - credential_file, sample_content - ] -end - -credential = YAML.load_file(credential_file) -redmine = Minedig::Redmine.new do |config| - config.home = credential['home'] # ex: 'http://project.gnuside.com' - config.api_key = credential['key'] # ex: ... -end - -book = Rspreadsheet::Workbook.new -tickets = redmine.project('catone-smb-device').tickets(count: :all) -tickets.each do |ticket| - type = case ticket.tracker_id - when 2 then :feature # feature - when 4 then :user_story # user story - else :bug - end - - next if type != :user_story +class Aoidos < Thor - prefix = nil - title = nil - sheet = nil - if ticket.subject.strip =~ /^(\s*As\s+.*?)\s*,\s+i\s+want\s+to\s+(.*)$/i then - prefix = $1.strip - title = $2.strip - else - raise "Invalid ticket #{ticket.id} - #{ticket.subject}" - end - sheet = book.sheet(prefix) || book.create_worksheet(prefix) + desc "export PROJECT", "Export project user stories" + def export(project) + target_version = make_version '2.0.0' + credential_file = ENV['HOME'] + '/.aoidos/redmine.yml' - if sheet.rows.size == 0 then - [prefix, 'Description', 'Version', 'ID'].each_with_index do |txt,idx| - cell = sheet.cell(1,idx+1) - cell.value = txt - cell.format.bold = true - cell.format.color = '#FFFFFF' - cell.format.background_color = '#662D91' + unless File.exist? credential_file + sample_content = "home: 'http://redmine.example.com'\nkey: REDMINE_API_KEY" + raise Errno::ENOENT, "Please create %s file with:\n%s" % [ + credential_file, sample_content + ] end + + credential = YAML.load_file(credential_file) + redmine = Minedig::Redmine.new do |config| + config.home = credential['home'] # ex: 'http://project.gnuside.com' + config.api_key = credential['key'] # ex: ... + end + + book = Rspreadsheet::Workbook.new + tickets = redmine.project(project).tickets(count: :all) + tickets.each do |ticket| + type = case ticket.tracker_id + when 2 then :feature # feature + when 4 then :user_story # user story + else :bug + end + + next if type != :user_story + + + prefix = nil + title = nil + sheet = nil + if ticket.subject.strip =~ /^(\s*As\s+.*?)\s*,\s+i\s+want\s+to\s+(.*)$/i then + prefix = $1.strip + title = $2.strip + else + raise "Invalid ticket #{ticket.id} - #{ticket.subject}" + end + sheet = book.sheet(prefix) || book.create_worksheet(prefix) + + if sheet.rows.size == 0 then + [prefix, 'Description', 'Version', 'ID'].each_with_index do |txt,idx| + cell = sheet.cell(1,idx+1) + cell.value = txt + cell.format.bold = true + cell.format.color = '#FFFFFF' + cell.format.background_color = '#662D91' + end + end + + nextline = sheet.rows.size + 1 + ticket_title = "%s%s" % [title[0].upcase, title[1..-1]] + ticket_version = + (ticket.ticket['fixed_version'] || {'name' => ''})['name'] + .split(/\s+-\s+/)[0] + + ticket_version_obj = make_version ticket_version.gsub(/^v/,'') + puts "[ %- 8d | %- 30.30s | %- 50.50s ]" % [ticket.id, prefix, ticket_title] + + [ticket_title, '', ticket_version, ticket.id].each_with_index do |txt,idx| + cell = sheet.cell(nextline,idx+1) + cell.value = txt + if ticket_version_obj <= target_version then + cell.format.bold = true + cell.format.color = '#000000' + else + cell.format.color = '#888888' + end + end + + end + book.save(project + '.ods') end - nextline = sheet.rows.size + 1 - ticket_title = "%s%s" % [title[0].upcase, title[1..-1]] - ticket_version = (ticket.ticket['fixed_version'] || {'name' => ''})['name'] - puts "[ %- 8d | %- 30.30s | %- 50.50s ]" % [ticket.id, prefix, ticket_title] + private - [title, '', ticket_version, ticket.id].each_with_index do |txt,idx| - cell = sheet.cell(nextline,idx+1) - cell.value = txt + def make_version str + return Semantic::Version.new str + rescue ArgumentError + make_version str + '.0' end - end -book.save('report.ods') + +Aoidos.start(ARGV) diff --git a/report.ods b/report.ods deleted file mode 100644 index a91fbb28320aa6fdd4a30a44002a52650a2183d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4320 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 U2#NmGC%B$BuhpBbZv+7T2l+gZ!2kdN