checkoff 0.258.0 → 0.261.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 +4 -4
- data/lib/checkoff/attachments.rb +14 -15
- data/lib/checkoff/cli.rb +7 -12
- data/lib/checkoff/clients.rb +0 -2
- data/lib/checkoff/custom_fields.rb +13 -24
- data/lib/checkoff/internal/asana_event_enrichment.rb +11 -21
- data/lib/checkoff/internal/asana_event_filter.rb +1 -5
- data/lib/checkoff/internal/config_loader.rb +0 -2
- data/lib/checkoff/internal/logging.rb +0 -2
- data/lib/checkoff/internal/project_hashes.rb +26 -4
- data/lib/checkoff/internal/search_url/custom_field_param_converter.rb +9 -10
- data/lib/checkoff/internal/search_url/custom_field_variant.rb +7 -2
- data/lib/checkoff/internal/search_url/date_param_converter.rb +13 -10
- data/lib/checkoff/internal/search_url/parser.rb +2 -7
- data/lib/checkoff/internal/search_url/simple_param_converter.rb +1 -4
- data/lib/checkoff/internal/section_selector_evaluator.rb +1 -1
- data/lib/checkoff/internal/selector_classes/common/function_evaluator.rb +2 -2
- data/lib/checkoff/internal/selector_classes/common.rb +2 -3
- data/lib/checkoff/internal/selector_classes/function_evaluator.rb +9 -4
- data/lib/checkoff/internal/selector_classes/project/function_evaluator.rb +2 -2
- data/lib/checkoff/internal/selector_classes/project.rb +0 -1
- data/lib/checkoff/internal/selector_classes/section/function_evaluator.rb +2 -2
- data/lib/checkoff/internal/selector_classes/section.rb +1 -2
- data/lib/checkoff/internal/selector_classes/task/function_evaluator.rb +2 -2
- data/lib/checkoff/internal/selector_classes/task.rb +2 -26
- data/lib/checkoff/internal/selector_evaluator.rb +6 -5
- data/lib/checkoff/internal/task_hashes.rb +17 -9
- data/lib/checkoff/internal/task_timing.rb +0 -4
- data/lib/checkoff/internal/thread_local.rb +0 -2
- data/lib/checkoff/monkeypatches/resource_marshalling.rb +3 -3
- data/lib/checkoff/my_tasks.rb +1 -4
- data/lib/checkoff/portfolios.rb +0 -1
- data/lib/checkoff/project_selectors.rb +1 -1
- data/lib/checkoff/projects.rb +19 -8
- data/lib/checkoff/resources.rb +14 -3
- data/lib/checkoff/sections.rb +9 -9
- data/lib/checkoff/subtasks.rb +1 -2
- data/lib/checkoff/tags.rb +3 -4
- data/lib/checkoff/task_searches.rb +1 -8
- data/lib/checkoff/task_selectors.rb +25 -12
- data/lib/checkoff/tasks.rb +6 -14
- data/lib/checkoff/timelines.rb +3 -20
- data/lib/checkoff/timing.rb +1 -2
- data/lib/checkoff/version.rb +1 -1
- data/lib/checkoff/workspaces.rb +1 -7
- data/rbi/checkoff.rbi +99 -146
- data/sig/checkoff.rbs +86 -153
- metadata +2 -2
|
@@ -73,9 +73,6 @@ module Checkoff
|
|
|
73
73
|
workspace = workspaces.workspace_or_raise(workspace_name)
|
|
74
74
|
api_params, task_selector = @search_url_parser.convert_params(url)
|
|
75
75
|
debug { "Task search params: api_params=#{api_params}, task_selector=#{task_selector}" }
|
|
76
|
-
# @sg-ignore task_selector expected Symbol,Array<Symbol,Integer,Array> received
|
|
77
|
-
# Hash{String=>String} — Solargraph mis-assigns tuple-destructured types from
|
|
78
|
-
# `api_params, task_selector = @search_url_parser.convert_params(url)` above
|
|
79
76
|
raw_task_search(api_params, workspace_gid: workspace.gid, task_selector:,
|
|
80
77
|
extra_fields:)
|
|
81
78
|
end
|
|
@@ -189,12 +186,8 @@ module Checkoff
|
|
|
189
186
|
|
|
190
187
|
# @param [Array<String>] extra_fields
|
|
191
188
|
# @return [Hash{Symbol => Array<String>}]
|
|
192
|
-
# @sg-ignore return type could not be inferred — bracket access on a Hash{Symbol=>undefined}
|
|
193
|
-
# local doesn't narrow even with a T.cast on the return expression
|
|
194
189
|
def calculate_api_options(extra_fields)
|
|
195
|
-
|
|
196
|
-
all_options = projects.task_options(extra_fields: ['custom_fields'] + extra_fields)
|
|
197
|
-
all_options[:options]
|
|
190
|
+
{ fields: projects.task_fields(extra_fields: ['custom_fields'] + extra_fields) }
|
|
198
191
|
end
|
|
199
192
|
|
|
200
193
|
# bundle exec ./task_searches.rb
|
|
@@ -40,7 +40,7 @@ module Checkoff
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# @param [Asana::Resources::Task] task
|
|
43
|
-
# @param [Symbol, Array<Symbol, Integer, Array>] task_selector Filter based on
|
|
43
|
+
# @param [Symbol, Array<Symbol, String, Integer, Array>] task_selector Filter based on
|
|
44
44
|
# task details. Examples: [:tag, 'foo'] [:not, [:tag, 'foo']] [:tag, 'foo']
|
|
45
45
|
# @return [Boolean]
|
|
46
46
|
def filter_via_task_selector(task, task_selector)
|
|
@@ -60,30 +60,43 @@ module Checkoff
|
|
|
60
60
|
# @return [Checkoff::CustomFields]
|
|
61
61
|
attr_reader :custom_fields
|
|
62
62
|
|
|
63
|
+
class << self
|
|
64
|
+
# @return [Array(Symbol, Array)]
|
|
65
|
+
def task_selector
|
|
66
|
+
task_selector_json = ARGV[2] || raise('Please pass task_selector in JSON form as third argument')
|
|
67
|
+
function_name, args = validate_task_selector(JSON.parse(task_selector_json))
|
|
68
|
+
[function_name.to_sym, args]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @param parsed [Object] result of JSON.parse on a task selector
|
|
72
|
+
# @return [Array(String, Array)]
|
|
73
|
+
def validate_task_selector(parsed)
|
|
74
|
+
raise "Expected a 2-element [function_name, args] array, got #{parsed.inspect}" \
|
|
75
|
+
unless parsed.is_a?(Array) && parsed.length == 2
|
|
76
|
+
|
|
77
|
+
function_name = parsed.fetch(0)
|
|
78
|
+
args = parsed.fetch(1)
|
|
79
|
+
raise "Expected function_name to be a String, got #{function_name.inspect}" \
|
|
80
|
+
unless function_name.is_a?(String)
|
|
81
|
+
raise "Expected args to be an Array, got #{args.inspect}" unless args.is_a?(Array)
|
|
82
|
+
|
|
83
|
+
[function_name, args]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
63
87
|
# bundle exec ./task_selectors.rb
|
|
64
88
|
# :nocov:
|
|
65
89
|
class << self
|
|
66
90
|
# @return [String]
|
|
67
|
-
# @sg-ignore `x || raise(...)` isn't inferred as narrowing away the nil branch
|
|
68
91
|
def project_name
|
|
69
92
|
ARGV[1] || raise('Please pass project name to pull tasks from as first argument')
|
|
70
93
|
end
|
|
71
94
|
|
|
72
95
|
# @return [String]
|
|
73
|
-
# @sg-ignore `x || raise(...)` isn't inferred as narrowing away the nil branch
|
|
74
96
|
def workspace_name
|
|
75
97
|
ARGV[0] || raise('Please pass workspace name as first argument')
|
|
76
98
|
end
|
|
77
99
|
|
|
78
|
-
# @return [Array(Symbol, Array)]
|
|
79
|
-
# @sg-ignore `x || raise(...)` isn't inferred as narrowing away the nil branch
|
|
80
|
-
def task_selector
|
|
81
|
-
task_selector_json = ARGV[2] || raise('Please pass task_selector in JSON form as third argument')
|
|
82
|
-
|
|
83
|
-
# @return [Symbol, Array]
|
|
84
|
-
T.cast(JSON.parse(task_selector_json), [Symbol, Array])
|
|
85
|
-
end
|
|
86
|
-
|
|
87
100
|
# @return [void]
|
|
88
101
|
def run
|
|
89
102
|
require 'checkoff/projects'
|
data/lib/checkoff/tasks.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Checkoff
|
|
|
32
32
|
LONG_CACHE_TIME = MINUTE * 15
|
|
33
33
|
SHORT_CACHE_TIME = MINUTE * 5
|
|
34
34
|
|
|
35
|
-
# @param config [Hash, Checkoff::Internal::EnvFallbackConfigLoader]
|
|
35
|
+
# @param config [Hash{Symbol => Object}, Checkoff::Internal::EnvFallbackConfigLoader]
|
|
36
36
|
# @param client [Asana::Client]
|
|
37
37
|
# @param workspaces [Checkoff::Workspaces]
|
|
38
38
|
# @param sections [Checkoff::Sections]
|
|
@@ -180,8 +180,6 @@ module Checkoff
|
|
|
180
180
|
# @param assignee_gid [String]
|
|
181
181
|
#
|
|
182
182
|
# @return [Asana::Resources::Task]
|
|
183
|
-
# @sg-ignore @asana_task.create return type could not be inferred — calling a class method
|
|
184
|
-
# through a Class<T>-typed ivar is a known Solargraph dispatch limitation
|
|
185
183
|
def add_task(name,
|
|
186
184
|
workspace_gid: @workspaces.default_workspace_gid,
|
|
187
185
|
assignee_gid: default_assignee_gid)
|
|
@@ -282,7 +280,7 @@ module Checkoff
|
|
|
282
280
|
task_hashes.task_to_h(task)
|
|
283
281
|
end
|
|
284
282
|
|
|
285
|
-
# @param task_data [Hash]
|
|
283
|
+
# @param task_data [Hash{String => Object}]
|
|
286
284
|
#
|
|
287
285
|
# @return [Asana::Resources::Task]
|
|
288
286
|
def h_to_task(task_data)
|
|
@@ -295,16 +293,14 @@ module Checkoff
|
|
|
295
293
|
# @param portfolio_name [String]
|
|
296
294
|
# @param workspace_name [String]
|
|
297
295
|
# @return [Boolean]
|
|
298
|
-
# @sg-ignore Checkoff::Tasks#in_portfolio_named? return type could not be inferred
|
|
299
296
|
def in_portfolio_named?(task,
|
|
300
297
|
portfolio_name,
|
|
301
298
|
workspace_name: T.must(@workspaces.default_workspace.name))
|
|
302
299
|
portfolio_projects = @portfolios.projects_in_portfolio(workspace_name, portfolio_name)
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
project_gid = T.cast(m.fetch('project'), T::Hash[String, T.untyped]).fetch('gid')
|
|
300
|
+
task.memberships.any? do |membership|
|
|
301
|
+
project_gid = membership.fetch('project').fetch('gid')
|
|
306
302
|
portfolio_projects.any? { |portfolio_project| portfolio_project.gid == project_gid }
|
|
307
|
-
end
|
|
303
|
+
end
|
|
308
304
|
end
|
|
309
305
|
|
|
310
306
|
# True if the task is in a project which is in the given portfolio
|
|
@@ -320,8 +316,7 @@ module Checkoff
|
|
|
320
316
|
portfolio_project_gids = portfolio_projects.map(&:gid)
|
|
321
317
|
seen = T.let(false, T::Boolean)
|
|
322
318
|
task.memberships.each do |membership|
|
|
323
|
-
|
|
324
|
-
project_gid = T.cast(m.fetch('project'), T::Hash[String, T.untyped]).fetch('gid')
|
|
319
|
+
project_gid = membership.fetch('project').fetch('gid')
|
|
325
320
|
next unless portfolio_project_gids.include?(project_gid)
|
|
326
321
|
return true if seen
|
|
327
322
|
|
|
@@ -386,9 +381,6 @@ module Checkoff
|
|
|
386
381
|
end
|
|
387
382
|
|
|
388
383
|
# @return [String]
|
|
389
|
-
# @sg-ignore @config.fetch return type could not be inferred — @config is intentionally
|
|
390
|
-
# dual-typed [Hash, EnvFallbackConfigLoader] throughout this codebase; Solargraph can't
|
|
391
|
-
# unify #fetch across that union
|
|
392
384
|
def default_assignee_gid
|
|
393
385
|
@config.fetch(:default_assignee_gid)
|
|
394
386
|
end
|
data/lib/checkoff/timelines.rb
CHANGED
|
@@ -54,16 +54,11 @@ module Checkoff
|
|
|
54
54
|
memberships_data = task_data.fetch('memberships')
|
|
55
55
|
memberships_data.all? do |membership_data|
|
|
56
56
|
# @type [Hash{String => String}]
|
|
57
|
-
# @sg-ignore Hash#fetch generic<X> leak on rbs >= 4.1.0, fix in progress upstream
|
|
58
|
-
# https://github.com/castwide/solargraph/pull/1228
|
|
59
57
|
section_data = membership_data.fetch('section')
|
|
60
58
|
section_gid = section_data.fetch('gid')
|
|
61
|
-
# @sg-ignore Hash#fetch generic<X> leak on rbs >= 4.1.0, fix in progress upstream
|
|
62
|
-
# https://github.com/castwide/solargraph/pull/1228
|
|
63
59
|
section = @sections.section_by_gid(section_gid)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# without a nil guard — looks like a real gap, flagging for the follow-up code PR
|
|
60
|
+
next false if section.nil?
|
|
61
|
+
|
|
67
62
|
task_data_dependent_on_previous_section_last_milestone?(task_data, section)
|
|
68
63
|
end
|
|
69
64
|
end
|
|
@@ -85,20 +80,14 @@ module Checkoff
|
|
|
85
80
|
md = membership_data
|
|
86
81
|
unless limit_to_portfolio_name.nil?
|
|
87
82
|
# @type [Hash{String => Object}]
|
|
88
|
-
# @sg-ignore Hash#fetch generic<X> leak on rbs >= 4.1.0, fix in progress upstream
|
|
89
|
-
# https://github.com/castwide/solargraph/pull/1228
|
|
90
83
|
project_data = md.fetch('project')
|
|
91
84
|
project_gid = project_data.fetch('gid')
|
|
92
85
|
next true unless limit_to_projects.map(&:gid).include? project_gid
|
|
93
86
|
end
|
|
94
87
|
# @type [Hash{String => Object}]
|
|
95
|
-
# @sg-ignore Hash#fetch generic<X> leak on rbs >= 4.1.0, fix in progress upstream
|
|
96
|
-
# https://github.com/castwide/solargraph/pull/1228
|
|
97
88
|
section_data = md.fetch('section')
|
|
98
89
|
section_gid = section_data.fetch('gid')
|
|
99
90
|
|
|
100
|
-
# @sg-ignore Hash#fetch generic<X> leak on rbs >= 4.1.0, fix in progress upstream
|
|
101
|
-
# https://github.com/castwide/solargraph/pull/1228
|
|
102
91
|
last_milestone = last_milestone_in_section(section_gid)
|
|
103
92
|
|
|
104
93
|
next false if last_milestone.nil?
|
|
@@ -107,8 +96,6 @@ module Checkoff
|
|
|
107
96
|
|
|
108
97
|
all_dependent_task_gids ||= @tasks.all_dependent_tasks(task).map(&:gid)
|
|
109
98
|
|
|
110
|
-
# @sg-ignore all_dependent_task_gids is nil-initialized then set via ||= above, but
|
|
111
|
-
# Solargraph doesn't narrow it back to non-nil after the reassignment
|
|
112
99
|
all_dependent_task_gids.include? last_milestone.gid
|
|
113
100
|
end
|
|
114
101
|
end
|
|
@@ -130,8 +117,6 @@ module Checkoff
|
|
|
130
117
|
md = membership_data
|
|
131
118
|
unless limit_to_portfolio_name.nil?
|
|
132
119
|
# @type [Hash{String => Object}]
|
|
133
|
-
# @sg-ignore Hash#fetch generic<X> leak on rbs >= 4.1.0, fix in progress upstream
|
|
134
|
-
# https://github.com/castwide/solargraph/pull/1228
|
|
135
120
|
project_data = md.fetch('project')
|
|
136
121
|
project_gid = project_data.fetch('gid')
|
|
137
122
|
next true unless limit_to_projects.map(&:gid).include? project_gid
|
|
@@ -146,8 +131,6 @@ module Checkoff
|
|
|
146
131
|
dependent_task.resource_subtype == 'milestone'
|
|
147
132
|
end
|
|
148
133
|
|
|
149
|
-
# @sg-ignore all_dependent_milestones is nil-initialized then set via ||= above, but
|
|
150
|
-
# Solargraph doesn't narrow it back to non-nil after the reassignment
|
|
151
134
|
all_dependent_milestones.any? do |milestone|
|
|
152
135
|
milestone.memberships.any? do |milestone_membership_data|
|
|
153
136
|
milestone_membership_data.fetch('project').fetch('gid') == project_gid
|
|
@@ -169,7 +152,7 @@ module Checkoff
|
|
|
169
152
|
|
|
170
153
|
private
|
|
171
154
|
|
|
172
|
-
# @param task_data [Hash]
|
|
155
|
+
# @param task_data [Hash{String => Object}]
|
|
173
156
|
# @param section [Asana::Resources::Section]
|
|
174
157
|
#
|
|
175
158
|
# @return [Boolean]
|
data/lib/checkoff/timing.rb
CHANGED
|
@@ -36,7 +36,7 @@ module Checkoff
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# @param date_or_time [Date,Time,nil]
|
|
39
|
-
# @param period [Symbol, Array
|
|
39
|
+
# @param period [Symbol, Array<Symbol, Integer>]
|
|
40
40
|
#
|
|
41
41
|
# Valid values: :this_week, :now_or_before, :indefinite, [:less_than_n_days_ago, Integer]
|
|
42
42
|
def in_period?(date_or_time, period)
|
|
@@ -175,7 +175,6 @@ module Checkoff
|
|
|
175
175
|
# @param num_days [Integer]
|
|
176
176
|
#
|
|
177
177
|
# @return [Date]
|
|
178
|
-
# @sg-ignore Checkoff::Timing#n_days_from_today return type could not be inferred
|
|
179
178
|
def n_days_from_today(num_days)
|
|
180
179
|
T.cast(@today_getter.today + num_days, Date)
|
|
181
180
|
end
|
data/lib/checkoff/version.rb
CHANGED
data/lib/checkoff/workspaces.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Checkoff
|
|
|
22
22
|
# @!parse
|
|
23
23
|
# extend CacheMethod::ClassMethods
|
|
24
24
|
|
|
25
|
-
# @param config [Hash, Checkoff::Internal::EnvFallbackConfigLoader]
|
|
25
|
+
# @param config [Hash{Symbol => Object}, Checkoff::Internal::EnvFallbackConfigLoader]
|
|
26
26
|
# @param client [Asana::Client]
|
|
27
27
|
# @param asana_workspace [Class<Asana::Resources::Workspace>]
|
|
28
28
|
def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
|
|
@@ -44,8 +44,6 @@ module Checkoff
|
|
|
44
44
|
cache_method :workspace, LONG_CACHE_TIME
|
|
45
45
|
|
|
46
46
|
# @return [Asana::Resources::Workspace]
|
|
47
|
-
# @sg-ignore @asana_workspace.find_by_id return type could not be inferred — calling a
|
|
48
|
-
# class method through a Class<T>-typed ivar is a known Solargraph dispatch limitation
|
|
49
47
|
def default_workspace
|
|
50
48
|
@asana_workspace.find_by_id(client, default_workspace_gid)
|
|
51
49
|
end
|
|
@@ -53,7 +51,6 @@ module Checkoff
|
|
|
53
51
|
|
|
54
52
|
# @param [String, Symbol] workspace_name
|
|
55
53
|
# @return [Asana::Resources::Workspace]
|
|
56
|
-
# @sg-ignore workspace() is nil-checked below
|
|
57
54
|
def workspace_or_raise(workspace_name)
|
|
58
55
|
w = workspace(workspace_name)
|
|
59
56
|
raise "Could not find workspace #{workspace_name}" if w.nil?
|
|
@@ -62,9 +59,6 @@ module Checkoff
|
|
|
62
59
|
end
|
|
63
60
|
|
|
64
61
|
# @return [String]
|
|
65
|
-
# @sg-ignore @config.fetch return type could not be inferred — @config is intentionally
|
|
66
|
-
# dual-typed [Hash, EnvFallbackConfigLoader] throughout this codebase; Solargraph can't
|
|
67
|
-
# unify #fetch across that union
|
|
68
62
|
def default_workspace_gid
|
|
69
63
|
@config.fetch(:default_workspace_gid)
|
|
70
64
|
end
|