Module: GithubIssues

Defined in:
app/services/github_issues.rb

Overview

GitHub Issues sync (card #49): issues are the adjacent primitive to cards — gh is already authenticated, so import is a listing + a click, and closing happens naturally via "Closes #N" in the card's PR body.

Defined Under Namespace

Classes: Issue

Class Method Summary collapse

Class Method Details

.available?(board) ⇒ Boolean

Returns:

  • (Boolean)


7
8
9
# File 'app/services/github_issues.rb', line 7

def self.available?(board)
  board.repo_url.present? && board.local_path.present?
end

.import!(board, number) ⇒ Object

One click → one card in the inbox, tagged with the issue's labels, body carried as the description with provenance. Best-effort backlink comment on the issue so the GitHub side knows where the work went.

Raises:

  • (ArgumentError)


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/services/github_issues.rb', line 30

def self.import!(board, number)
  issue = list(board).find { |i| i.number == number.to_i }
  raise ArgumentError, "issue ##{number} not found among open issues" unless issue

  existing = board.cards.find_by(issue_number: issue.number)
  return existing if existing

  inbox = board.columns.inbox.order(:position).first
  card = board.cards.create!(
    column: inbox, title: issue.title, issue_number: issue.number,
    tags: issue.labels.first(5),
    description: "#{issue.body.presence || "(no issue body)"}\n\n---\n_Imported from GitHub issue ##{issue.number}._"
  )
  card.log!("status_change", actor: "user", text: "Imported from GitHub issue ##{issue.number}")
  Open3.capture2e("gh", "issue", "comment", issue.number.to_s,
                  "--body", "Tracking in Cardinal as card ##{card.number}. The pull request, when opened, will link back and close this issue on merge.",
                  chdir: board.local_path)
  card
end

.list(board) ⇒ Object

Open issues, newest first. Empty array on any failure (no remote, gh not authed, offline) — the modal explains instead of erroring.



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'app/services/github_issues.rb', line 13

def self.list(board)
  out, status = Open3.capture2e(
    "gh", "issue", "list", "--state", "open", "--limit", "50",
    "--json", "number,title,body,labels", chdir: board.local_path
  )
  return [] unless status.success?
  JSON.parse(out).map do |i|
    Issue.new(number: i["number"], title: i["title"], body: i["body"].to_s,
              labels: Array(i["labels"]).map { |l| l["name"] })
  end
rescue JSON::ParserError
  []
end