linear-cli 0.5.3 → 0.6.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: b9dbcbc2f5187f96fc259c3255587676d654919430f20a62e734ed9e5b43dccd
4
- data.tar.gz: 0ed365c14b74cb25b818037aff0f84abb03316bba52d7eb6b2705a06fc1d9b54
3
+ metadata.gz: bc273e12a3dd9e864894c2484bd08a203531da62873505b33d5706f13349e2c6
4
+ data.tar.gz: ffb38d1c66023c229bc98812fa55e4a58e29342adb46e96f63cf0054560a3964
5
5
  SHA512:
6
- metadata.gz: 677845b48a38aa6b7c03323db68f69de36645516f84f9085f5cd3b5a30ac8e99cfb45d4e14122a5b48a308ca8470ffa33db3033db7cf7e6e5e17d44d50801226
7
- data.tar.gz: c4f131d5548f80c8ab49cb0f85136bd38b04e13303dd66446488101c1a355b0b9939fa1c6e11fc23a37d7252a7039fe70e4ffe9150ce09c26ebc70b2a0d2326c
6
+ metadata.gz: 2323c788c7095f385320006a7be3b167b7dc9fc731c96a13ea5af48dcdec0dc013f8e6f55c71e9631022ae744a5faecbc34c8bda668c172cfb98d935c1af40a0
7
+ data.tar.gz: c8422224df18d500f92d1d8e0d90cd27f41cc8d0c148943b6f53f6e6269d67aae676f2fd006e9a4210199e5aae572e39e9b3bf46ddce2206f2880d88c3a78fac
data/CHANGELOG.md CHANGED
@@ -2,8 +2,27 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.6.0] - 2024-02-04
6
+
7
+ ## [0.5.5] - 2024-02-04
8
+ ### Added
9
+ - Added lclose alias and 'issue update' subcommand (@bougyman)
10
+
11
+ ## [0.5.4] - 2024-02-04
12
+
13
+ ## [0.5.3] - 2024-02-03
14
+ ### Added
15
+ - Added support for multiline descriptions without failing (@bougyman)
16
+
17
+ ### Changed
18
+ - Changed default branch to use upstream default branch name (@bougyman)
19
+
5
20
  ## [0.5.2] - 2024-02-03
6
21
  ### Added
7
22
  - Added new changelog management system (changelog-rb) (@bougyman)
8
23
 
9
- [Unreleased]: https://github.com/rubyists/linear-cli/compare/v0.5.2...HEAD
24
+ [Unreleased]: https://github.com/rubyists/linear-cli/compare/0.6.0...HEAD
25
+ [0.6.0]: https://github.com/rubyists/linear-cli/compare/v0.5.5...0.6.0
26
+ [0.5.5]: https://github.com/rubyists/linear-cli/compare/v0.5.4...v0.5.5
27
+ [0.5.4]: https://github.com/rubyists/linear-cli/compare/v0.5.3...v0.5.4
28
+ [0.5.3]: https://github.com/rubyists/linear-cli/compare/v0.5.2...v0.5.3
data/Readme.adoc CHANGED
@@ -82,6 +82,7 @@ $ lc w --teams
82
82
  ----
83
83
  $ lcls
84
84
  $ lcls --full
85
+ $ lcls -f CRY-1
85
86
  ----
86
87
 
87
88
  ==== Assign one or more issues to yourself (take em!)
@@ -100,7 +101,41 @@ $ lc issue take CRY-456 CRY-789
100
101
 
101
102
  [source,sh]
102
103
  ----
