trello_tool 0.2.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4cfb13afc59a0bbc26ff8d073ec8205a8be3186078586626f2b1d1a6678534b
4
- data.tar.gz: 24100d779e70261e15fd631cf8cc8c6e15bbfe52b4c14e020759244c10ac91f2
3
+ metadata.gz: 6ed0b9ce508c845c11e20e9832e4b0bdce3540b50eb726eb39f2e2b0a92dd1da
4
+ data.tar.gz: 72155610d0070653878eb3f705ece349d23358e97b105fb5d2bf75d5090b5d58
5
5
  SHA512:
6
- metadata.gz: 0645b48ad54aea192469652a91a4d809c502cd32a97a440dbde72a40992ad365ba948c465d8c8e8705b424367f80783111cd36bf13530ad289f8515611a9d34e
7
- data.tar.gz: a1a50a0449d75ddd376931d32caf80f057ca973d5825a003d4bee9b5ded2d89aea22501ae235cedebc78e40d89314b972773e701ffb330261aae5dbc314d633b
6
+ metadata.gz: 6811ec433a67808fb9b7d457127a59ac39c9e6e2e96717b51df6ef7f6f4669760f19e82c50b57928f3e41a8ee0e6261734765ebfe40ca65d2747df1332ae8942
7
+ data.tar.gz: 8345785d3149a3322c1850cd1ea89d48a2cf38eaf4249714835c047271c4ccd799b16e601a24ac2231e84a01626740ac0ab37ac30629e2185ea1d7e0b70327b7
data/CHANGELOG.md CHANGED
@@ -1,4 +1,13 @@
1
- ## [Unreleased]
1
+ ## [0.4.0] - 2026-10-02
2
+
3
+ * added `search` and `cards` (find cards in a board; markdown or `--json`)
4
+ * added `comment`, `create`, `checklist`, `check` and `move` (change cards), and the
5
+ `default_list_name_for_new_cards` configuration key for `create`
6
+ * commands that fail now exit non-zero
7
+
8
+ ## [0.3.0] - 2026-09-04
9
+
10
+ * added `summarize_as_md_long`
2
11
 
3
12
  ## [0.2.0] - 2022-05-21
4
13
 
data/README.md CHANGED
@@ -56,6 +56,7 @@ You can also configure some defaults
56
56
  * `divider_template` = "[%s]"
57
57
  * `too_many_doing` = 2
58
58
  * `too_many_todo` = 10
59
+ * `default_list_name_for_new_cards` = (none) -- the list `create` puts a card in when no list is named, e.g. "Triage"
59
60
 
60
61
 
61
62
  ### Trello Authorisation
@@ -69,8 +70,42 @@ You can also read more at https://github.com/jeremytregunna/ruby-trello
69
70
 
70
71
  ## Usage
71
72
 
72
- * bin/trello/health
73
- trello/health
73
+ `bin/trello_tool help` lists every command and `bin/trello_tool help COMMAND` its options. Boards default to
74
+ `main_board_url`; cards are given by id or url; lists, labels and checklists by name.
75
+
76
+ The board:
77
+
78
+ * `bin/trello_tool health` -- checks whether the main board is "healthy"
79
+ * `bin/trello_tool lists (BOARD_URL)` -- the lists of a board
80
+ * `bin/trello_tool release (VERSION)`, `archive`, `archive_last (N)` -- rename "next version" on release, and
81
+ move old version lists to the archive board
82
+
83
+ Reading cards:
84
+
85
+ * `bin/trello_tool card CARD` -- one card as json (title, description, url, checklists, attachment urls)
86
+ * `bin/trello_tool search QUERY (BOARD_URL) (--json)` -- the unarchived cards matching a trello search, grouped by
87
+ list. The query is trello's own, so `label:bug`, `list:"TO DO"` and the like work, and the last word matches as
88
+ a prefix
89
+ * `bin/trello_tool cards (BOARD_URL) (--json)` -- every unarchived card in the board, grouped by list
90
+ * `bin/trello_tool summarize_as_md`, `summarize_as_md_long`, `summarize_as_urls (LIST_NAME (BOARD_URL))` -- the
91
+ cards of one list
92
+
93
+ Changing cards:
94
+
95
+ * `bin/trello_tool comment CARD "text"` or `--file notes.md` -- adds a comment
96
+ * `bin/trello_tool create (LIST_NAME (BOARD_URL)) --title "…" (--desc "…" | --desc-file card.md) (--label bug …)
97
+ (--top) (--force)` -- creates a card and prints it as json. Without LIST_NAME it goes in
98
+ `default_list_name_for_new_cards`. It first searches for an unarchived card with the same title and stops with
99
+ that card's url if there is one (`--force` creates another; trello's search can lag a few seconds behind a card
100
+ that was only just created)
101
+ * `bin/trello_tool checklist CARD NAME --items "first" "second" (--checked)` -- adds the items to the card's
102
+ checklist of that name, creating the checklist if need be and skipping items already there
103
+ * `bin/trello_tool check CARD "item text" (--checklist NAME) (--uncheck)` -- ticks (or unticks) the item with that
104
+ text, or the only item containing it
105
+ * `bin/trello_tool move CARD (LIST_NAME (BOARD_URL)) (--top | --bottom)` -- to the bottom (or top) of a list; without
106
+ LIST_NAME, to the top or bottom of the list the card is in
107
+
108
+ A command that can't do what it was asked says why and exits non-zero.
74
109
 
