Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .rspec

This file was deleted.

33 changes: 29 additions & 4 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
---
plugins:
- rubocop-minitest
- rubocop-performance
- rubocop-rake
- rubocop-rspec

AllCops:
TargetRubyVersion: 3.4.0
NewCops: enable
SuggestExtensions: false

Metrics/ClassLength:
CountAsOne: ['array', 'heredoc', 'hash']
Max: 115

Metrics/ModuleLength:
CountAsOne: ['array', 'heredoc', 'hash']
Max: 115
Exclude:
- 'spec/**/*.rb'

Metrics/MethodLength:
CountAsOne: ['array', 'heredoc', 'hash']

Metrics/BlockLength:
CountAsOne: ['array', 'heredoc', 'hash']
Exclude:
- 'test/**/*'
- '*.gemspec'

Layout/LineLength:
Max: 120
AllowedPatterns: ['\A#']

Style/CommentedKeyword:
Enabled: false

Style/StringLiterals:
Enabled: true
Expand All @@ -14,6 +42,3 @@ Style/StringLiterals:
Style/StringLiteralsInInterpolation:
Enabled: true
EnforcedStyle: double_quotes

Layout/LineLength:
Max: 120
6 changes: 4 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ group :development, :test do
gem 'changelog-rb', '~> 0.3'
gem 'cucumber', '~> 9.1'
gem 'gem-release', '~> 2.2'
gem 'minitest', '~> 5.0'
gem 'rake', '~> 13.0'
gem 'rspec', '~> 3.0'
gem 'rubocop', '~> 1.21'
gem 'rubocop-minitest', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rake', require: false
gem 'rubocop-rspec', require: false
gem 'shoulda-context', '~> 2.0'
end

# Specify your gem's dependencies in linear-cli.gemspec
Expand Down
15 changes: 12 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
# frozen_string_literal: true

require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require 'rake/testtask'

RSpec::Core::RakeTask.new(:spec)
Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.libs << 'lib'
t.test_files = FileList['test/**/*_test.rb']
end

require 'rubocop/rake_task'

RuboCop::RakeTask.new

task default: %i[spec rubocop]
desc 'Run Cucumber features'
task :cucumber do
sh 'cucumber --format pretty'
end

task default: %i[rubocop test cucumber]
5 changes: 2 additions & 3 deletions exe/scripts/lc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ elif [ $result -gt 1 ]; then
printf "\n\nlc: linear-cli interrupted\n" >&2
exit 130
fi
printf "lc: linear-cli failed %s\n" $result >&2
lc "$@" --help 2>&1
exit 1
exit $result
fi
exit $result
11 changes: 6 additions & 5 deletions features/completion.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ Feature: Completion
# TODO: Make this not raise an exception and just show the usage instead
Scenario: Showing exception when no shell is given
When I run `lc completion`
Then the output should contain:
"""
missing keyword: :shell (ArgumentError)
"""
Then the output should match /missing keyword: :shell \(ArgumentError\)/

Scenario: Showing exception when an invalid shell is given
When I run `lc completion invalid`
Expand All @@ -22,5 +19,9 @@ Feature: Completion
When I run `lc completion bash`
Then the output should contain:
"""
# lc completion -*- shell-script -*-
# linear-cli completion -*- shell-script -*-
"""
And the output should contain:
"""
complete -F _linear-cli_completions lc
"""
17 changes: 17 additions & 0 deletions features/issue_list.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Feature: Issue List
As a user
I want to list issues
So that I can see what I need to work on

Scenario: Listing my issues
When I run `lc issue list`
Then the output should match /[\w-]+/

Scenario: Listing all issues
When I run `lc issue list --no-mine`
Then the output should match /[\w-]+/

Scenario: Listing specific issue
When I run `lc issue list NOCRY-123`
Then the exit status should be 66
And the output should match /Record not found/
12 changes: 12 additions & 0 deletions features/team_list.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Feature: Team List
As a user
I want to list teams
So that I can see what teams are available

Scenario: Listing my teams
When I run `lc team list`
Then the output should match /[\w-]+/

