Class: Hubkit::Issue

Inherits:
Object
  • Object
show all
Defined in:
lib/hubkit/issue.rb

Overview

Represents one issue in github

Constant Summary collapse

ISSUE_PATTERN =

A regex which matches a textual name of an issue i.e. dingus/123 or foobar/dingus/123

%r{
  (
    (?<org>[^/]+)/(?<repo>[^/]+)
    |
    (?<repo>[^/]+)
  )
  /
  (?<number>[0-9]+)
}x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(org:, repo:, number:) ⇒ Issue

Create a new issue model

Parameters:

  • org (String)

    the github organization name of the issue

  • repo (String)

    the github repo name

  • number (Fixnum)

    the issue's number


58
59
60
61
62
# File 'lib/hubkit/issue.rb', line 58

def initialize(org:, repo:, number:)
  @org = org
  @repo = repo
  @number = number
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Allow access to elements of the github payload by calling the names as methods

Parameters:

  • name (String, Symbol)
  • args (Array)

    should be empty, only needed to match the expected signature from Ruby

Returns:


180
181
182
183
# File 'lib/hubkit/issue.rb', line 180

def method_missing(name, *args, &block)
  return to_gh[name] if args.length == 0 && !block_given? && to_gh.key?(name)
  super
end

Instance Attribute Details

#numberFixnum

the issue's number

Returns:

  • (Fixnum)

    the current value of number


6
7
8
# File 'lib/hubkit/issue.rb', line 6

def number
  @number
end

#orgString

the github organization name of the issue

Returns:

  • (String)

    the current value of org


6
7
8
# File 'lib/hubkit/issue.rb', line 6

def org
  @org
end

#repoString

the github repo name

Returns:

  • (String)

    the current value of repo


6
7
8
# File 'lib/hubkit/issue.rb', line 6

def repo
  @repo
end

Class Method Details

.from_gh(org:, repo:, gh:) ⇒ Object

Create an Issue model from a github api payload. Preseeds the github payload of the model to avoid refetching from the API later.

Parameters:

  • org (String)

    the github organization of the issue

  • repo (String)

    the repo name of the issue

  • gh (Hash)

    the payload hash from the API


46
47
48
49
50
# File 'lib/hubkit/issue.rb', line 46

def self.from_gh(org:, repo:, gh:)
  new(org: org, repo: repo, number: gh['number']).tap do |issue|
    issue.instance_variable_set(:@_to_gh, gh)
  end
end

.from_name(name) ⇒ Hubkit::Issue

Create an Issue model from the textual name of the issue

Examples:

Hubkit::Issue.from_name('foobar/dingus/123')

Parameters:

  • name (String)

    a string name for an issue, like dingus/123 or foobar/dingus/123

Returns:

  • (Hubkit::Issue)

    the issue matching this org, repo, and number


25
26
27
# File 'lib/hubkit/issue.rb', line 25

def self.from_name(name)
  new(**parameters_from_name(name))
end

.parameters_from_name(name) ⇒ Hash

Parse an issue name into org, repo, and number

Parameters:

  • name (String)

    a string like dingus/123 or foobar/dingus/123

Returns:

  • (Hash)

    a hash containing org:, repo:, and number: values


32
33
34
35
36
37
38
39
# File 'lib/hubkit/issue.rb', line 32

def self.parameters_from_name(name)
  match_data = Issue::ISSUE_PATTERN.match(name)
  {
    org: match_data[:org] || Hubkit::Configuration.default_org,
    repo: match_data[:repo],
    number: match_data[:number],
  }
end

Instance Method Details

#event_paginatorEventPaginator

Returns a paginator for fetching all events for this issue

Returns:

  • (EventPaginator)

    the paginator for fetching all events for this issue


149
150
151
152
153
154
155
# File 'lib/hubkit/issue.rb', line 149

def event_paginator
  EventPaginator.new(
    org: @org,
    repo: @repo,
    issue_number: @number,
  )
end

#eventsEventCollection

The EventCollection of events related to this Issue

Returns:

  • (EventCollection)

    the events for this issue, in reverse chronological order


