linear-cli 0.9.19 → 2.0.2

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: f8b5d0243a88d0bf959a14f147c7966fa661839059d2b4c17d4905c9ea7d9b8d
4
- data.tar.gz: 3162551cd445f432cc01e42643c5d428ed86e3e4fad93cab4fc829519a1b0c96
3
+ metadata.gz: 67f8561868c8ddb5435df18b48ebae374b05d8f568d8e3157694d698e66f9708
4
+ data.tar.gz: 0c30dcf56e08baec2527d3fe8e4e2c36adeca1b927291e0cba000a74d817e50e
5
5
  SHA512:
6
- metadata.gz: 3f98055e6ecbb47cb3725609f01491648d43854bcb010b09eb7ec5c92a227e37c31cd6ef74a192ea08d726e3350b9401d038ea9ac383458555f82ec807727860
7
- data.tar.gz: 3c5bc6ed193aaa0995625185f3dfb3c98f0eb5f83c960077b145bd5921382170623ae5c62c08bc361d6d5089e7e52366cadfab2af9755e7f6329726d31c8193b
6
+ metadata.gz: 9d92a9bbd9fb3fe7e9ef9dc80c2bffac7f5757415095ec644db0e5d4de640ec6d7f7b6fbde63467d29761129cbe00064aecab0653e03d3f64e2df4242882d312
7
+ data.tar.gz: 9ac7db53b71073d6ffcc9f3c356c34ea82165f1af2556d6f8ba2a87f76c0dd39214b6441930a0d403c19bc437932e9faf7afcaaea3177130930e40b31bee165e
@@ -0,0 +1,32 @@
1
+ {
2
+ "packages": {
3
+ ".": {
4
+ "changelog-path": "CHANGELOG.md",
5
+ "release-type": "simple",
6
+ "bump-minor-pre-major": true,
7
+ "bump-patch-for-minor-pre-major": true,
8
+ "draft": false,
9
+ "prerelease": false,
10
+ "version-file": ".version.txt",
11
+ "extra-files": [
12
+ {
13
+ "type": "generic",
14
+ "path": "lib/linear/cli/version.rb"
15
+ },
16
+ {
17
+ "type": "generic",
18
+ "path": "oci/Gemfile"
19
+ }
20
+ ],
21
+ "exclude-paths": [
22
+ ".release-please-manifest.json",
23
+ ".version.txt",
24
+ "lib/linear/version.rb",
25
+ ".rubocop.yml",
26
+ ".overcommit.yml",
27
+ "coverage/coverage.json"
28
+ ]
29
+ }
30
+ },
31
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
32
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "2.0.2"
3
+ }
data/.version.txt ADDED
@@ -0,0 +1 @@
1
+ 2.0.2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.2](https://github.com/rubyists/linear-cli/compare/v2.0.1...v2.0.2) (2025-11-03)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * Corrects publish workflow yaml syntax error ([#16](https://github.com/rubyists/linear-cli/issues/16)) ([4a50f27](https://github.com/rubyists/linear-cli/commit/4a50f27ed08abc690b7a27b4712cd5088cf57e70))
9
+ * Corrects publisher for gem ([#13](https://github.com/rubyists/linear-cli/issues/13)) ([61bf747](https://github.com/rubyists/linear-cli/commit/61bf74747cea8d2572ef9f553c5e56f4cc7788a8))
10
+ * Fix gem publisher ([#15](https://github.com/rubyists/linear-cli/issues/15)) ([d370dd6](https://github.com/rubyists/linear-cli/commit/d370dd684832056748e28b4a34e69ef7ba64b3bb))
11
+
12
+ ## [2.0.1](https://github.com/rubyists/linear-cli/compare/v2.0.0...v2.0.1) (2025-11-03)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * Remove unused ci/cd stuff ([#11](https://github.com/rubyists/linear-cli/issues/11)) ([8f070ba](https://github.com/rubyists/linear-cli/commit/8f070ba556873b97ee1d6d2723f82ab1227430b7))
18
+
19
+ ## [2.0.0](https://github.com/rubyists/linear-cli/compare/v1.0.0...v2.0.0) (2025-11-03)
20
+
21
+
22
+ ### ⚠ BREAKING CHANGES
23
+
24
+ * **sqlite:** Updates dependencies, including painful sqlite ([#8](https://github.com/rubyists/linear-cli/issues/8))
25
+
26
+ ### Features
27
+
28
+ * **release:** Adds release-please for release management ([#9](https://github.com/rubyists/linear-cli/issues/9)) ([a3ebfeb](https://github.com/rubyists/linear-cli/commit/a3ebfebe1ffb3519222dec440dfed757190c7a95))
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * **issue update:** CRY-28 - Implement the pr command ([#1](https://github.com/rubyists/linear-cli/issues/1)) ([832781a](https://github.com/rubyists/linear-cli/commit/832781a9375c0be7823c0c10695390c2f45d5c95))
34
+ * **sqlite:** Updates dependencies, including painful sqlite ([#8](https://github.com/rubyists/linear-cli/issues/8)) ([be93723](https://github.com/rubyists/linear-cli/commit/be937232f7e05681fa84fc3017a33de0d3f16702))
35
+
3
36
  ## [Unreleased]
4
37
 
5
38
  ## [0.9.11] - 2024-02-20
data/Readme.adoc CHANGED
@@ -7,6 +7,7 @@
7
7
  :note-caption: 📝
8
8
  :experimental:
9
9
  :plc-url: https://raw.githubusercontent.com/rubyists/linear-cli/main/oci/plc
10
+ :conventional-commits: https://www.conventionalcommits.org/en/v1.0.0/[Conventional Commits]
10
11
 
11
12
  A command line interface to https://linear.app.
12
13
 
@@ -14,7 +15,7 @@ A command line interface to https://linear.app.
14
15
 
15
16
  === I don't want to install
16
17
 
17
- You can use the OCI container image to run the CLI without installing it.
18
+ If you do not want to install this, you can use the OCI container image to run the CLI without installing it.
18
19
 
19
20
  [source,sh]
20
21
  ----
@@ -38,7 +39,7 @@ Then you can just run 'lc' to use the CLI.
38
39
 
39
40
  === Gem install (Most should use this)
40
41
 
41
- Requires ruby 3.2 or later
42
+ Requires ruby 3.4 or later
42
43
 
43
44
  [source,sh]
44
45
  ----
@@ -207,3 +208,37 @@ $ lcls
207
208
  $ lcreate --description "This is a new issue" --labels Bug,Feature --team CRY
208
209
  $ lclose --reason "This issue sucks" CRY-1234 CRY-456
209
210
  ----
211
+
212
+ == Development
213
+
214
+ The project uses Minitest and RuboCop. Run tests with Rake:
215
+
216
+ [source,bash]
217
+ ----
218
+ $ bundle exec rake
219
+ ----
220
+
221
+ === Build the gem
222
+
223
+ [source,bash]
224
+ ----
225
+ $ bundle exec gem build
226
+ ----
227
+
228
+ === Build the container
229
+
230
+ [source,bash]
231
+ ----
232
+ $ ./ci/build_image.sh <tag_name>
233
+ ----
234
+
235
+ === Conventional Commits (semantic commit messages)
236
+
237
+ This project follows the {conventional-commits} specification.
238
+
239
+ To contribute, please follow that commit message format,
240
+ or your pull request may be rejected.
241
+
242
+ == License
243
+
244
+ MIT
data/lib/linear/api.rb CHANGED
@@ -8,6 +8,7 @@ module Rubyists
8
8
  # Responsible for making requests to the Linear API
9
9
  class GraphApi
10
10
  include SemanticLogger::Loggable
11
+
11
12
  BASE_URI = 'https://api.linear.app/graphql'
12
13
  RETRY_AFTER = lambda do |*|
13
14
  @retries ||= 0
@@ -6,6 +6,7 @@ module Rubyists
6
6
  # This module is prepended to all commands to log their calls
7
7
  module Caller
8
8
  include SemanticLogger::Loggable
9
+
9
10
  def self.prepended(mod) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
10
11
  # Global options for all commands
11
12
  mod.instance_eval do
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubyists
4
+ module Linear
5
+ module CLI
6
+ # The Project module contains support for finding and selecting projects
7
+ # as part of a filter or query
8
+ module Projects
9
+ def ask_for_projects(projects, search: true)
10
+ prompt.warn("No project found matching #{search}.") if search
11
+ return projects.first if projects.size == 1
12
+
13
+ prompt.select('Project:', projects.to_h { |p| [p.name, p] })
14
+ end
15
+
16
+ def project_scores(projects, search_term)
17
+ projects.select { |p| p.match_score?(search_term).positive? }.sort_by { |p| p.match_score?(search_term) }
18
+ end
19
+
20
+ def project_for(project = nil, projects: Project.all)
21
+ return nil if projects.empty?
22
+
23
+ possibles = project ? project_scores(projects, project) : []
24
+ return ask_for_projects(projects, search: project) if possibles.empty?
25
+
26
+ first = possibles.first
27
+ return first if first.match_score?(project) == 100
28
+
29
+ selections = possibles + (projects - possibles)
30
+ prompt.select('Project:', selections.to_h { |p| [p.name, p] }) if possibles.size.positive?
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Rubyists
4
4
  module Linear
5
- VERSION = '0.9.19'
5
+ # x-release-please-start-version
6
+ VERSION = '2.0.2'
7
+ # x-release-please-end
6
8
  end
7
9
  end
@@ -4,7 +4,9 @@ module Rubyists
4
4
  module Linear
5
5
  module CLI
6
6
  # Module for the _for methods
7
- module WhatFor # rubocop:disable Metrics/ModuleLength
7
+ module WhatFor
8
+ include CLI::Projects # for methods called within #project_for
9
+
8
10
  # TODO: Make this configurable
9
11
  PR_TYPES = {
10
12
  fix: 'Bug fixes',
@@ -87,31 +89,6 @@ module Rubyists
87
89
  prompt.ask('Title:')
88
90
  end
89
91
 
90
- def ask_for_projects(projects, search: true)
91
- prompt.warn("No project found matching #{search}.") if search
92
- return projects.first if projects.size == 1
93
-
94
- prompt.select('Project:', projects.to_h { |p| [p.name, p] })
95
- end
96
-
97
- def project_scores(projects, search_term)
98
- projects.select { |p| p.match_score?(search_term).positive? }.sort_by { |p| p.match_score?(search_term) }
99
- end
100
-
101
- def project_for(team, project = nil) # rubocop:disable Metrics/AbcSize
102
- projects = team.projects
103
- return nil if projects.empty?
104
-
105
- possibles = project ? project_scores(projects, project) : []
106
- return ask_for_projects(projects, search: project) if possibles.empty?
107
-
108
- first = possibles.first
109
- return first if first.match_score?(project) == 100
110
-
111
- selections = possibles + (projects - possibles)
112
- prompt.select('Project:', selections.to_h { |p| [p.name, p] }) if possibles.size.positive?
113
- end
114
-
115
92
  def pr_title_for(issue)
116
93
  proposed = [pr_type_for(issue)]
117
94
  proposed_scope = pr_scope_for(issue.title)
@@ -143,7 +120,7 @@ module Rubyists
143
120
  end
144
121
 
145
122
  def pr_scope_for(title)
146
- proposed_scope = title.match(/^\w+\(([^\)]+)\)/)
123
+ proposed_scope = title.match(/^\w+\(([^)]+)\)/)
147
124
  return proposed_scope[1].downcase if proposed_scope
148
125
 
149
126
  scope = prompt.ask('What is the scope of this PR?', default: 'none')
@@ -16,6 +16,7 @@ module Rubyists
16
16
  include SemanticLogger::Loggable
17
17
  include Rubyists::Linear::CLI::CommonOptions
18
18
  include Rubyists::Linear::CLI::Issue # for #gimme_da_issue! and other Issue methods
19
+
19
20
  desc 'Create a new issue. If you do not pass any options, you will be prompted for the required information.'
20
21
  option :description, type: :string, aliases: ['-d'], desc: 'Issue Description'
21
22
  option :labels, type: :array, aliases: ['-l'], desc: 'Labels for the issue (Comma separated list)'
@@ -17,6 +17,7 @@ module Rubyists
17
17
  include SemanticLogger::Loggable
18
18
  include Rubyists::Linear::CLI::CommonOptions
19
19
  include Rubyists::Linear::CLI::Issue # for #gimme_da_issue! and other Issue methods
20
+
20
21
  desc 'Start or update development status of an issue'
21
22
  argument :issue_id, required: true, desc: 'The Issue (i.e. ISS-1)'
22
23
 
@@ -15,20 +15,25 @@ module Rubyists
15
15
  class List
16
16
  include SemanticLogger::Loggable
17
17
  include Rubyists::Linear::CLI::CommonOptions
18
+ include CLI::SubCommands # for #prompt within CLI::Projects
19
+ include CLI::Projects # for methods called within #project_for
18
20
 
19
21
  desc 'List issues'
20
22
  example [
21
- ' # List your issues',
22
- '--no-mine # List The most recent 100 issues',
23
- '-u # List unassigned issues',
24
- '-fu # List unassigned issues with full details',
25
- 'CRY-123 # Show issue CRY-123'
23
+ ' # List your issues',
24
+ '--no-mine # List The most recent 100 issues',
25
+ '-u # List unassigned issues',
26
+ '-fu # List unassigned issues with full details',
27
+ '--project "Manhattan" # List only issues in project "Manhattan"',
28
+ 'CRY-123 # Show issue CRY-123'
26
29
  ]
27
30
  argument :ids, type: :array, default: [], desc: 'Issue IDs to list'
28
31
  option :mine, type: :boolean, default: true, desc: 'Only show my issues'
29
32
  option :unassigned, aliases: ['-u'], type: :boolean, default: false, desc: 'Show unassigned issues only'
30
33
  option :team, aliases: ['-t'], type: :string, desc: 'Show issues for only this team'
31
34
  option :full, type: :boolean, aliases: ['-f'], default: false, desc: 'Show full issue details'
35
+ option :project, type: :string, aliases: ['-p'],
36
+ desc: 'Show issues for only this project. Can be name, URL, ID, or - to select from a list'
32
37
 
33
38
  def call(ids:, **options)
34
39
  logger.debug 'Listing issues'
@@ -42,6 +47,13 @@ module Rubyists
42
47
  filter[:assignee] = { isMe: { eq: true } } if options[:mine]
43
48
  filter[:assignee] = { null: true } if options[:unassigned]
44
49
  filter[:team] = { key: { eq: options[:team] } } if options[:team]
50
+
51
+ if options[:project]
52
+ project = project_for(options[:project])
53
+ logger.debug('Found project', project:)
54
+ filter[:project] = { id: { eq: project.id } } if project
55
+ end
56
+
45
57
  filter
46
58
  end
47
59
 
@@ -17,6 +17,7 @@ module Rubyists
17
17
  include SemanticLogger::Loggable
18
18
  include Rubyists::Linear::CLI::CommonOptions
19
19
  include Rubyists::Linear::CLI::Issue # for #gimme_da_issue! and other Issue methods
20
+
20
21
  desc 'Create a PR for an issue and push it to the remote'
21
22
  argument :issue_id, required: true, desc: 'The Issue (i.e. CRY-1)'
22
23
  option :title, required: false, desc: 'The title of the PR'
@@ -16,11 +16,13 @@ module Rubyists
16
16
  include SemanticLogger::Loggable
17
17
  include Rubyists::Linear::CLI::CommonOptions
18
18
  include Rubyists::Linear::CLI::Issue # for #gimme_da_issue! and other Issue methods
19
+
19
20
  desc 'Assign one or more issues to yourself'
20
21
  argument :issue_ids, type: :array, required: true, desc: 'Issue Identifiers'
21
22
 
22
23
  def call(issue_ids:, **options)
23
24
  updates = issue_ids.map do |issue_id|
25
+ Rubyists::Linear::Issue.find(issue_id)
24
26
  gimme_da_issue! issue_id # gimme_da_issue! is defined in Rubyists::Linear::CLI::Issue
25
27
  rescue NotFoundError => e
26
28
  logger.warn e.message
@@ -17,6 +17,7 @@ module Rubyists
17
17
  include SemanticLogger::Loggable
18
18
  include Rubyists::Linear::CLI::CommonOptions
19
19
  include Rubyists::Linear::CLI::Issue # for #gimme_da_issue! and other Issue methods
20
+
20
21
  desc 'Update an issue'
21
22
  argument :issue_ids, type: :array, required: true, desc: 'Issue IDs (i.e. CRY-1)'
22
23
  option :comment, type: :string, aliases: ['-m'], desc: 'Comment to add to the issue. - open an editor'
@@ -65,7 +65,7 @@ module Rubyists
65
65
  end
66
66
 
67
67
  def attach_project(issue, project_search)
68
- project = project_for(issue.team, project_search)
68
+ project = project_for(project_search, projects: issue.team.projects)
69
69
  issue.attach_to_project project
70
70
  prompt.ok "#{issue.identifier} was attached to #{project.name}"
71
71
  end
@@ -88,7 +88,7 @@ module Rubyists
88
88
  description = description_for(options[:description])
89
89
  team = team_for(options[:team])
90
90
  labels = labels_for(team, options[:labels])
91
- project = project_for(team, options[:project])
91
+ project = project_for(options[:project], projects: team.projects)
92
92
  Rubyists::Linear::Issue.create(title:, description:, team:, labels:, project:)
93
93
  end
94
94
 
@@ -7,6 +7,7 @@ module Rubyists
7
7
  # The Team module is the namespace for all team-related commands
8
8
  module Team
9
9
  include CLI::SubCommands
10
+
10
11
  # Aliases for Team commands.
11
12
  ALIASES = {
12
13
  list: %w[ls l], # aliases for the list command
@@ -7,6 +7,7 @@ module Rubyists
7
7
  # Reusable fragments
8
8
  module Fragments
9
9
  extend GQLi::DSL
10
+
10
11
  PageInfo = fragment('PageInfo', 'PageInfo') do
11
12
  pageInfo do
12
13
  hasNextPage
@@ -55,7 +55,7 @@ module Rubyists
55
55
  sym = camel_name.to_sym
56
56
  ff = full_fragment
57
57
  query_data = Api.query(query { __node(camel_name, id: id_val) { ___ ff } })
58
- raise NotFoundError, "No #{just_name} found with id #{id_val}" if query_data[sym].nil?
58
+ raise NotFoundError, "No #{just_name} found with id #{id_val}" if query_data.nil? || query_data[sym].nil?
59
59
 
60
60
  new query_data[sym]
61
61
  end
@@ -15,6 +15,7 @@ module Rubyists
15
15
  include GQLi::DSL
16
16
  include SemanticLogger::Loggable
17
17
  extend ClassMethods
18
+
18
19
  attr_reader :data, :updated_data
19
20
 
20
21
  CANCELLED_STATES = %w[cancelled canceled].freeze
@@ -10,6 +10,7 @@ module Rubyists
10
10
  # The Comment class represents a Linear issue comment.
11
11
  class Comment
12
12
  include SemanticLogger::Loggable
13
+
13
14
  many_to_one :user
14
15
 
15
16
  Base = fragment('BaseComment', 'Comment') do
@@ -12,6 +12,7 @@ module Rubyists
12
12
  class Issue # rubocop:disable Metrics/ClassLength
13
13
  include SemanticLogger::Loggable
14
14
  extend ClassMethods
15
+
15
16
  many_to_one :assignee, :User
16
17
  many_to_one :team
17
18
  one_to_many :comments
@@ -26,7 +26,9 @@ module Rubyists
26
26
  File.basename(url).sub("-#{slugId}", '')
27
27
  end
28
28
 
29
- def match_score?(string)
29
+ def match_score?(string) # rubocop:disable Naming/PredicateMethod
30
+ return 100 if matches_attributes?(string, :id, :url)
31
+
30
32
  downed = string.downcase
31
33
  return 100 if downed.split.join('-') == slug || downed == name.downcase
32
34
  return 75 if name.include?(string) || slug.include?(downed)
@@ -35,6 +37,11 @@ module Rubyists
35
37
  0
36
38
  end
37
39
 
40
+ # Does :string _exactly_ match any of the attribute values in *attrs?
41
+ def matches_attributes?(string, *attrs)
42
+ Array(attrs).any? { |attr| string.casecmp?(data.fetch(attr.to_sym)) }
43
+ end
44
+
38
45
  def to_s
39
46
  format('%<name>-12s %<url>s', name:, url:)
40
47
  end
@@ -10,6 +10,7 @@ module Rubyists
10
10
  # The Issue class represents a Linear issue.
11
11
  class Team
12
12
  include SemanticLogger::Loggable
13
+
13
14
  one_to_many :projects
14
15
 
15
16
  # TODO: Make this configurable
@@ -39,7 +39,7 @@ module Rubyists
39
39
  end
40
40
 
41
41
  def initialize(data)
42
- super(data)
42
+ super
43
43
  self.teams = data[:teams] if data.key? :teams
44
44
  end
45
45
 
data/lib/linear.rb CHANGED
@@ -16,6 +16,7 @@ module Rubyists
16
16
  # Namespace for Linear classes
17
17
  module Linear
18
18
  include SemanticLogger::Loggable
19
+
19
20
  # rubocop:disable Layout/SpaceAroundOperators
20
21
  ROOT = (Pathname(__FILE__)/'../..').expand_path
21
22
  LIBROOT = ROOT/:lib/:linear
@@ -47,13 +48,12 @@ module Rubyists
47
48
  end
48
49
 
49
50
  def self.verbosity=(debug)
50
- return verbosity unless debug
51
+ return unless debug
51
52
 
52
53
  logger.warn 'Debug level should be between 0 and 3' unless debug.between?(0, 3)
53
54
  @verbosity = debug
54
55
  level = @verbosity > (DEBUG_LEVELS.size - 1) ? :trace : DEBUG_LEVELS[@verbosity]
55
56
  SemanticLogger.default_level = level
56
- @verbosity
57
57
  end
58
58
  end
59
59
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/linear/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'linear-cli'
7
+ spec.version = Rubyists::Linear::VERSION
8
+ spec.authors = ['Tj (bougyman) Vanderpoel']
9
+ spec.email = ['tj@rubyists.com']
10
+
11
+ spec.summary = 'CLI for interacting with Linear.app.'
12
+ spec.description = 'A CLI for interacting with Linear.app. Loosely based on the GitHub CLI'
13
+ spec.homepage = 'https://github.com/rubyists/linear-cli'
14
+ spec.required_ruby_version = '>= 3.4.0'
15
+
16
+ spec.license = 'MIT'
17
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (File.expand_path(f) == __FILE__) ||
28
+ f.start_with?(*%w[changelog/ pkg/ oci/ ci/ bin/ test/ spec/ features/ .git .github appveyor
29
+ .rspec .rubocop cucumber.yml Gemfile])
30
+ end
31
+ end
32
+ spec.bindir = 'exe'
33
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }.reject { |f| f.end_with?('.sh') }
34
+ spec.require_paths = ['lib']
35
+
36
+ # Uncomment to register a new dependency of your gem
37
+ spec.add_dependency 'base64'
38
+ spec.add_dependency 'dry-cli'
39
+ spec.add_dependency 'dry-cli-completion'
40
+ spec.add_dependency 'git'
41
+ spec.add_dependency 'gqli'
42
+ spec.add_dependency 'httpx'
43
+ spec.add_dependency 'pry-byebug'
44
+ spec.add_dependency 'reline'
45
+ spec.add_dependency 'semantic_logger'
46
+ spec.add_dependency 'sequel'
47
+ spec.add_dependency 'sqlite3'
48
+ spec.add_dependency 'tty-editor'
49
+ spec.add_dependency 'tty-markdown'
50
+ spec.add_dependency 'tty-prompt'
51
+
52
+ # For more information and examples about making a new gem, check out our
53
+ # guide at: https://bundler.io/guides/creating_gem.html
54
+ spec.metadata['rubygems_mfa_required'] = 'true'
55
+ end
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ ruby = "3.4.7"
metadata CHANGED
@@ -1,99 +1,98 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linear-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.19
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tj (bougyman) Vanderpoel
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-04-15 00:00:00.000000000 Z
10
+ date: 2025-11-03 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: base64
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '0.2'
18
+ version: '0'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - "~>"
23
+ - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '0.2'
25
+ version: '0'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: dry-cli
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
- - - "~>"
30
+ - - ">="
32
31
  - !ruby/object:Gem::Version
33
- version: '1.0'
32
+ version: '0'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
- - - "~>"
37
+ - - ">="
39
38
  - !ruby/object:Gem::Version
40
- version: '1.0'
39
+ version: '0'
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: dry-cli-completion
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
- - - "~>"
44
+ - - ">="
46
45
  - !ruby/object:Gem::Version
47
- version: '1.0'
46
+ version: '0'
48
47
  type: :runtime
49
48
  prerelease: false
50
49
  version_requirements: !ruby/object:Gem::Requirement
51
50
  requirements:
52
- - - "~>"
51
+ - - ">="
53
52
  - !ruby/object:Gem::Version
54
- version: '1.0'
53
+ version: '0'
55
54
  - !ruby/object:Gem::Dependency
56
55
  name: git
57
56
  requirement: !ruby/object:Gem::Requirement
58
57
  requirements:
59
- - - "~>"
58
+ - - ">="
60
59
  - !ruby/object:Gem::Version
61
- version: '1.5'
60
+ version: '0'
62
61
  type: :runtime
63
62
  prerelease: false
64
63
  version_requirements: !ruby/object:Gem::Requirement
65
64
  requirements:
66
- - - "~>"
65
+ - - ">="
67
66
  - !ruby/object:Gem::Version
68
- version: '1.5'
67
+ version: '0'
69
68
  - !ruby/object:Gem::Dependency
70
69
  name: gqli
71
70
  requirement: !ruby/object:Gem::Requirement
72
71
  requirements:
73
- - - "~>"
72
+ - - ">="
74
73
  - !ruby/object:Gem::Version
75
- version: '1.2'
74
+ version: '0'
76
75
  type: :runtime
77
76
  prerelease: false
78
77
  version_requirements: !ruby/object:Gem::Requirement
79
78
  requirements:
80
- - - "~>"
79
+ - - ">="
81
80
  - !ruby/object:Gem::Version
82
- version: '1.2'
81
+ version: '0'
83
82
  - !ruby/object:Gem::Dependency
84
83
  name: httpx
85
84
  requirement: !ruby/object:Gem::Requirement
86
85
  requirements:
87
- - - "~>"
86
+ - - ">="
88
87
  - !ruby/object:Gem::Version
89
- version: '1.2'
88
+ version: '0'
90
89
  type: :runtime
91
90
  prerelease: false
92
91
  version_requirements: !ruby/object:Gem::Requirement
93
92
  requirements:
94
- - - "~>"
93
+ - - ">="
95
94
  - !ruby/object:Gem::Version
96
- version: '1.2'
95
+ version: '0'
97
96
  - !ruby/object:Gem::Dependency
98
97
  name: pry-byebug
99
98
  requirement: !ruby/object:Gem::Requirement
@@ -108,90 +107,104 @@ dependencies:
108
107
  - - ">="
109
108
  - !ruby/object:Gem::Version
110
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: reline
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
111
124
  - !ruby/object:Gem::Dependency
112
125
  name: semantic_logger
113
126
  requirement: !ruby/object:Gem::Requirement
114
127
  requirements:
115
- - - "~>"
128
+ - - ">="
116
129
  - !ruby/object:Gem::Version
117
- version: '4.0'
130
+ version: '0'
118
131
  type: :runtime
119
132
  prerelease: false
120
133
  version_requirements: !ruby/object:Gem::Requirement
121
134
  requirements:
122
- - - "~>"
135
+ - - ">="
123
136
  - !ruby/object:Gem::Version
124
- version: '4.0'
137
+ version: '0'
125
138
  - !ruby/object:Gem::Dependency
126
139
  name: sequel
127
140
  requirement: !ruby/object:Gem::Requirement
128
141
  requirements:
129
- - - "~>"
142
+ - - ">="
130
143
  - !ruby/object:Gem::Version
131
- version: '5.0'
144
+ version: '0'
132
145
  type: :runtime
133
146
  prerelease: false
134
147
  version_requirements: !ruby/object:Gem::Requirement
135
148
  requirements:
136
- - - "~>"
149
+ - - ">="
137
150
  - !ruby/object:Gem::Version
138
- version: '5.0'
151
+ version: '0'
139
152
  - !ruby/object:Gem::Dependency
140
153
  name: sqlite3
141
154
  requirement: !ruby/object:Gem::Requirement
142
155
  requirements:
143
- - - "~>"
156
+ - - ">="
144
157
  - !ruby/object:Gem::Version
145
- version: '1.7'
158
+ version: '0'
146
159
  type: :runtime
147
160
  prerelease: false
148
161
  version_requirements: !ruby/object:Gem::Requirement
149
162
  requirements:
150
- - - "~>"
163
+ - - ">="
151
164
  - !ruby/object:Gem::Version
152
- version: '1.7'
165
+ version: '0'
153
166
  - !ruby/object:Gem::Dependency
154
167
  name: tty-editor
155
168
  requirement: !ruby/object:Gem::Requirement
156
169
  requirements:
157
- - - "~>"
170
+ - - ">="
158
171
  - !ruby/object:Gem::Version
159
- version: '0.7'
172
+ version: '0'
160
173
  type: :runtime
161
174
  prerelease: false
162
175
  version_requirements: !ruby/object:Gem::Requirement
163
176
  requirements:
164
- - - "~>"
177
+ - - ">="
165
178
  - !ruby/object:Gem::Version
166
- version: '0.7'
179
+ version: '0'
167
180
  - !ruby/object:Gem::Dependency
168
181
  name: tty-markdown
169
182
  requirement: !ruby/object:Gem::Requirement
170
183
  requirements:
171
- - - "~>"
184
+ - - ">="
172
185
  - !ruby/object:Gem::Version
173
- version: '0.7'
186
+ version: '0'
174
187
  type: :runtime
175
188
  prerelease: false
176
189
  version_requirements: !ruby/object:Gem::Requirement
177
190
  requirements:
178
- - - "~>"
191
+ - - ">="
179
192
  - !ruby/object:Gem::Version
180
- version: '0.7'
193
+ version: '0'
181
194
  - !ruby/object:Gem::Dependency
182
195
  name: tty-prompt
183
196
  requirement: !ruby/object:Gem::Requirement
184
197
  requirements:
185
- - - "~>"
198
+ - - ">="
186
199
  - !ruby/object:Gem::Version
187
- version: '0.23'
200
+ version: '0'
188
201
  type: :runtime
189
202
  prerelease: false
190
203
  version_requirements: !ruby/object:Gem::Requirement
191
204
  requirements:
192
- - - "~>"
205
+ - - ">="
193
206
  - !ruby/object:Gem::Version
194
- version: '0.23'
207
+ version: '0'
195
208
  description: A CLI for interacting with Linear.app. Loosely based on the GitHub CLI
196
209
  email:
197
210
  - tj@rubyists.com
@@ -206,6 +219,9 @@ extensions: []
206
219
  extra_rdoc_files: []
207
220
  files:
208
221
  - ".overcommit.yml"
222
+ - ".release-please-config.json"
223
+ - ".release-please-manifest.json"
224
+ - ".version.txt"
209
225
  - CHANGELOG.md
210
226
  - LICENSE.txt
211
227
  - Rakefile
@@ -228,6 +244,7 @@ files:
228
244
  - lib/linear/cli.rb
229
245
  - lib/linear/cli/caller.rb
230
246
  - lib/linear/cli/common_options.rb
247
+ - lib/linear/cli/projects.rb
231
248
  - lib/linear/cli/sub_commands.rb
232
249
  - lib/linear/cli/version.rb
233
250
  - lib/linear/cli/watcher.rb
@@ -258,9 +275,8 @@ files:
258
275
  - lib/linear/models/user.rb
259
276
  - lib/linear/models/workflow_state.rb
260
277
  - lib/linear/version.rb
261
- - oci/Containerfile
262
- - oci/build_image
263
- - oci/plc
278
+ - linear-cli.gemspec
279
+ - mise.toml
264
280
  homepage: https://github.com/rubyists/linear-cli
265
281
  licenses:
266
282
  - MIT
@@ -270,7 +286,6 @@ metadata:
270
286
  source_code_uri: https://github.com/rubyists/linear-cli
271
287
  changelog_uri: https://github.com/rubyists/linear-cli/blob/master/CHANGELOG.md
272
288
  rubygems_mfa_required: 'true'
273
- post_install_message:
274
289
  rdoc_options: []
275
290
  require_paths:
276
291
  - lib
@@ -278,15 +293,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
278
293
  requirements:
279
294
  - - ">="
280
295
  - !ruby/object:Gem::Version
281
- version: 3.2.0
296
+ version: 3.4.0
282
297
  required_rubygems_version: !ruby/object:Gem::Requirement
283
298
  requirements:
284
299
  - - ">="
285
300
  - !ruby/object:Gem::Version
286
301
  version: '0'
287
302
  requirements: []
288
- rubygems_version: 3.5.3
289
- signing_key:
303
+ rubygems_version: 3.6.2
290
304
  specification_version: 4
291
305
  summary: CLI for interacting with Linear.app.
292
306
  test_files: []
data/oci/Containerfile DELETED
@@ -1,37 +0,0 @@
1
- FROM docker.io/ruby:3.3.0-alpine3.18 AS build-env
2
-
3
-
4
- # Setting env up
5
- ARG APP_ROOT=/app
6
- ARG APP_VERSION
7
- ARG BUNDLE_JOBS=8
8
- ENV LANG C.UTF-8
9
- ENV BUNDLE_SILENCE_ROOT_WARNING=1
10
-
11
- #Install dependencies needed for compilation
12
- RUN apk --update add bash ruby-dev build-base git sqlite-dev
13
-
14
- WORKDIR $APP_ROOT
15
-
16
- COPY . $APP_ROOT
17
- RUN gem i semantic_logger && \
18
- bundle config set build.nokogiri --use-system-libraries && \
19
- bundle config set without 'test assets' && \
20
- bundle install && \
21
- bundle exec rake build
22
-
23
- ############### Build step done ###############
24
- FROM docker.io/ruby:3.3.0-alpine3.18
25
- ARG PACKAGES="bash sqlite github-cli openssh"
26
- ARG APP_VERSION
27
- ARG APP_ROOT=/app
28
-
29
- # install packages
30
- RUN apk --update --no-cache add $PACKAGES
31
- COPY --from=build-env /app /app
32
- COPY --from=build-env /usr/local/bundle /usr/local/bundle
33
- WORKDIR $APP_ROOT
34
- RUN bundle exec gem i /app/pkg/linear-cli-${APP_VERSION}.gem
35
-
36
- CMD ["lc"]
37
-
data/oci/build_image DELETED
@@ -1,138 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- : "${IMAGE_NAME:=$(basename "$(pwd)")}"
4
- : "${BUILD_CONTEXT:=$(pwd)}"
5
-
6
- usage() { # {{{
7
- cat <<-EOT
8
- Usage: $0 <options> <image_tag>
9
- Options:
10
- -i NAME Name of the image (default: $IMAGE_NAME)
11
- -c CONTAINERFILE Path to the containerfile (default: ./oci/Containerfile)
12
- -C CONTEXT Build context (default: $BUILD_CONTEXT)
13
- -p Push the image to the registry
14
- -s Also mark the image as stable
15
- -h Show help / usage
16
- EOT
17
- } # }}}
18
-
19
- die() { # {{{
20
- local -i code
21
- code=$1
22
- shift
23
- printf "Error! => %s\n" "$*" >&2
24
- printf "\n" >&2
25
- usage >&2
26
- # shellcheck disable=SC2086
27
- exit $code
28
- } # }}}
29
-
30
- push=0
31
- stable=0
32
- while getopts :hpi:c:C:s opt # {{{
33
- do
34
- case $opt in
35
- c)
36
- CONTAINERFILE=$OPTARG
37
- ;;
38
- C)
39
- BUILD_CONTEXT=$OPTARG
40
- ;;
41
- i)
42
- IMAGE_NAME=$OPTARG
43
- ;;
44
- p)
45
- push=1
46
- ;;
47
- s)
48
- stable=1
49
- ;;
50
- h)
51
- usage
52
- exit
53
- ;;
54
- :)
55
- printf "Option %s requires an argument\n" "$OPTARG" >&2
56
- usage >&2
57
- exit 28
58
- ;;
59
- ?)
60
- printf "Invalid option '%s'\n" "$OPTARG" >&2
61
- usage >&2
62
- exit 27
63
- ;;
64
- esac
65
- done # }}}
66
- shift $((OPTIND-1))
67
-
68
- tag=$1
69
- [ -z "$tag" ] && die 1 "Missing image tag"
70
- shift
71
-
72
- [ $# -gt 0 ] && die 2 "Too many arguments"
73
-
74
- if [ -z "$CONTAINERFILE" ]; then
75
- printf "No containerfile specified, looking for default locations\n"
76
- for containerfile in Containerfile Dockerfile
77
- do
78
- if [ -f ./oci/"$containerfile" ]; then
79
- printf "Found ./oci/%s\n" "$containerfile" >&2
80
- containerfile=./oci/"$containerfile"
81
- break
82
- fi
83
- if [ -f "$containerfile" ]; then
84
- printf "Found %s\n" "$containerfile" >&2
85
- break
86
- fi
87
- done
88
- else
89
- [ -f "$CONTAINERFILE" ] || die 3 "Containerfile '$CONTAINERFILE' not found"
90
- printf "Using containerfile %s\n" "$CONTAINERFILE" >&2
91
- containerfile=$CONTAINERFILE
92
- fi
93
-
94
- [ -f "$containerfile" ] || die 4 "No containerfile found"
95
-
96
- [ -d "$BUILD_CONTEXT" ] || die 5 "Build context '$BUILD_CONTEXT' not found"
97
-
98
- # Build the image
99
- if command -v podman 2>/dev/null
100
- then
101
- runtime=podman
102
- elif command -v docker 2>/dev/null
103
- then
104
- runtime=docker
105
- else
106
- die 6 "No container runtime found"
107
- fi
108
-
109
- app_version=$(bundle exec lc version)
110
- $runtime build --build-arg "APP_VERSION=${app_version}" -t "$IMAGE_NAME:$tag" -f "$containerfile" "$BUILD_CONTEXT" || die 7 "Failed to build image"
111
-
112
- set -x
113
- [ $push -eq 1 ] || exit 0
114
- # push the image
115
- registry_image_name="ghcr.io/rubyists/$IMAGE_NAME:$tag"
116
- if ! $runtime login --get-login ghcr.io
117
- then
118
- printf "Not logged in to ghcr.io, trying to login\n" >&2
119
- [ -z "$GITHUB_TOKEN" ] && die 8 "No GITHUB_TOKEN set, cannot login"
120
- printf "%s" "$GITHUB_TOKEN" | $runtime login -u "$GITHUB_TOKEN" --password-stdin ghcr.io || die 9 "Failed to login to ghcr.io"
121
- fi
122
-
123
- if [ "$runtime" = "podman" ]
124
- then
125
- podman push "$IMAGE_NAME:$tag" "$registry_image_name" || die 10 "Failed to push image"
126
- else
127
- docker push "$registry_image_name" || die 11 "Failed to push image"
128
- fi
129
-
130
- [ "$stable" -eq 0 ] && exit 0
131
- # Mark the image as stable
132
- registry_stable_name="ghcr.io/rubyists/$IMAGE_NAME:stable"
133
- if [ "$runtime" = "podman" ]
134
- then
135
- podman push "$IMAGE_NAME:$tag" "$registry_stable_name" || die 10 "Failed to push image"
136
- else
137
- docker push "$registry_stable_name" || die 11 "Failed to push image"
138
- fi
data/oci/plc DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env bash
2
- exec podman run -v ~/.ssh:/root/.ssh -w /git -v .:/git -e GITHUB_TOKEN="$GITHUB_TOKEN" -e LINEAR_API_KEY="$LINEAR_API_KEY" --rm -it ghcr.io/rubyists/linear-cli:stable lc "$@"