103
- $ lc i c --title "My new issue" --description "This is a new issue"
104
+ $ lc i c --title "My new issue" --description "This is a new issue" --labels Bug,Feature --team CRY
105
+ $ lc i c -t "My new issue" -T CRY -l Improvment,Feature
106
+ ----
107
+
108
+ NOTE: If you don't provide a title, team, labels or description, you will be prompted to enter them.
109
+
110
+ ==== Develop an issue
111
+
112
+ This will switch to the branch for the issue, creating the branch if it doesn't exist.
113
+
114
+ 'dev' is a shortcut for the 'develop' subcommand of the issue command
115
+
116
+ [source,sh]
117
+ ----
118
+ $ lc i dev CRY-1234
119
+ ----
120
+
121
+ TIP: You may pass the --dev option to the create subcommand to immediately develop the creted issue.
122
+
123
+ ==== Update an issue
124
+
125
+ All of the update options can work on multiple issues, so long as it's not more than 50
126
+ at a time. You can also use the 'u' alias for 'update', and as always, the 'i' alias for 'issue'.
127
+
128
+ ===== Add a comment to one or more issues
129
+
130
+ [source,sh]
131
+ ----
132
+ $ lc issue update --comment "Here is a comment" CRY-1234
133
+ ----
134
+
135
+ ===== Close one or many issues
136
+
137
+ [source,sh]
138
+ ----
139
+ $ lc i u --close --reason "These were closable" CRY-1234 CRY-2
104
140
  ----
105
141
 
106
- NOTE: If you don't provide a title or description, you will be prompted to enter them.
@@ -0,0 +1,4 @@
1
+ type: Added
2
+ title: >
3
+ Added support for multiline descriptions without failing
4
+ author: bougyman
@@ -0,0 +1 @@
1
+ date: 2024-02-04
@@ -0,0 +1,4 @@
1
+ type: Added
2
+ title: >
3
+ Added lclose alias and 'issue update' subcommand
4
+ author: bougyman
@@ -0,0 +1 @@
1
+ date: 2024-02-04
@@ -0,0 +1 @@
1
+ date: 2024-02-04
data/exe/lclose ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ exec File.join(__dir__, 'lclose.sh'), *ARGV
data/exe/lclose.sh ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ if [[ "$*" =~ "--help" ]]
3
+ then
4
+ printf "This wrapper adds the --close option to the 'issue update' command.\n" >&2
5
+ printf "It is used to close one or many issues. The issues are specified by their ID/slugs.\n" >&2
6
+ printf "For closing multiple issues, you really want to pass --reason so you do not get prompted for each issue.\n\n" >&2
7
+ exec lc issue update --help
8
+ fi
9
+ exec lc issue update --close "$@"
data/lib/linear/api.rb CHANGED
@@ -41,7 +41,13 @@ module Rubyists
41
41
  end
42
42
 
43
43
  def query(query)
44
- call format('{ "query": "%s" }', query.to_s.gsub("\n", '').gsub('"', '\"'))
44
+ call format('{ "query": %s }', query.to_s.to_json)
45
+ rescue StandardError => e
46
+ logger.error('Error in query', query:, error: e)
47
+ raise e unless Rubyists::Linear.verbosity > 2
48
+
49
+ require 'pry'
50
+ binding.pry # rubocop:disable Lint/Debugger
45
51
  end
46
52
 
47
53
  def api_key
@@ -51,6 +57,7 @@ module Rubyists
51
57
  @api_key = ENV.fetch('LINEAR_API_KEY')
52
58
  end
53
59
  end
60
+ # Acts as a singleton for a GraphApi instance
54
61
  Api = Rubyists::Linear::GraphApi.new
55
62
  end
56
63
  end
@@ -47,10 +47,24 @@ module Rubyists
47
47
  ask_for_team
48
48
  end
49
49
 
50
+ def reason_for(reason = nil, four: nil)
51
+ return reason if reason
52
+
53
+ question = four ? "Reason for #{four}:" : 'Reason:'
54
+ prompt.ask(question)
55
+ end
56
+
57
+ def completed_state_for(thingy)
58
+ states = thingy.completed_states
59
+ return states.first if states.size == 1
60
+
61
+ prompt.select('Choose a completed state', states.to_h { |s| [s.name, s.id] })
62
+ end
63
+
50
64
  def description_for(description = nil)
51
65
  return description if description
52
66
 
53
- prompt.multiline('Description:').join(' ')
67
+ prompt.multiline('Description:').map(&:chomp).join('\\n')
54
68
  end
55
69
 
56
70
  def title_for(title = nil)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rubyists
4
4
  module Linear
5
- VERSION = '0.5.3'
5
+ VERSION = '0.6.0'
6
6
  end