139
140
141
142
143
144
145
# File 'lib/hubkit/issue.rb', line 139

def events
  @_events ||=
    EventCollection.new(
      event_paginator,
    )
    .reverse_chronological
end

#label!(label) ⇒ Enumerable

Add a label to an issue

Parameters:

  • label (String)

    the label to add to the issue

Returns:

  • (Enumerable)

    the new list of labels including the addition


79
80
81
82
# File 'lib/hubkit/issue.rb', line 79

def label!(label)
  Hubkit.client.issues.labels.add @org, @repo, @number, label
  labels.append(label).uniq!
end

#labelsEnumerable

A list of all of the current labels of the issue

Returns:

  • (Enumerable)

    the list of labels


72
73
74
# File 'lib/hubkit/issue.rb', line 72

def labels
  @_labels ||= to_gh['labels'].map { |label| label.name.downcase }
end

#pull?Boolean

Returns true if the issue is a pull request

Returns:

  • (Boolean)

    true if the issue is a pull request, otherwise false


105
106
107
# File 'lib/hubkit/issue.rb', line 105

def pull?
  to_gh['pull_request'].present?
end

#to_ghGithub::Mash

The issue payload from the github API

Returns:

  • (Github::Mash)

    a hash-like object of the github API response


66
67
68
# File 'lib/hubkit/issue.rb', line 66

def to_gh
  @_to_gh ||= Github.issues.get(@org, @repo, @number).body
end

#to_textString

A plaintext version of the issue, with the name, title, and body

Returns:

  • (String)

    a string containing the name, title, and body, suitable for uses like export or chat integration


170
171
172
# File 'lib/hubkit/issue.rb', line 170

def to_text
  "#{number}: #{title}\n---\n#{body}\n"
end

#true_issue?Boolean

Returns true if the issue is not a pull request

Returns:

  • (Boolean)

    false if the issue is a pull request, otherwise true


111
112
113
# File 'lib/hubkit/issue.rb', line 111

def true_issue?
  !pull?
end

#unlabel! {|label_name| ... } ⇒ Enumerable

Remove a label from an issue

Yield Parameters:

  • label_name (String)

    a current label. if the block returns true, this label will be removed from the list

Returns:

  • (Enumerable)

    the new list of labels after any removals


88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/hubkit/issue.rb', line 88

def unlabel!(&block)
  fail('Block is required for unlabel') unless block_given?
  to_gh.labels.map(&:name)
  .select do |label_name|
    yield label_name
  end
  .each do |label_name|
    Hubkit.client.issues.labels.remove @org, @repo, @number, label_name: label_name
    labels.delete(label_name)
  end
  labels
end

#users_ever_assignedEnumerable

Return the list of usernames of every user ever assigned to an issue

Returns:

  • (Enumerable)

    the usernames of the users which have been assigned to the issue


160
161
162
163
164
165
# File 'lib/hubkit/issue.rb', line 160

def users_ever_assigned
  events
    .select { |event| event.event == 'assigned' }
    .map { |event| event.assignee. }
    .uniq
end

#when_closedDateTime

Returns when the issue was closed

Returns:

  • (DateTime)

    the DateTime when the issue was closed


132
133
134
135
# File 'lib/hubkit/issue.rb', line 132

def when_closed
  return unless events.closed.any?
  Time.parse(events.closed.first['created_at'])
end

#when_labeled(label) ⇒ Date

Returns the time at which the issue was labeled `label`. It will return the time of the latest such event.

Parameters:

  • label (String)

    the label to search for

Returns:

  • (Date)

    the date when that issue was labeled such.


119
120
121
122
# File 'lib/hubkit/issue.rb', line 119

def when_labeled(label)
  return unless events.labeled(label).any?
  Time.parse(events.labeled(label).first['created_at'])
end

#when_openedDateTime

Returns when the issue was opened

Returns:

  • (DateTime)

    the DateTime when the issue was created


126
127
128
# File 'lib/hubkit/issue.rb', line 126

def when_opened
  Time.parse(created_at)
end