Scenario: Listing all teams
When I run `lc team list --no-mine`
Then the output should match /[\w-]+/
8 changes: 8 additions & 0 deletions features/whoami.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Feature: WhoAmI
As a user
I want to know who I am logged in as
So that I can verify my credentials

Scenario: Displaying the current user
When I run `lc whoami`
Then the output should match /[\w-]+: .+ <.+>/
7 changes: 7 additions & 0 deletions lib/linear.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

require 'pathname'
require 'trailblazer'
require 'trailblazer/operation'
require 'semantic_logger'
SemanticLogger.default_level = :info
SemanticLogger.add_appender(io: $stderr, formatter: :color)
Expand All @@ -21,6 +23,7 @@ module Linear
ROOT = (Pathname(__FILE__)/'../..').expand_path
LIBROOT = ROOT/:lib/:linear
MODEL_ROOT = ROOT/:lib/:linear/:models
OPERATION_ROOT = ROOT/:lib/:linear/:operations
SPEC_ROOT = ROOT/:spec
FEATURE_ROOT = ROOT/:features
DEBUG_LEVELS = %i[warn info debug trace].freeze
Expand All @@ -41,6 +44,10 @@ def self.L(*libraries) # rubocop:disable Naming/MethodName
def self.M(*models) # rubocop:disable Naming/MethodName
Array(models).each { |model| require MODEL_ROOT/model }
end

def self.O(*operations) # rubocop:disable Naming/MethodName
Array(operations).each { |operation| require OPERATION_ROOT/operation }
end
# rubocop:enable Layout/SpaceAroundOperators

def self.verbosity
Expand Down
1 change: 0 additions & 1 deletion lib/linear/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