75
110
  ## Development
76
111
 
@@ -18,7 +18,8 @@ module TrelloTool
18
18
  version_template: "v%s",
19
19
  divider_template: "[%s]",
20
20
  too_many_doing: 2,
21
- too_many_todo: 10
21
+ too_many_todo: 10,
22
+ default_list_name_for_new_cards: nil
22
23
  }.freeze
23
24
  end
24
25
  Configuration = Struct.new(*DefaultConfiguration::DEFAULTS.keys, keyword_init: true) do
@@ -33,7 +34,7 @@ module TrelloTool
33
34
  # generates a file based on current settings
34
35
  def generate
35
36
  File.open(config_file, "w") do |f|
36
- Psych.dump(to_h { |k, v| [k.to_s, v] }, f) # rubocop:disable Style/HashTransformKeys doesn't work
37
+ Psych.dump(to_h { |k, v| [k.to_s, v] }, f)
37
38
  end
38
39
  end
39
40
 
@@ -3,7 +3,11 @@
3
3
  module TrelloTool
4
4
  # Health analysis of a board
5
5
  class Health
6
- attr_reader :board, :configuration, :symbols_and_colours, :unexpected, :expected_lists
6
+ # @return [Trello::Board]
7
+ attr_reader :board
8
+ # @return [TrelloTool::Configuration]
9
+ attr_reader :configuration
10
+ attr_reader :symbols_and_colours, :unexpected, :expected_lists
7
11
 
8
12
  def initialize(board, configuration)
9
13
  @board = board
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
3
4
  require "trello"
4
5
  require "trello_tool/util"
5
6
 
@@ -7,6 +8,7 @@ module TrelloTool
7
8
  # Wrapped client for trello adapting it to things we need it to do
8
9
  class TrelloClient < SimpleDelegator
9
10
  include TrelloTool::Util
11
+
10
12
  attr_reader :client, :configuration
11
13
 
12
14
  # @param configuration[TrelloTool::Configuration]
@@ -54,6 +56,56 @@ module TrelloTool
54
56
  end
55
57
  end
56
58
 