7
7
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'semantic_logger'
4
+ require 'git'
5
+ require_relative '../issue'
6
+
7
+ module Rubyists
8
+ # Namespace for Linear
9
+ module Linear
10
+ M :issue, :user, :label
11
+ # Namespace for CLI
12
+ module CLI
13
+ module Issue
14
+ Update = Class.new Dry::CLI::Command
15
+ # The Update class is a Dry::CLI::Command to update an issue
16
+ class Update
17
+ include SemanticLogger::Loggable
18
+ include Rubyists::Linear::CLI::CommonOptions
19
+ include Rubyists::Linear::CLI::Issue # for #gimme_da_issue! and other Issue methods
20
+ desc 'Update an issue'
21
+ argument :issue_ids, type: :array, required: true, desc: 'Issue IDs (i.e. ISS-1)'
22
+ option :comment, type: :string, aliases: ['--message'], desc: 'Comment to add to the issue'
23
+ option :pr, type: :boolean, aliases: ['--pull-request'], default: false, desc: 'Create a pull request'
24
+ option :close, type: :boolean, default: false, desc: 'Close the issue'
25
+ option :reason, type: :string, aliases: ['--close-reason'], desc: 'Reason for closing the issue'
26
+
27
+ def call(issue_ids:, **options)
28
+ logger.debug('Updating issues', issue_ids:, options:)
29
+ Rubyists::Linear::Issue.find_all(issue_ids).each do |issue|
30
+ update_issue(issue, **options)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -12,13 +12,40 @@ module Rubyists
12
12
  include CLI::SubCommands
13
13
  # Aliases for Issue commands
14
14
  ALIASES = {
15
- create: %w[c new add], # aliases for the create command
16
- develop: %w[d dev], # aliases for the create command
17
- list: %w[l ls], # aliases for the list command
18
- show: %w[s view v], # aliases for the show command
19
- issue: %w[i issues] # aliases for the main issue command itself
15
+ create: %w[c new add], # aliases for the create command
16
+ develop: %w[d dev], # aliases for the develop command
17
+ list: %w[l ls], # aliases for the list command
18
+ update: %w[u], # aliases for the close command
19
+ issue: %w[i issues] # aliases for the main issue command itself
20
20
  }.freeze
21
21
 
22
+ def issue_comment(issue, comment)
23
+ issue.add_comment(comment)
24
+ prompt.ok("Comment added to #{issue.identifier}")
25
+ end
26
+
27
+ def close_issue(issue, **options)
28
+ reason = reason_for(options[:reason], four: "closing #{issue.identifier} - #{issue.title}")
29
+ issue_comment(issue, reason)
30
+ close_state = completed_state_for(issue)
31
+ issue.close!(state: close_state, trash: options[:trash])
32
+ prompt.ok("#{issue.identifier} was closed")
33
+ end
34
+
35
+ def issue_pr(issue)
36
+ issue.create_pr!
37
+ prompt.ok("Pull request created for #{issue.identifier}")
38
+ end
39
+
40
+ def update_issue(issue, **options)
41
+ issue_comment(issue, options[:comment]) if options[:comment]
42
+ return close_issue(issue, **options) if options[:close]
43
+ return issue_pr(issue) if options[:pr]
44
+
45
+ prompt.warn('No action taken, no options specified')
46
+ prompt.ok('Issue was not updated')
47
+ end
48
+
22
49
  def make_da_issue!(**options)
23
50
  # These *_for methods are defined in Rubyists::Linear::CLI::SubCommands
24
51
  title = title_for options[:title]
@@ -28,7 +55,7 @@ module Rubyists
28
55
  Rubyists::Linear::Issue.create(title:, description:, team:, labels:)
29
56
  end
30
57
 
31
- def gimme_da_issue!(issue_id, me) # rubocop:disable Naming/MethodParameterName
58
+ def gimme_da_issue!(issue_id, me: Rubyists::Linear::User.me) # rubocop:disable Naming/MethodParameterName
32
59
  logger.trace('Looking up issue', issue_id:, me:)
33
60
  issue = Rubyists::Linear::Issue.find(issue_id)