require 'dry/cli'
require 'dry/cli/completion/command'
require_relative '../linear'
require 'semantic_logger'
require 'tty-markdown'
require 'tty-prompt'
Expand Down
4 changes: 2 additions & 2 deletions lib/linear/cli/what_for.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def pr_title_for(issue)
proposed = [pr_type_for(issue)]
proposed_scope = pr_scope_for(issue.title)
proposed << "(#{proposed_scope})" if proposed_scope
summary = issue.title.sub(/(?:#{ALLOWED_PR_TYPES})(\([^)]+\))? /, '')
summary = issue.title.sub(/(?:#{ALLOWED_PR_TYPES})(\([^)]+\))? /o, '')
proposed << ": #{issue.identifier} - #{summary}"
prompt.ask("Title for PR for #{issue.identifier} - #{summary}", default: proposed.join)
end
Expand All @@ -113,7 +113,7 @@ def pr_description_for(issue)
end

def pr_type_for(issue)
proposed_type = issue.title.match(/^(#{ALLOWED_PR_TYPES})/i)
proposed_type = issue.title.match(/^(#{ALLOWED_PR_TYPES})/io)
return proposed_type[1].downcase if proposed_type

prompt.select('What type of PR is this?', PR_TYPE_SELECTIONS)
Expand Down
1 change: 0 additions & 1 deletion lib/linear/commands/issue/create.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# frozen_string_literal: true

require 'semantic_logger'
require_relative '../issue'

module Rubyists
# Namespace for Linear
Expand Down
1 change: 0 additions & 1 deletion lib/linear/commands/issue/develop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

require 'semantic_logger'
require 'git'
require_relative '../issue'

module Rubyists
# Namespace for Linear
Expand Down
31 changes: 7 additions & 24 deletions lib/linear/commands/issue/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Rubyists
module Linear
M :issue
M :user
O 'issue/list'
# Namespace for CLI
module CLI
module Issue
Expand Down Expand Up @@ -37,31 +38,13 @@ class List

def call(ids:, **options)
logger.debug 'Listing issues'
return display(issues_for(options), options) if ids.empty?

display issues_for(options.merge(ids:)), options
end

def filters_for(options)
filter = {}
filter[:assignee] = { isMe: { eq: true } } if options[:mine]
filter[:assignee] = { null: true } if options[:unassigned]
filter[:team] = { key: { eq: options[:team] } } if options[:team]

if options[:project]
project = project_for(options[:project])
logger.debug('Found project', project:)
filter[:project] = { id: { eq: project.id } } if project
project = project_for(options[:project]) if options[:project]
result = Rubyists::Linear::Operations::Issue::List.call(params: options.merge(ids:), project: project)
if result.success?
display result[:issues], options
else
logger.error 'Failed to list issues'
end

filter
end

def issues_for(options)
logger.debug('Fetching issues', options:)
return options[:ids].map { |id| Rubyists::Linear::Issue.find(id.upcase) } if options[:ids]

Rubyists::Linear::Issue.all filter: filters_for(options)
end
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/linear/commands/issue/pr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

require 'semantic_logger'
require 'git'
require_relative '../issue'

module Rubyists
# Namespace for Linear
Expand Down
5 changes: 2 additions & 3 deletions lib/linear/commands/issue/take.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# frozen_string_literal: true

require 'semantic_logger'
require_relative '../issue'

module Rubyists
# Namespace for Linear
Expand All @@ -21,13 +20,13 @@ class Take
argument :issue_ids, type: :array, required: true, desc: 'Issue Identifiers'

def call(issue_ids:, **options)
updates = issue_ids.map do |issue_id|
updates = issue_ids.filter_map do |issue_id|
Rubyists::Linear::Issue.find(issue_id)
gimme_da_issue! issue_id # gimme_da_issue! is defined in Rubyists::Linear::CLI::Issue
rescue NotFoundError => e
logger.warn e.message
next
end.compact
end
display updates, options
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/linear/commands/issue/update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

require 'semantic_logger'
require 'git'
require_relative '../issue'

module Rubyists
# Namespace for Linear
Expand Down
14 changes: 7 additions & 7 deletions lib/linear/commands/team/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Rubyists
# Namespace for Linear
module Linear
M :team, :issue
O 'team/list'
# Namespace for CLI
module CLI
module Team
Expand All @@ -19,13 +20,12 @@ class List

def call(**options)
logger.debug 'Listing teams'
display teams_for(options), options
end

def teams_for(options)
return Rubyists::Linear::Team.mine if options[:mine]

Rubyists::Linear::Team.all
result = Rubyists::Linear::Operations::Team::List.call(params: options)
if result.success?
display result[:teams], options
else
logger.error 'Failed to list teams'
end
end

prepend Rubyists::Linear::CLI::Caller
Expand Down
8 changes: 7 additions & 1 deletion lib/linear/commands/whoami.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Rubyists
# Namespace for Linear
module Linear
M :user
O :whoami
# Namespace for CLI
module CLI
WhoAmI = Class.new Dry::CLI::Command
Expand All @@ -20,7 +21,12 @@ class WhoAmI

def call(**options)
logger.debug 'Getting user info'
display Rubyists::Linear::User.me(teams: options[:teams]), options
result = Rubyists::Linear::Operations::WhoAmI.call(params: options)
if result.success?
display result[:user], options
else
logger.error 'Failed to get user info'
end
end

prepend Rubyists::Linear::CLI::Caller
Expand Down
6 changes: 3 additions & 3 deletions lib/linear/models/base_model/method_magic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ module Linear
class BaseModel
# Methods for Linear models.
module MethodMagic
def self.included(base) # rubocop:disable Metrics/AbcSize
def self.included(base)
base.instance_eval do
base.base_fragment.__nodes.each do |node|
sym = node.__name.to_sym
define_method(sym) { updated_data[sym] } unless instance_methods.include? sym
define_method(sym) { updated_data[sym] } unless method_defined?(sym)
esym = :"#{sym}="
next if instance_methods.include? esym
next if method_defined?(esym)

define_method(esym) { |value| updated_data[sym] = value }
end
Expand Down
2 changes: 1 addition & 1 deletion lib/linear/models/issue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module Linear
Issue = Class.new(BaseModel)
M 'issue/class_methods'
# The Issue class represents a Linear issue.
class Issue # rubocop:disable Metrics/ClassLength
class Issue
include SemanticLogger::Loggable
extend ClassMethods

Expand Down
Loading
Loading