59
+ # @param card_id [String]
60
+ # @return [Trello::Card]
61
+ def find_card(card_id)
62
+ client.find(:cards, card_id)
63
+ end
64
+
65
+ # @return [Trello::Board]
66
+ def find_board(board_url)
67
+ client.find(:boards, extract_id_from_url(board_url))
68
+ end
69
+
70
+ # the card fields the listing commands need, as trello names them
71
+ CARD_FIELDS = "name,url,idList,labels,closed"
72
+
73
+ # Unarchived cards of a board matching a trello search (operators such as label: and list: work, and the
74
+ # last word matches as a prefix)
75
+ # @return [Array<Hash>] cards as trello returns them: "name", "url", "idList", "labels"
76
+ def search_cards(board, query, limit: 50)
77
+ response = client.get("/search", "query" => query, "idBoards" => board.id, "modelTypes" => "cards",
78
+ "cards_limit" => limit.to_s, "card_fields" => CARD_FIELDS, "partial" => "true")
79
+ JSON.parse(response.body).fetch("cards", []).reject { |card| card["closed"] }
80
+ end
81
+
82
+ # Every unarchived card in an unarchived list of a board, in one request
83
+ # @return [Array<Hash>] as #search_cards
84
+ def open_cards(board)
85
+ JSON.parse(client.get("/boards/#{board.id}/cards/visible", "fields" => CARD_FIELDS).body)
86
+ end
87
+
88
+ # @param list [Trello::List]
89
+ # @return [Hash] the new card as trello returns it ("id", "url"...)
90
+ def create_card(list, title:, description: "", top: false, label_ids: [])
91
+ body = { name: title, desc: description, idList: list.id, pos: top ? "top" : "bottom" }
92
+ body[:idLabels] = label_ids.join(",") if label_ids.any?
93
+ JSON.parse(client.post("/cards", body).body)
94
+ end
95
+
96
+ # @param item [Hash] a checklist's check item ("id", "name", "state")
97
+ def set_check_item_state(card, item, complete:)
98
+ client.put("/cards/#{card.id}/checkItem/#{item['id']}", state: complete ? "complete" : "incomplete")
99
+ end
100
+
101
+ # @param position [String] "top" or "bottom"
102
+ # @param list [Trello::List, nil] nil to reposition the card within its list
103
+ def move_card(card, position:, list: nil)
104
+ body = { pos: position }
105
+ body[:idList] = list.id if list
106
+ client.put("/cards/#{card.id}", body)
107
+ end
108
+
57
109
  def next_version_list
58
110
  @next_version_list ||= find_list_by_list_name(main_board, configuration.next_version_list_name)
59
111
  end
@@ -14,6 +14,13 @@ module TrelloTool
14
14
  match_data[1]
15
15
  end
16
16
 
