linear-cli 0.7.5 → 0.7.7
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/CHANGELOG.md +9 -2
- data/Readme.adoc +11 -3
- data/changelog/0.7.7/added_ability_to_attach_project_to_command.yml +4 -0
- data/changelog/0.7.7/added_issue_pr_command.yml +4 -0
- data/changelog/0.7.7/added_lcomment_alias_to_add_comments_to_issues.yml +4 -0
- data/changelog/0.7.7/tag.yml +1 -0
- data/exe/lc +5 -1
- data/exe/lclose +1 -0
- data/exe/lcls +1 -0
- data/exe/lcomment +1 -0
- data/exe/lcreate +1 -0
- data/exe/linear-cli +8 -1
- data/exe/{lc.sh → scripts/lc.sh} +4 -3
- data/exe/scripts/lcls.sh +2 -0
- data/exe/scripts/lcomment.sh +2 -0
- data/lib/linear/api.rb +1 -1
- data/lib/linear/cli/caller.rb +6 -1
- data/lib/linear/cli/sub_commands.rb +5 -59
- data/lib/linear/cli/version.rb +1 -1
- data/lib/linear/cli/what_for.rb +143 -0
- data/lib/linear/cli.rb +8 -1
- data/lib/linear/commands/issue/create.rb +1 -0
- data/lib/linear/commands/issue/pr.rb +38 -0
- data/lib/linear/commands/issue/update.rb +21 -6
- data/lib/linear/commands/issue.rb +54 -21
- data/lib/linear/models/base_model/class_methods.rb +129 -0
- data/lib/linear/models/base_model/method_magic.rb +23 -0
- data/lib/linear/models/base_model.rb +9 -108
- data/lib/linear/models/issue/class_methods.rb +44 -0
- data/lib/linear/models/issue.rb +23 -38
- data/lib/linear/models/project.rb +47 -0
- data/lib/linear/models/team.rb +6 -9
- data/lib/linear.rb +8 -0
- data/linear-cli.gemspec +2 -1
- metadata +33 -10
- data/exe/lclose +0 -4
- data/exe/lcls +0 -4
- data/exe/lcls.sh +0 -2
- data/exe/lcreate +0 -4
- /data/exe/{lclose.sh → scripts/lclose.sh} +0 -0
- /data/exe/{lcreate.sh → scripts/lcreate.sh} +0 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubyists
|
4
|
+
module Linear
|
5
|
+
class BaseModel
|
6
|
+
# Class methods for Linear models.
|
7
|
+
module ClassMethods
|
8
|
+
def setter!(relation, klass)
|
9
|
+
define_method "#{relation}=" do |val|
|
10
|
+
hash = val.is_a?(Hash) ? val : val.updated_data
|
11
|
+
updated_data[relation] = hash
|
12
|
+
instance_variable_set("@#{relation}", Rubyists::Linear.const_get(klass).new(hash))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def getter!(relation)
|
17
|
+
define_method relation do
|
18
|
+
return instance_variable_get("@#{relation}") if instance_variable_defined?("@#{relation}")
|
19
|
+
|
20
|
+
return unless (val = updated_data[relation])
|
21
|
+
|
22
|
+
send("#{relation}=", val)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def many_to_one(relation, klass = nil)
|
27
|
+
klass ||= relation.to_s.camelize.to_sym
|
28
|
+
getter! relation
|
29
|
+
setter! relation, klass
|
30
|
+
end
|
31
|
+
|
32
|
+
alias one_to_one many_to_one
|
33
|
+
|
34
|
+
def many_setter!(relation, klass)
|
35
|
+
define_method "#{relation}=" do |val|
|
36
|
+
vals = if val&.key?(:nodes)
|
37
|
+
val[:nodes]
|
38
|
+
else
|
39
|
+
Array(val)
|
40
|
+
end
|
41
|
+
updated_data[relation] = vals.map { |v| v.is_a?(Hash) ? v : v.updated_data }
|
42
|
+
new_relations = vals.map { |v| v.is_a?(Hash) ? Rubyists::Linear.const_get(klass).new(v) : v }
|
43
|
+
instance_variable_set("@#{relation}", new_relations)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def one_to_many(relation, klass = nil)
|
48
|
+
klass ||= relation.to_s.singularize.camelize.to_sym
|
49
|
+
getter! relation
|
50
|
+
many_setter! relation, klass
|
51
|
+
end
|
52
|
+
|
53
|
+
def find(id_val)
|
54
|
+
camel_name = just_name.camelize :lower
|
55
|
+
ff = full_fragment
|
56
|
+
query_data = Api.query(query { __node(camel_name, id: id_val) { ___ ff } })
|
57
|
+
new query_data[camel_name.to_sym]
|
58
|
+
end
|
59
|
+
|
60
|
+
def const_added(const)
|
61
|
+
return unless const == :Base
|
62
|
+
|
63
|
+
include MethodMagic
|
64
|
+
end
|
65
|
+
|
66
|
+
def allq(filter: nil, limit: 50, after: nil)
|
67
|
+
args = { first: limit }
|
68
|
+
args[:filter] = filter ? basic_filter.merge(filter) : basic_filter
|
69
|
+
args.delete(:filter) if args[:filter].empty?
|
70
|
+
args[:after] = after if after
|
71
|
+
all_query args, plural.to_s, base_fragment
|
72
|
+
end
|
73
|
+
|
74
|
+
def all_query(args, subject, base_fragment)
|
75
|
+
query do
|
76
|
+
__node(subject, args) do
|
77
|
+
edges do
|
78
|
+
node { ___ base_fragment }
|
79
|
+
cursor
|
80
|
+
end
|
81
|
+
___ Fragments::PageInfo
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def just_name
|
87
|
+
name.split('::').last
|
88
|
+
end
|
89
|
+
|
90
|
+
def base_fragment
|
91
|
+
const_get(:Base)
|
92
|
+
end
|
93
|
+
|
94
|
+
def full_fragment
|
95
|
+
base_fragment
|
96
|
+
end
|
97
|
+
|
98
|
+
def basic_filter
|
99
|
+
return const_get(:BASIC_FILTER) if const_defined?(:BASIC_FILTER)
|
100
|
+
|
101
|
+
{}
|
102
|
+
end
|
103
|
+
|
104
|
+
def plural
|
105
|
+
return const_get(:PLURAL) if const_defined?(:PLURAL)
|
106
|
+
|
107
|
+
just_name.downcase.pluralize.to_sym
|
108
|
+
end
|
109
|
+
|
110
|
+
def gql_query(filter: nil, after: nil)
|
111
|
+
Api.query(allq(filter:, after:))
|
112
|
+
end
|
113
|
+
|
114
|
+
def all(after: nil, filter: nil, max: 100)
|
115
|
+
edges = []
|
116
|
+
moar = true
|
117
|
+
while moar
|
118
|
+
data = gql_query(filter:, after:)
|
119
|
+
subjects = data[plural]
|
120
|
+
edges += subjects[:edges]
|
121
|
+
moar = false if edges.size >= max || !subjects[:pageInfo][:hasNextPage]
|
122
|
+
after = subjects[:pageInfo][:endCursor]
|
123
|
+
end
|
124
|
+
edges.map { |edge| new edge[:node] }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubyists
|
4
|
+
module Linear
|
5
|
+
class BaseModel
|
6
|
+
# Methods for Linear models.
|
7
|
+
module MethodMagic
|
8
|
+
def self.included(base) # rubocop:disable Metrics/AbcSize
|
9
|
+
base.instance_eval do
|
10
|
+
base.base_fragment.__nodes.each do |node|
|
11
|
+
sym = node.__name.to_sym
|
12
|
+
define_method(sym) { updated_data[sym] } unless instance_methods.include? sym
|
13
|
+
esym = :"#{sym}="
|
14
|
+
next if instance_methods.include? esym
|
15
|
+
|
16
|
+
define_method(esym) { |value| updated_data[sym] = value }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -8,120 +8,17 @@ module Rubyists
|
|
8
8
|
# Namespace for Linear
|
9
9
|
module Linear
|
10
10
|
L :api, :fragments
|
11
|
-
|
11
|
+
M 'base_model/method_magic', 'base_model/class_methods'
|
12
|
+
# The base model for all Linear models
|
12
13
|
class BaseModel
|
13
14
|
extend GQLi::DSL
|
14
15
|
include GQLi::DSL
|
15
16
|
include SemanticLogger::Loggable
|
16
|
-
|
17
|
-
# Methods for Linear models.
|
18
|
-
module MethodMagic
|
19
|
-
def self.included(base) # rubocop:disable Metrics/MethodLength
|
20
|
-
base.instance_eval do
|
21
|
-
base.base_fragment.__nodes.each do |node|
|
22
|
-
sym = node.__name.to_sym
|
23
|
-
define_method node.__name do
|
24
|
-
updated_data[sym]
|
25
|
-
end
|
26
|
-
|
27
|
-
define_method "#{node.__name}=" do |value|
|
28
|
-
updated_data[sym] = value
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Class methods for Linear models.
|
36
|
-
class << self
|
37
|
-
def one_to_one(relation, klass)
|
38
|
-
define_method relation do
|
39
|
-
return instance_variable_get("@#{relation}") if instance_variable_defined?("@#{relation}")
|
40
|
-
return unless (val = data[relation])
|
41
|
-
|
42
|
-
instance_variable_set("@#{relation}", Rubyists::Linear.const_get(klass).new(val))
|
43
|
-
end
|
44
|
-
|
45
|
-
define_method "#{relation}=" do |val|
|
46
|
-
hash = val.is_a?(Hash) ? val : val.data
|
47
|
-
updated_data[relation] = hash
|
48
|
-
instance_variable_set("@#{relation}", Rubyists::Linear.const_get(klass).new(hash))
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def find(id_val)
|
53
|
-
camel_name = just_name.camelize :lower
|
54
|
-
bf = base_fragment
|
55
|
-
query_data = Api.query(query { __node(camel_name, id: id_val) { ___ bf } })
|
56
|
-
new query_data[camel_name.to_sym]
|
57
|
-
end
|
58
|
-
|
59
|
-
def const_added(const)
|
60
|
-
return unless const == :Base
|
61
|
-
|
62
|
-
include MethodMagic
|
63
|
-
end
|
64
|
-
|
65
|
-
def allq(filter: nil, limit: 50, after: nil)
|
66
|
-
args = { first: limit }
|
67
|
-
args[:filter] = filter ? basic_filter.merge(filter) : basic_filter
|
68
|
-
args.delete(:filter) if args[:filter].empty?
|
69
|
-
args[:after] = after if after
|
70
|
-
all_query args, plural.to_s, base_fragment
|
71
|
-
end
|
72
|
-
|
73
|
-
def all_query(args, subject, base_fragment)
|
74
|
-
query do
|
75
|
-
__node(subject, args) do
|
76
|
-
edges do
|
77
|
-
node { ___ base_fragment }
|
78
|
-
cursor
|
79
|
-
end
|
80
|
-
___ Fragments::PageInfo
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def just_name
|
86
|
-
name.split('::').last
|
87
|
-
end
|
88
|
-
|
89
|
-
def base_fragment
|
90
|
-
const_get(:Base)
|
91
|
-
end
|
92
|
-
|
93
|
-
def basic_filter
|
94
|
-
return const_get(:BASIC_FILTER) if const_defined?(:BASIC_FILTER)
|
95
|
-
|
96
|
-
{}
|
97
|
-
end
|
98
|
-
|
99
|
-
def plural
|
100
|
-
return const_get(:PLURAL) if const_defined?(:PLURAL)
|
101
|
-
|
102
|
-
just_name.downcase.pluralize.to_sym
|
103
|
-
end
|
104
|
-
|
105
|
-
def gql_query(filter: nil, after: nil)
|
106
|
-
Api.query(allq(filter:, after:))
|
107
|
-
end
|
108
|
-
|
109
|
-
def all(after: nil, filter: nil, max: 100)
|
110
|
-
edges = []
|
111
|
-
moar = true
|
112
|
-
while moar
|
113
|
-
data = gql_query(filter:, after:)
|
114
|
-
subjects = data[plural]
|
115
|
-
edges += subjects[:edges]
|
116
|
-
moar = false if edges.size >= max || !subjects[:pageInfo][:hasNextPage]
|
117
|
-
after = subjects[:pageInfo][:endCursor]
|
118
|
-
end
|
119
|
-
edges.map { |edge| new edge[:node] }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
17
|
+
extend ClassMethods
|
123
18
|
attr_reader :data, :updated_data
|
124
19
|
|
20
|
+
CANCELLED_STATES = %w[cancelled canceled].freeze
|
21
|
+
|
125
22
|
def initialize(data)
|
126
23
|
data.each_key { |k| raise SmellsBad, "Unknown key #{k}" unless respond_to? "#{k}=" }
|
127
24
|
@data = data
|
@@ -136,6 +33,10 @@ module Rubyists
|
|
136
33
|
workflow_states.select { |ws| ws.type == 'completed' }
|
137
34
|
end
|
138
35
|
|
36
|
+
def cancelled_states
|
37
|
+
workflow_states.select { |ws| CANCELLED_STATES.include? ws.type }
|
38
|
+
end
|
39
|
+
|
139
40
|
def to_h
|
140
41
|
updated_data
|
141
42
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rubyists
|
4
|
+
# Namespace for Linear
|
5
|
+
module Linear
|
6
|
+
M :user, :team
|
7
|
+
# The Issue class represents a Linear issue.
|
8
|
+
class Issue
|
9
|
+
# Class methods for Issue
|
10
|
+
module ClassMethods
|
11
|
+
def base_fragment
|
12
|
+
@base_fragment ||= fragment('BaseIssue', 'Issue') do
|
13
|
+
___ Base
|
14
|
+
assignee { ___ User.base_fragment }
|
15
|
+
team { ___ Team.base_fragment }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def full_fragment
|
20
|
+
@full_fragment ||= fragment('FullIssue', 'Issue') do
|
21
|
+
___ Base
|
22
|
+
assignee { ___ User.full_fragment }
|
23
|
+
team { ___ Team.full_fragment }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_all(*slugs)
|
28
|
+
slugs.flatten.map { |slug| find(slug) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def create(title:, description:, team:, project:, labels: [])
|
32
|
+
team_id = team.id
|
33
|
+
label_ids = labels.map(&:id)
|
34
|
+
input = { title:, description:, teamId: team_id }
|
35
|
+
input[:labelIds] = label_ids unless label_ids.empty?
|
36
|
+
input[:projectId] = project.id if project
|
37
|
+
m = mutation { issueCreate(input:) { issue { ___ Issue.base_fragment } } }
|
38
|
+
query_data = Api.query(m)
|
39
|
+
new query_data.dig(:issueCreate, :issue)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/linear/models/issue.rb
CHANGED
@@ -5,13 +5,15 @@ require 'gqli'
|
|
5
5
|
module Rubyists
|
6
6
|
# Namespace for Linear
|
7
7
|
module Linear
|
8
|
-
M :base_model
|
8
|
+
M :base_model
|
9
9
|
Issue = Class.new(BaseModel)
|
10
|
+
M 'issue/class_methods'
|
10
11
|
# The Issue class represents a Linear issue.
|
11
|
-
class Issue
|
12
|
+
class Issue
|
12
13
|
include SemanticLogger::Loggable
|
13
|
-
|
14
|
-
|
14
|
+
extend ClassMethods
|
15
|
+
many_to_one :assignee, :User
|
16
|
+
many_to_one :team, :Team
|
15
17
|
|
16
18
|
BASIC_FILTER = { completedAt: { null: true } }.freeze
|
17
19
|
|
@@ -25,38 +27,6 @@ module Rubyists
|
|
25
27
|
updatedAt
|
26
28
|
end
|
27
29
|
|
28
|
-
class << self
|
29
|
-
def base_fragment
|
30
|
-
@base_fragment ||= fragment('IssueWithTeams', 'Issue') do
|
31
|
-
___ Base
|
32
|
-
assignee { ___ User.base_fragment }
|
33
|
-
team { ___ Team.base_fragment }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def find(slug)
|
38
|
-
q = query { issue(id: slug) { ___ Issue.base_fragment } }
|
39
|
-
data = Api.query(q)
|
40
|
-
raise NotFoundError, "Issue not found: #{slug}" if data.nil?
|
41
|
-
|
42
|
-
new(data[:issue])
|
43
|
-
end
|
44
|
-
|
45
|
-
def find_all(*slugs)
|
46
|
-
slugs.flatten.map { |slug| find(slug) }
|
47
|
-
end
|
48
|
-
|
49
|
-
def create(title:, description:, team:, labels: [])
|
50
|
-
team_id = team.id
|
51
|
-
label_ids = labels.map(&:id)
|
52
|
-
input = { title:, description:, teamId: team_id }
|
53
|
-
input[:labelIds] = label_ids unless label_ids.empty?
|
54
|
-
m = mutation { issueCreate(input:) { issue { ___ Issue.base_fragment } } }
|
55
|
-
query_data = Api.query(m)
|
56
|
-
new query_data.dig(:issueCreate, :issue)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
30
|
def comment_fragment
|
61
31
|
@comment_fragment ||= fragment('Comment', 'Comment') do
|
62
32
|
id
|
@@ -65,6 +35,21 @@ module Rubyists
|
|
65
35
|
end
|
66
36
|
end
|
67
37
|
|
38
|
+
def update!(input)
|
39
|
+
id_for_this = identifier
|
40
|
+
m = mutation { issueUpdate(id: id_for_this, input:) { issue { ___ Issue.full_fragment } } }
|
41
|
+
query_data = Api.query(m)
|
42
|
+
updated = query_data.dig(:issueUpdate, :issue)
|
43
|
+
raise SmellsBad, "Unknown response for issue update: #{data} (should have :issueUpdate key)" if updated.nil?
|
44
|
+
|
45
|
+
@data = @updated_data = updated
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def attach_to_project(project)
|
50
|
+
update!({ projectId: project.id })
|
51
|
+
end
|
52
|
+
|
68
53
|
# Reference for this mutation:
|
69
54
|
# https://studio.apollographql.com/public/Linear-API/variant/current/schema/reference/inputs/CommentCreateInput
|
70
55
|
def add_comment(comment)
|
@@ -81,7 +66,7 @@ module Rubyists
|
|
81
66
|
id_for_this = identifier
|
82
67
|
input = { stateId: close_state.id }
|
83
68
|
input[:trash] = true if trash
|
84
|
-
mutation { issueUpdate(id: id_for_this, input:) { issue { ___ Issue.
|
69
|
+
mutation { issueUpdate(id: id_for_this, input:) { issue { ___ Issue.full_fragment } } }
|
85
70
|
end
|
86
71
|
|
87
72
|
def close!(state: nil, trash: false)
|
@@ -97,7 +82,7 @@ module Rubyists
|
|
97
82
|
|
98
83
|
def assign!(user)
|
99
84
|
this_id = identifier
|
100
|
-
m = mutation { issueUpdate(id: this_id, input: { assigneeId: user.id }) { issue { ___ Issue.
|
85
|
+
m = mutation { issueUpdate(id: this_id, input: { assigneeId: user.id }) { issue { ___ Issue.full_fragment } } }
|
101
86
|
query_data = Api.query(m)
|
102
87
|
updated = query_data.dig(:issueUpdate, :issue)
|
103
88
|
raise SmellsBad, "Unknown response for issue update: #{data} (should have :issueUpdate key)" if updated.nil?
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'gqli'
|
4
|
+
|
5
|
+
module Rubyists
|
6
|
+
# Namespace for Linear
|
7
|
+
module Linear
|
8
|
+
M :base_model
|
9
|
+
Project = Class.new(BaseModel)
|
10
|
+
# The Project class represents a Linear workflow state.
|
11
|
+
class Project
|
12
|
+
include SemanticLogger::Loggable
|
13
|
+
|
14
|
+
Base = fragment('BaseProject', 'Project') do
|
15
|
+
id
|
16
|
+
name
|
17
|
+
content
|
18
|
+
slugId
|
19
|
+
description
|
20
|
+
url
|
21
|
+
createdAt
|
22
|
+
updatedAt
|
23
|
+
end
|
24
|
+
|
25
|
+
def slug
|
26
|
+
File.basename(url).sub("-#{slugId}", '')
|
27
|
+
end
|
28
|
+
|
29
|
+
def match_score?(string)
|
30
|
+
downed = string.downcase
|
31
|
+
return 100 if downed.split.join('-') == slug || downed == name.downcase
|
32
|
+
return 75 if name.include?(string) || slug.include?(downed)
|
33
|
+
return 50 if description.downcase.include?(downed)
|
34
|
+
|
35
|
+
0
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
format('%<name>-12s %<url>s', name:, url:)
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspection
|
43
|
+
format('name: "%<name>s" type: "%<url>s"', name:, url:)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/linear/models/team.rb
CHANGED
@@ -5,11 +5,12 @@ require 'gqli'
|
|
5
5
|
module Rubyists
|
6
6
|
# Namespace for Linear
|
7
7
|
module Linear
|
8
|
-
M :base_model, :issue, :
|
8
|
+
M :base_model, :issue, :project, :workflow_state, :user
|
9
9
|
Team = Class.new(BaseModel)
|
10
10
|
# The Issue class represents a Linear issue.
|
11
11
|
class Team
|
12
12
|
include SemanticLogger::Loggable
|
13
|
+
one_to_many :projects
|
13
14
|
|
14
15
|
# TODO: Make this configurable
|
15
16
|
BaseFilter = { # rubocop:disable Naming/ConstantName
|
@@ -29,15 +30,11 @@ module Rubyists
|
|
29
30
|
updatedAt
|
30
31
|
end
|
31
32
|
|
32
|
-
def self.
|
33
|
-
|
34
|
-
|
33
|
+
def self.full_fragment
|
34
|
+
@full_fragment ||= fragment('WholeTeam', 'Team') do
|
35
|
+
___ Base
|
36
|
+
projects { nodes { ___ Project.base_fragment } }
|
35
37
|
end
|
36
|
-
data = Api.query(q)
|
37
|
-
hash = data[:team]
|
38
|
-
raise NotFoundError, "Team not found: #{key}" unless hash
|
39
|
-
|
40
|
-
new hash
|
41
38
|
end
|
42
39
|
|
43
40
|
def self.mine
|
data/lib/linear.rb
CHANGED
@@ -24,6 +24,14 @@ module Rubyists
|
|
24
24
|
FEATURE_ROOT = ROOT/:features
|
25
25
|
DEBUG_LEVELS = %i[warn info debug trace].freeze
|
26
26
|
|
27
|
+
def self.tmpdir=(other)
|
28
|
+
@tmpdir = other.is_a?(Pathname) ? other : Pathname(other)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.tmpdir
|
32
|
+
@tmpdir || raise('tmpdir not set')
|
33
|
+
end
|
34
|
+
|
27
35
|
def self.L(*libraries) # rubocop:disable Naming/MethodName
|
28
36
|
Array(libraries).each { |library| require LIBROOT/library }
|
29
37
|
end
|
data/linear-cli.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
spec.bindir = 'exe'
|
32
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }.reject { |f| f.end_with?('.sh') }
|
33
33
|
spec.require_paths = ['lib']
|
34
34
|
|
35
35
|
# Uncomment to register a new dependency of your gem
|
@@ -43,6 +43,7 @@ Gem::Specification.new do |spec|
|
|
43
43
|
spec.add_dependency 'semantic_logger', '~> 4.0'
|
44
44
|
spec.add_dependency 'sequel', '~> 5.0'
|
45
45
|
spec.add_dependency 'sqlite3', '~> 1.7'
|
46
|
+
spec.add_dependency 'tty-editor', '~> 0.7'
|
46
47
|
spec.add_dependency 'tty-markdown', '~> 0.7'
|
47
48
|
spec.add_dependency 'tty-prompt', '~> 0.23'
|
48
49
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linear-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tj (bougyman) Vanderpoel
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base64
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '1.7'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: tty-editor
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0.7'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0.7'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: tty-markdown
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,13 +197,10 @@ email:
|
|
183
197
|
- tj@rubyists.com
|
184
198
|
executables:
|
185
199
|
- lc
|
186
|
-
- lc.sh
|
187
200
|
- lclose
|
188
|
-
- lclose.sh
|
189
201
|
- lcls
|
190
|
-
-
|
202
|
+
- lcomment
|
191
203
|
- lcreate
|
192
|
-
- lcreate.sh
|
193
204
|
- linear-cli
|
194
205
|
extensions: []
|
195
206
|
extra_rdoc_files: []
|
@@ -219,17 +230,23 @@ files:
|
|
219
230
|
- changelog/0.7.3/tag.yml
|
220
231
|
- changelog/0.7.5/fixed_problem_when_choosing_from_multiple_completed_states.yml
|
221
232
|
- changelog/0.7.5/tag.yml
|
233
|
+
- changelog/0.7.7/added_ability_to_attach_project_to_command.yml
|
234
|
+
- changelog/0.7.7/added_issue_pr_command.yml
|
235
|
+
- changelog/0.7.7/added_lcomment_alias_to_add_comments_to_issues.yml
|
236
|
+
- changelog/0.7.7/tag.yml
|
222
237
|
- changelog/unreleased/.gitkeep
|
223
238
|
- cinemas/listings.cinema
|
224
239
|
- exe/lc
|
225
|
-
- exe/lc.sh
|
226
240
|
- exe/lclose
|
227
|
-
- exe/lclose.sh
|
228
241
|
- exe/lcls
|
229
|
-
- exe/
|
242
|
+
- exe/lcomment
|
230
243
|
- exe/lcreate
|
231
|
-
- exe/lcreate.sh
|
232
244
|
- exe/linear-cli
|
245
|
+
- exe/scripts/lc.sh
|
246
|
+
- exe/scripts/lclose.sh
|
247
|
+
- exe/scripts/lcls.sh
|
248
|
+
- exe/scripts/lcomment.sh
|
249
|
+
- exe/scripts/lcreate.sh
|
233
250
|
- lib/linear.rb
|
234
251
|
- lib/linear/api.rb
|
235
252
|
- lib/linear/cli.rb
|
@@ -238,10 +255,12 @@ files:
|
|
238
255
|
- lib/linear/cli/sub_commands.rb
|
239
256
|
- lib/linear/cli/version.rb
|
240
257
|
- lib/linear/cli/watcher.rb
|
258
|
+
- lib/linear/cli/what_for.rb
|
241
259
|
- lib/linear/commands/issue.rb
|
242
260
|
- lib/linear/commands/issue/create.rb
|
243
261
|
- lib/linear/commands/issue/develop.rb
|
244
262
|
- lib/linear/commands/issue/list.rb
|
263
|
+
- lib/linear/commands/issue/pr.rb
|
245
264
|
- lib/linear/commands/issue/take.rb
|
246
265
|
- lib/linear/commands/issue/update.rb
|
247
266
|
- lib/linear/commands/team.rb
|
@@ -250,8 +269,12 @@ files:
|
|
250
269
|
- lib/linear/exceptions.rb
|
251
270
|
- lib/linear/fragments.rb
|
252
271
|
- lib/linear/models/base_model.rb
|
272
|
+
- lib/linear/models/base_model/class_methods.rb
|
273
|
+
- lib/linear/models/base_model/method_magic.rb
|
253
274
|
- lib/linear/models/issue.rb
|
275
|
+
- lib/linear/models/issue/class_methods.rb
|
254
276
|
- lib/linear/models/label.rb
|
277
|
+
- lib/linear/models/project.rb
|
255
278
|
- lib/linear/models/team.rb
|
256
279
|
- lib/linear/models/user.rb
|
257
280
|
- lib/linear/models/workflow_state.rb
|
data/exe/lclose
DELETED
data/exe/lcls
DELETED
data/exe/lcls.sh
DELETED
data/exe/lcreate
DELETED
File without changes
|
File without changes
|