34
61
  if issue.assignee && issue.assignee[:id] == me.id
@@ -5,7 +5,9 @@ require 'semantic_logger'
5
5
  require 'sequel/extensions/inflector'
6
6
 
7
7
  module Rubyists
8
+ # Namespace for Linear
8
9
  module Linear
10
+ L :api, :fragments
9
11
  # Module which provides a base model for Linear models.
10
12
  class BaseModel
11
13
  extend GQLi::DSL
@@ -32,6 +34,20 @@ module Rubyists
32
34
 
33
35
  # Class methods for Linear models.
34
36
  class << self
37
+ def has_one(relation, klass) # rubocop:disable Naming/PredicateName
38
+ define_method relation do
39
+ return instance_variable_get("@#{relation}") if instance_variable_defined?("@#{relation}")
40
+
41
+ instance_variable_set("@#{relation}", Rubyists::Linear.const_get(klass).new(data[relation]))
42
+ end
43
+
44
+ define_method "#{relation}=" do |val|
45
+ hash = val.is_a?(Hash) ? val : val.data
46
+ updated_data[relation] = hash
47
+ instance_variable_set("@#{relation}", Rubyists::Linear.const_get(klass).new(hash))
48
+ end
49
+ end
50
+
35
51
  def const_added(const)
36
52
  return unless const == :Base
37
53
 
@@ -108,6 +124,10 @@ module Rubyists
108
124
  data != updated_data
109
125
  end
110
126
 
127
+ def completed_states
128
+ workflow_states.select { |ws| ws.type == 'completed' }
129
+ end
130
+
111
131
  def to_h
112
132
  updated_data
113
133
  end
@@ -5,14 +5,13 @@ require 'gqli'
5
5
  module Rubyists
6
6
  # Namespace for Linear
7
7
  module Linear
8
- L :api
9
- L :fragments
10
- M :base_model
11
- M :user
8
+ M :base_model, :user
12
9
  Issue = Class.new(BaseModel)
13
10
  # The Issue class represents a Linear issue.
14
- class Issue
11
+ class Issue # rubocop:disable Metrics/ClassLength
15
12
  include SemanticLogger::Loggable
13
+ has_one :assignee, :User
14
+ has_one :team, :Team
16
15
 
17
16
  BASIC_FILTER = { completedAt: { null: true } }.freeze
18
17
 
@@ -20,7 +19,6 @@ module Rubyists
20
19
  id
21
20
  identifier
22
21
  title
23
- assignee { ___ User::Base }
24
22
  branchName
25
23
  description
26
24
  createdAt
@@ -28,33 +26,88 @@ module Rubyists
28
26
  end
29
27
 
30
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
+
31
37
  def find(slug)
32
- q = query { issue(id: slug) { ___ Base } }
38
+ q = query { issue(id: slug) { ___ Issue.base_fragment } }
33
39
  data = Api.query(q)
34
40
  raise NotFoundError, "Issue not found: #{slug}" if data.nil?
35
41
 
36
42
  new(data[:issue])
37
43
  end
38
44
 
45
+ def find_all(*slugs)
46
+ slugs.flatten.map { |slug| find(slug) }
47
+ end
48
+
39
49
  def create(title:, description:, team:, labels: [])
40
50
  team_id = team.id
41
51
  label_ids = labels.map(&:id)
42
52
  input = { title:, description:, teamId: team_id }
43
- input.merge!(labelIds: label_ids) unless label_ids.empty?
44
- m = mutation { issueCreate(input:) { issue { ___ Base } } }
45
- data = Api.query(m)
46
- new(data[:issueCreate][:issue])
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)
47
57
  end
48
58
  end
49
59
 