17
+ # @param card_id_or_url [String] a card id or a https://trello.com/c/ID/description url
18
+ # @return [String] the card id
19
+ def extract_card_id(card_id_or_url)
20
+ match_data = %r{\Ahttps://trello.com/c/([a-zA-Z0-9]+)/?.*}.match(card_id_or_url)
21
+ match_data ? match_data[1] : card_id_or_url
22
+ end
23
+
17
24
  # @param board [Trello::Board]
18
25
  # @param list_name [String]
19
26
  # @return [Trello::List]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TrelloTool
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
3
4
  require "thor"
4
5
  require "trello_tool/configuration"
5
6
  require "trello_tool/health"
@@ -7,7 +8,7 @@ require "trello_tool/trello_client"
7
8
  require "trello_tool/util"
8
9
 
9
10
  # The thor class
10
- # rubocop:disable Metrics/ClassLength
11
+ # rubocop:disable-next Metrics/ClassLength
11
12
  class TrelloToolThor < Thor
12
13
  include TrelloTool::Util
13
14
 
@@ -15,6 +16,11 @@ class TrelloToolThor < Thor
15
16
  @configuration ||= TrelloTool::Configuration.new
16
17
  end
17
18
 
19
+ # a command that can't do what it was asked (raises Thor::Error) exits non-zero
20
+ def self.exit_on_failure?
21
+ true
22
+ end
23
+
18
24
  no_commands do
19
25
  delegate :configuration, to: :class
20
26
  end
@@ -89,6 +95,14 @@ class TrelloToolThor < Thor
89
95
  end
90
96
  end
91
97
 
98
+ desc "card CARD_ID_OR_URL",
99
+ "prints out a card as json (title, description, url, checklists, attachment urls)"
100
+
101
+ def card(card_id_or_url)
102
+ card = client.find_card(extract_card_id(card_id_or_url))
103
+ say JSON.pretty_generate(card_as_hash(card))
104
+ end
105
+
92
106
  desc "release (VERSION)",
93
107
  "rename next_version to VERSION and create next_version. If VERSION isn't specified use whatever is in ./.RELEASE_NEW_VERSION"
94
108
 
@@ -162,10 +176,236 @@ class TrelloToolThor < Thor
162
176
  say "\n"
163
177
  end
164
178
 
179
+ desc "search QUERY (BOARD_URL)",
180
+ "prints the unarchived cards matching a trello search, grouped by list " \
181
+ "(operators like label: and list: work) -- markdown, or --json"
182
+ method_option :json, type: :boolean, default: false, desc: "print json instead of markdown"
183
+
184
+ def search(query, url = configuration.main_board_url)
185
+ board = client.find_board(url)
186
+ print_cards(board, client.search_cards(board, query))
187
+ end
188
+
189
+ desc "cards (BOARD_URL)", "prints every unarchived card in a board, grouped by list -- markdown, or --json"
190
+ method_option :json, type: :boolean, default: false, desc: "print json instead of markdown"
191
+
192
+ def cards(url = configuration.main_board_url)
193
+ board = client.find_board(url)
194
+ print_cards(board, client.open_cards(board))
195
+ end
196
+
197
+ desc "comment CARD_ID_OR_URL (TEXT)", "adds a comment to a card (the text inline, or from --file)"
198
+ method_option :file, type: :string, desc: "read the comment from this file"
199
+
200
+ def comment(card_id_or_url, text = nil)
201
+ raise Thor::Error, "give the comment either inline or with --file, not both" if text && options[:file]
202
+
203
+ text = File.read(options[:file]) if options[:file]
204
+ raise Thor::Error, "the comment is empty" if text.to_s.strip.empty?
205
+
206
+ card = client.find_card(extract_card_id(card_id_or_url))
207
+ card.add_comment(text)
208
+ say "commented on #{card.url}"
209
+ end
210
+
211
+ desc "create (LIST_NAME (BOARD_URL)) --title TITLE (--desc TEXT | --desc-file PATH) (--label NAME ...) (--top) (--force)",
212
+ "creates a card at the bottom (or --top) of LIST_NAME (default: default_list_name_for_new_cards) and " \
213
+ "prints it as json; stops if an unarchived card already has that title, unless --force"
214
+ method_option :title, type: :string, required: true
215
+ method_option :desc, type: :string, desc: "the description"
216
+ method_option :desc_file, type: :string, desc: "read the description (markdown) from this file"
217
+ method_option :label, type: :array, default: [], desc: "names of labels of the board"
218
+ method_option :top, type: :boolean, default: false, desc: "at the top of the list rather than the bottom"
219
+ method_option :force, type: :boolean, default: false, desc: "create even if a card with this title exists"
220
+
221
+ def create(list_name = configuration.default_list_name_for_new_cards, url = configuration.main_board_url)
222
+ title = title_option!
223
+ description = description_option!
224
+ no_list = "give a LIST_NAME, or set default_list_name_for_new_cards in #{configuration.config_file}"
225
+ raise Thor::Error, no_list unless list_name
226
+
227
+ board = client.find_board(url)
228
+ list = find_list!(board, list_name)
229
+ label_ids = label_ids!(board, Array(options[:label]))
230
+ refuse_duplicate!(board, title) unless options[:force]
231
+ created = client.create_card(list, title: title, description: description, top: options[:top] ? true : false,
232
+ label_ids: label_ids)
233
+ say "created #{created['url']} in #{list.name.inspect}"
234
+ card(created["id"])
235
+ end
236
+
237
+ desc "checklist CARD_ID_OR_URL NAME --items ITEM ...",
238
+ "adds items to the card's checklist of that name (creating it if need be), skipping items already there; " \
239
+ "prints the checklist as json"
240
+ method_option :items, type: :array, default: [], desc: "the items to add"
241
+ method_option :checked, type: :boolean, default: false, desc: "add the items already ticked"
242
+
243
+ def checklist(card_id_or_url, name)
244
+ card_id = extract_card_id(card_id_or_url)
245
+ list = find_checklist(card_id, name) || create_checklist(card_id, name)
246
+ existing = list.check_items.map { |item| item["name"] }
247
+ (Array(options[:items]).uniq - existing).each { |item| list.add_item(item, options[:checked] ? true : false, "bottom") }
248
+ say JSON.pretty_generate(checklist_as_hash(find_checklist(card_id, name)))
249
+ end
250
+
251
+ desc "check CARD_ID_OR_URL ITEM_TEXT (--checklist NAME) (--uncheck)",
252
+ "ticks (or with --uncheck unticks) the checklist item with that text (the whole text, or a part only it has)"
253
+ method_option :checklist, type: :string, desc: "only look in the checklist of this name"
254
+ method_option :uncheck, type: :boolean, default: false, desc: "untick instead"
255
+
256
+ def check(card_id_or_url, item_text)
257
+ card = client.find_card(extract_card_id(card_id_or_url))
258
+ item = find_check_item!(card, item_text)
259
+ client.set_check_item_state(card, item, complete: !options[:uncheck])
260
+ say "#{options[:uncheck] ? 'unticked' : 'ticked'} #{item['name'].inspect} on #{card.url}"
261
+ end
262
+
263
+ desc "move CARD_ID_OR_URL (LIST_NAME (BOARD_URL)) (--top | --bottom)",
264
+ "moves a card to the bottom (or --top) of a list; without LIST_NAME, to the top or bottom of the list it is in"
265
+ method_option :top, type: :boolean, default: false
266
+ method_option :bottom, type: :boolean, default: false
267
+
268
+ def move(card_id_or_url, list_name = nil, url = configuration.main_board_url)
269
+ position = position_option!(list_name)
270
+ card = client.find_card(extract_card_id(card_id_or_url))
271
+ list = find_list!(client.find_board(url), list_name) if list_name
272
+ client.move_card(card, position: position, list: list)
273
+ say "moved #{card.url} to the #{position} of #{list ? list.name.inspect : 'its list'}"
274
+ end
275
+
165
276
  private
166
277
 
167
278
  def client
168
279
  TrelloTool::TrelloClient.new(configuration)
169
280
  end
281
+
282
+ # @param cards [Array<Hash>] as trello returns them ("name", "url", "idList", "labels"); cards whose list is
283
+ # archived (not among the board's lists) are left out
284
+ def print_cards(board, cards)
285
+ # in the board's list order
286
+ rows = board.lists.flat_map { |list| cards.filter_map { |found| card_row(found, [list]) } }
287
+ return say(JSON.pretty_generate(rows)) if options[:json]
288
+ return say("no cards found") if rows.empty?
289
+
290
+ print_cards_as_markdown(rows)
291
+ end
292
+
293
+ def print_cards_as_markdown(rows)
294
+ rows.group_by { |row| row[:list] }.each do |list_name, in_list|
295
+ say "\n# #{list_name} (#{in_list.length} cards)\n\n"
296
+ in_list.each { |row| say "* [#{row[:title]}](#{row[:url]})#{row[:labels].map { |label| " [#{label}]" }.join}" }
297
+ end
298
+ say "\n"
299
+ end
300
+
301
+ def title_option!
302
+ title = options[:title].to_s.strip
303
+ raise Thor::Error, "--title is empty" if title.empty?
304
+
305
+ title
306
+ end
307
+
308
+ def description_option!
309
+ both = "give the description either with --desc or with --desc-file, not both"
310
+ raise Thor::Error, both if options[:desc] && options[:desc_file]
311
+
312
+ options[:desc_file] ? File.read(options[:desc_file]) : options[:desc].to_s
313
+ end
314
+
315
+ # @return [String] "top" or "bottom" (the default when the card is going to another list)
316
+ def position_option!(list_name)
317
+ raise Thor::Error, "--top or --bottom, not both" if options[:top] && options[:bottom]
318
+ raise Thor::Error, "give a LIST_NAME, --top or --bottom" unless list_name || options[:top] || options[:bottom]
319
+
320
+ options[:top] ? "top" : "bottom"
321
+ end
322
+
323
+ # @return [Hash, nil] nil when the card's list isn't one of lists
324
+ def card_row(found, lists)
325
+ list = lists.detect { |candidate| candidate.id == found["idList"] }
326
+ return nil unless list
327
+
328
+ { title: found["name"], url: found["url"], list: list.name,
329
+ labels: (found["labels"] || []).map { |label| label["name"].to_s }.reject(&:empty?) }
330
+ end
331
+
332
+ # the list of that name (exactly, or failing that the only one that differs just by case)
333
+ def find_list!(board, list_name)
334
+ lists = board.lists
335
+ list = lists.detect { |candidate| candidate.name == list_name }
336
+ list ||= lists.select { |candidate| candidate.name.casecmp?(list_name) }.then { |found| found.first if found.size == 1 }
337
+ list || raise(Thor::Error, "no list called #{list_name.inspect} in #{board.name}. Lists: #{lists.map(&:name).join(', ')}")
338
+ end
339
+
340
+ def label_ids!(board, names)
341
+ return [] if names.empty?
342
+
343
+ labels = board.labels
344
+ names.map do |name|
345
+ label = labels.detect { |candidate| candidate.name.to_s.casecmp?(name) }
346
+ label&.id || raise(Thor::Error, "no label called #{name.inspect} in #{board.name}. " \
347
+ "Labels: #{labels.map { |candidate| candidate.name.to_s }.reject(&:empty?).join(', ')}")
348
+ end
349
+ end
350
+
351
+ def refuse_duplicate!(board, title)
352
+ duplicate = client.search_cards(board, %("#{title.delete('"')}")).detect { |found| found["name"].to_s.strip.casecmp?(title) }
353
+ return unless duplicate
354
+
355
+ raise Thor::Error, "a card called #{title.inspect} already exists: #{duplicate['url']} (--force to create another)"
356
+ end
357
+
358
+ # always from a fresh read of the card, so it sees a checklist or item that was just added
359
+ def find_checklist(card_id, name)
360
+ client.find_card(card_id).checklists.detect { |candidate| candidate.name == name }
361
+ end
362
+
363
+ def create_checklist(card_id, name)
364
+ client.find_card(card_id).create_new_checklist(name)
365
+ find_checklist(card_id, name) || raise(Thor::Error, "couldn't create the checklist #{name.inspect}")
366
+ end
367
+
368
+ # @return [Hash] the one check item whose name is item_text, or failing that the one containing it
369
+ def find_check_item!(card, item_text)
370
+ items = check_items!(card)
371
+ matches = items.select { |item| item["name"].casecmp?(item_text) }
372
+ matches = items.select { |item| item["name"].downcase.include?(item_text.downcase) } if matches.empty?
373
+ return matches.first if matches.size == 1
374
+
375
+ problem = matches.empty? ? "no item matching" : "more than one item matching"
376
+ candidates = (matches.empty? ? items : matches).map { |item| item["name"].inspect }.join(", ")
377
+ raise Thor::Error, "#{problem} #{item_text.inspect} on #{card.url}. Items: #{candidates}"
378
+ end
379
+
380
+ # @return [Array<Hash>] the check items of the card's checklists (of the --checklist one, if given)
381
+ def check_items!(card)
382
+ name = options[:checklist]
383
+ checklists = card.checklists.select { |candidate| name.nil? || candidate.name == name }
384
+ raise Thor::Error, "no checklist#{" called #{name.inspect}" if name} on #{card.url}" if checklists.empty?
385
+
386
+ checklists.flat_map(&:check_items)
387
+ end
388
+
389
+ # @param card [Trello::Card]
390
+ # @return [Hash]
391
+ def card_as_hash(card)
392
+ {
393
+ title: card.name,
394
+ description: card.desc,
395
+ url: card.url,
396
+ checklists: card.checklists.map { |checklist| checklist_as_hash(checklist) },
397
+ attachment_urls: card.attachments.map(&:url)
398
+ }
399
+ end
400
+
401
+ # @param checklist [Trello::Checklist]
402
+ # @return [Hash]
403
+ def checklist_as_hash(checklist)
404
+ {
405
+ name: checklist.name,
406
+ items: checklist.check_items.map do |item|
407
+ { name: item["name"], complete: item["state"] == "complete" }
408
+ end
409
+ }
410
+ end
170
411
  end
171
- # rubocop:enable Metrics/ClassLength
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trello_tool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Diggins
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-09-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: ruby-trello
@@ -38,7 +37,6 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
- description:
42
40
  email:
43
41
  - tim@red56.uk
44
42
  executables:
@@ -73,7 +71,6 @@ metadata:
73
71
  source_code_uri: https://github.com/timdiggins/trello_tool
74
72
  changelog_uri: https://github.com/timdiggins/trello_tool/blob/main/CHANGELOG.md
75
73
  rubygems_mfa_required: 'true'
76
- post_install_message:
77
74
  rdoc_options: []
78
75
  require_paths:
79
76
  - lib
@@ -88,8 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
85
  - !ruby/object:Gem::Version
89
86
  version: '0'
90
87
  requirements: []
91
- rubygems_version: 3.5.15
92
- signing_key:
88
+ rubygems_version: 3.6.9
93
89
  specification_version: 4
94
90
  summary: Tool for doing basic things to a dev trello using the api.
95
91
  test_files: []