Class: Trello::Main

Inherits:
Object
  • Object
show all
Includes:
Commander::Methods, Helpers, TrelloConfig
Defined in:
lib/trello.rb

Instance Method Summary collapse

Methods included from TrelloConfig

#__config_dir__, #config, #param_check, #save_config

Methods included from Helpers

#board_check, #format_api_url, #prompt_for_list_from_options, #prompt_from_options, #root, #user_check, #write_json_to_file

Instance Method Details

#runObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/trello.rb', line 18

def run
  program :name, "Trello"
  program :description, 'Trello interface'
  program :version, '1.0.0'

  command :init do |c|
    c.syntax = 'trello init'
    c.description = 'Generates a default config file for the Trello CLI so it can be used in this directory.'
    c.option '--force', 'Overwrites an existing config file.'
    c.action do |args, options|
      if File.exist?(CONFIG_FILE_NAME) && !options.force
        abort "Config file already exists. Run 'trello init -f' to overwrite it."
      end

      FileUtils.cp(File.join(root, '.trelloconfig.default'), "./#{CONFIG_FILE_NAME}")
      say "Created .trelloconfig in this directory."
    end
  end

  command 'server-config' do |c|
    c.syntax = 'trello server-config'
    c.description = 'Builds a config file for your API backend.'
    c.action do |args, options|
      trello_config = {base_url: "https://api.trello.com/1/"}
      trello_config[:api_key] = ask("API key?")

      puts "Requesting access to this application..."
      sleep(0.5)
      Launchy.open("https://trello.com/1/authorize?key=#{trello_config[:api_key]}&name=Your+Application&expiration=never&response_type=token&scope=read,write")
      sleep(0.5)
      trello_config[:token] = ask("What was the token?")

      trello_config[:board_id] = prompt_from_options("Which board should the API reference? (ID)") do
        result = Api::Trello.make_call(:get, "members/me", key: trello_config[:api_key], token: trello_config[:token], boards: 'open')['boards']

        result.map do |board|
          {id: board['id'], name: board['name']}
        end
      end

      lists_resp = Api::Trello.make_call(:get, "boards/#{trello_config[:board_id]}", {key: trello_config[:api_key], token: trello_config[:token], lists: 'open'})
      lists = lists_resp['lists'].map do |list|
        {id: list['id'], name: list['name']}
      end

      trello_config[:pending_columns] = prompt_for_list_from_options("Which lists hold pending tasks? (ID,ID)") { lists }

      {
        in_development_column: "Which column represents tasks in development? (ID)",
        in_review_column: "Which column represents tasks in review? (ID)",
        approved_merged_column: "Which column represents tasks approved/merged to staging? (ID)",
        deployed_column: "Which column represents tasks deployed to production? (ID)"
      }.each do |field, message|
        trello_config[field] = prompt_from_options(message) { lists }
      end

      config_file = {
        trello: trello_config
      }

      puts "Saving to config.json..."

      write_json_to_file(config_file, './config.json')
    end
  end

  command :config do |c|
    c.syntax = 'trello config --<field> value'
    c.description = 'Configure options for the integration'
    c.option '--user USERNAME', 'Configures the user\'s Trello username (required)'
    c.option '--board BOARD', 'Configures which Trello board to automate. This is the board\'s alphanumeric ID (e.g. sqT6xkP7), NOT its name. (required)'
    c.option '--key APIKEY', 'Configures the user\'s API key for access to the API backend'
    c.option '--url PATH', 'Configures the path to this trello CL\'s API backend'
    c.option '--repo REPO', 'Configures the Github repo with which your branches are associated. This should include the organization, e.g. Organization/cool-repo'
    c.action do |args, options|
      unless [options.user, options.board, options.url, options.key, options.repo].all?(&:nil?)
        if options.user
          response = Api::Trello.make_call(:get, "members/#{options.user}", {fields: :none})
          config.user = response['id']
        end

        if options.board
          config.board = options.board
        end

        if options.url
          config.url = format_api_url(options.url)
        end

        # handle unformatted keys
        {
          options.key => 'api_key',
          options.repo => 'repo'
        }.each do |option, config_key|
          if option
            config[config_key] = option
          end
        end

        if config.repo && !config.repo.include?('/')
          puts "Your repo #{config.repo} doesn't appear to include the organization. That's going to break links on Trello. Make sure to fix that before starting cards."
        end

        puts "Config updated."
        save_config
      else
        puts config.to_hash.to_yaml
      end
    end
  end

  command :tasks do |c|
    c.syntax = 'trello tasks'
    c.description = 'Shows tasks assigned to the configured user.'
    c.option '--all', 'Shows all tasks, regardless of assignee'
    c.action do |args, options|
      board_check

      unless options.all
        user_check
      end

      user = options.all ? nil : config['user']

      response = Api::Integration.make_call(:get, "cards", {board: config['board'], user: user})

      all_cards = response.map{|list| list['cards']}.flatten

      if (all_cards.length == 0) || (user && all_cards.select{|card| card['idMembers'].include?(user)}.length == 0)
        abort "Found no cards."
      end

      enable_paging
      response.each do |list|
        if user && list['cards'].none? {|card| card['idMembers'].include? user}
          next
        end

        list_name = list['name']
        say list_name
        say ('-' * list_name.length)
        list['cards'].each do |task|
          if options.all || (user && task['idMembers'].include?(user))
            say "  ##{task['idShort']}: #{task['name']}"
          end
        end
      end
    end
  end
  alias_command :ls, :tasks
  alias_command :list, :tasks

  command :start do |c|
    c.syntax = 'trello start 123 <branch>'
    c.description = "Marks the specified card as 'in development' on Trello and associates the specified branch with the card."
    c.option '--branch', 'Checks out the branch specified in the arguments.'
    c.option '--no-branch', 'Starts the card without creating a new branch.'
    c.action do |args, options|
      card_number, branch = args
      require_branch = options.no_branch.nil?

      user_check
      param_check 'repo', "You need to specify what repository you're working in with 'trello config --repo <name>'."

      user = config['user']

      if require_branch
        unless branch
          abort 'You need a branch name. To start this card without a branch, set the --no-branch flag (-n).'
        end

        if options.branch
          unless system "git checkout -b #{branch}"
            abort "Failed to create branch locally - exiting."
          end
        end
      end

      response = Api::Integration.make_call(:post, "cards/#{card_number}/start", {user: user, branch: (require_branch ? branch : '<no branch>'), repo: config['repo'], board: config['board']})
      if response.success?
        say "Started card #{card_number} with branch #{branch}."
      end
    end
  end

  run!
end