50
- def assign!(user)
60
+ def comment_fragment
61
+ @comment_fragment ||= fragment('Comment', 'Comment') do
62
+ id
63
+ body
64
+ url
65
+ end
66
+ end
67
+
68
+ # Reference for this mutation:
69
+ # https://studio.apollographql.com/public/Linear-API/variant/current/schema/reference/inputs/CommentCreateInput
70
+ def add_comment(comment)
71
+ id_for_this = identifier
72
+ comment_frag = comment_fragment
73
+ m = mutation { commentCreate(input: { issueId: id_for_this, body: comment }) { comment { ___ comment_frag } } }
74
+
75
+ query_data = Api.query(m)
76
+ query_data.dig(:commentCreate, :comment)
77
+ self
78
+ end
79
+
80
+ def close_mutation(close_state, trash: false)
51
81
  id_for_this = identifier
52
- m = mutation { issueUpdate(id: id_for_this, input: { assigneeId: user.id }) { issue { ___ Base } } }
53
- data = Api.query(m)
54
- updated = data.dig(:issueUpdate, :issue)
82
+ input = { stateId: close_state.id }
83
+ input[:trash] = true if trash
84
+ mutation { issueUpdate(id: id_for_this, input:) { issue { ___ Issue.base_fragment } } }
85
+ end
86
+
87
+ def close!(state: nil, trash: false)
88
+ logger.warn "Using first completed state found: #{completed_states.first}" if state.nil?
89
+ state ||= completed_states.first
90
+ query_data = Api.query close_mutation(state, trash:)
91
+ updated = query_data.dig(:issueUpdate, :issue)
92
+ raise SmellsBad, "Unknown response for issue close: #{data} (should have :issueUpdate key)" if updated.nil?
93
+
94
+ @data = @updated_data = updated
95
+ self
96
+ end
97
+
98
+ def assign!(user)
99
+ this_id = identifier
100
+ m = mutation { issueUpdate(id: this_id, input: { assigneeId: user.id }) { issue { ___ Issue.base_fragment } } }
101
+ query_data = Api.query(m)
102
+ updated = query_data.dig(:issueUpdate, :issue)
55
103
  raise SmellsBad, "Unknown response for issue update: #{data} (should have :issueUpdate key)" if updated.nil?
56
104
 
57
- Issue.new updated
105
+ @data = @updated_data = updated
106
+ self
107
+ end
108
+
109
+ def workflow_states
110
+ @workflow_states ||= team.workflow_states
58
111
  end
59
112
 
60
113
  def inspection
@@ -62,18 +115,26 @@ module Rubyists
62
115
  end
63
116
 
64
117
  def to_s
65
- basic = format('%<id>-12s %<title>s', id: data[:identifier], title: data[:title])
118
+ basic = format('%<id>-12s %<title>s', id: identifier, title:)
66
119
  return basic unless (name = data.dig(:assignee, :name))
67
120
 
68
121
  format('%<basic>s (%<name>s)', basic:, name:)
69
122
  end
70
123
 
124
+ def parsed_description
125
+ return TTY::Markdown.parse(description) if description && !description.empty?
126
+
127
+ TTY::Markdown.parse(['# No Description For this issue??',
128
+ 'Issues really need description',
129
+ "## What's up with that?"].join("\n"))
130
+ rescue StandardError => e
131
+ logger.error 'Error parsing description', e
132
+ "Description was unparsable: #{description}\n"
133
+ end
134
+
71
135
  def full
72
136
  sep = '-' * to_s.length
73
- format("%<to_s>s\n%<sep>s\n%<description>s\n",
74
- sep:,
75
- to_s:,
76
- description: (TTY::Markdown.parse(data[:description]) rescue 'No Description?')) # rubocop:disable Style/RescueModifier
137
+ format("%<to_s>s\n%<sep>s\n%<description>s\n", sep:, to_s:, description: parsed_description)
77
138
  end
78
139
 
79
140
  def display(options)
@@ -31,14 +31,14 @@ module Rubyists
31
31
  fragment('LabelWithTeams', 'IssueLabel') do
32
32
  ___ Base
33
33
  parent { ___ Base }
34
- team { ___ Team::Base }
34
+ team { ___ Team.base_fragment }
35
35
  end
36
36
  end
37
37
 
38
38
  def self.find_all_by_name(names)
39
39
  q = query do
40
40
  issueLabels(filter: { name: { in: names } }) do
41
- edges { node { ___ Base } }
41
+ edges { node { ___ base_fragment } }
42
42
  end
43
43
  end
44
44
  data = Api.query(q)
@@ -5,8 +5,7 @@ require 'gqli'
5
5
  module Rubyists
6
6
  # Namespace for Linear
7
7
  module Linear
8
- L :api, :fragments
9
- M :base_model, :issue, :user
8
+ M :base_model, :issue, :user, :workflow_state
10
9
  Team = Class.new(BaseModel)
11
10
  # The Issue class represents a Linear issue.
12
11
  class Team
@@ -96,6 +95,26 @@ module Rubyists
96
95
  def display(_options)
97
96
  printf "%s\n", full
98
97
  end
98
+
99
+ def workflow_states_query
100
+ team_id = id
101
+ query do
102
+ team(id: team_id) do
103
+ states do
104
+ nodes { ___ WorkflowState.base_fragment }
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ def workflow_states
111
+ return @workflow_states if @workflow_states
112
+
113
+ data = Api.query(workflow_states_query)
114
+ @workflow_states = data.dig(:team, :states, :nodes)&.map do |state|
115
+ WorkflowState.new state
116
+ end
117
+ end
99
118
  end
100
119
  end
101
120
  end
@@ -0,0 +1,33 @@
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
+ WorkflowState = Class.new(BaseModel)
10
+ # The WorkflowState class represents a Linear workflow state.
11
+ class WorkflowState
12
+ include SemanticLogger::Loggable
13
+
14
+ Base = fragment('BaseWorkflowState', 'WorkflowState') do
15
+ id
16
+ name
17
+ position
18
+ type
19
+ description
20
+ createdAt
21
+ updatedAt
22
+ end
23
+
24
+ def to_s
25
+ format('%<name>-12s %<type>s', name:, type:)
26
+ end
27
+
28
+ def inspection
29
+ format('name: "%<name>s" type: "%<type>s"', name:, type:)
30
+ end
31
+ end
32
+ end
33
+ end
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.5.3
4
+ version: 0.6.0
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-03 00:00:00.000000000 Z
11
+ date: 2024-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -183,6 +183,8 @@ email:
183
183
  - tj@rubyists.com
184
184
  executables:
185
185
  - lc
186
+ - lclose
187
+ - lclose.sh
186
188
  - lcls
187
189
  - lcls.sh
188
190
  extensions: []
@@ -194,10 +196,17 @@ files:
194
196
  - Readme.adoc
195
197
  - changelog/0.5.2/added_new_changelog_management_system_changelog_rb.yml
196
198
  - changelog/0.5.2/tag.yml
199
+ - changelog/0.5.3/added_support_for_multiline_descriptions_without_failing.yml
197
200
  - changelog/0.5.3/changed_default_branch_to_use_upstream_default_branch_name.yml
198
201
  - changelog/0.5.3/tag.yml
202
+ - changelog/0.5.4/tag.yml
203
+ - changelog/0.5.5/added_lclose_alias_and_issue_update_subcommand.yml
204
+ - changelog/0.5.5/tag.yml
205
+ - changelog/0.6.0/tag.yml
199
206
  - changelog/unreleased/.gitkeep
200
207
  - exe/lc
208
+ - exe/lclose
209
+ - exe/lclose.sh
201
210
  - exe/lcls
202
211
  - exe/lcls.sh
203
212
  - lib/linear.rb
@@ -213,6 +222,7 @@ files:
213
222
  - lib/linear/commands/issue/develop.rb
214
223
  - lib/linear/commands/issue/list.rb
215
224
  - lib/linear/commands/issue/take.rb
225
+ - lib/linear/commands/issue/update.rb
216
226
  - lib/linear/commands/team.rb
217
227
  - lib/linear/commands/team/list.rb
218
228
  - lib/linear/commands/whoami.rb
@@ -223,6 +233,7 @@ files:
223
233
  - lib/linear/models/label.rb
224
234
  - lib/linear/models/team.rb
225
235
  - lib/linear/models/user.rb
236
+ - lib/linear/models/workflow_state.rb
226
237
  - lib/linear/version.rb
227
238
  - linear-cli.gemspec
228
239
  - sig/linear/cli.rbs