Class: GithubIssueSync::IssueSyncer

Inherits:
Object
  • Object
show all
Defined in:
lib/github_issue_sync/issue_syncer.rb

Overview

Reads a QA CSV (produced by IssueExporter or the v2 template) and:

• Updates existing GitHub issues whose title, state, body, or labels changed.
• Creates new issues for rows where "GitHub Issue #" is blank.
• Skips rows that are identical to the current GitHub state.

Usage:

syncer = GithubIssueSync::IssueSyncer.new(repo: "owner/repo", token: ENV["GITHUB_TOKEN"])
result = syncer.call(csv_path: "tmp/gh-issues-export.csv")
result = syncer.call(csv_path: "...", dry_run: true, io: $stdout)

Instance Method Summary collapse

Constructor Details

#initialize(repo:, token:) ⇒ IssueSyncer

Returns a new instance of IssueSyncer.



18
19
20
21
# File 'lib/github_issue_sync/issue_syncer.rb', line 18

def initialize(repo:, token:)
  @repo  = repo
  @token = token
end

Instance Method Details

#call(csv_path:, dry_run: false, io: $stdout) ⇒ Hash

Returns Counts: { updated:, created: } or { would_update:, would_create: }.

Parameters:

  • csv_path (String)

    Path to the CSV to sync.

  • dry_run (Boolean) (defaults to: false)

    When true, print intended actions but make no API calls.

  • io (IO) (defaults to: $stdout)

    Output stream for dry-run / summary (default $stdout).

Returns:

  • (Hash)

    Counts: { updated:, created: } or { would_update:, would_create: }



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/github_issue_sync/issue_syncer.rb', line 27

def call(csv_path:, dry_run: false, io: $stdout)
  rows = load_csv(csv_path)

  # Split into existing (have a number) and new (no number).
  existing_rows, new_rows = rows.partition { |r| r["GitHub Issue #"].to_s.strip != "" }

  # Fetch current state of all referenced issues in one pass so we can diff.
  live_issues = fetch_live_issues(existing_rows.map { |r| r["GitHub Issue #"].to_i })

  updated = 0
  created = 0
  would_update = 0
  would_create = 0

  existing_rows.each do |row|
    number = row["GitHub Issue #"].to_i
    live   = live_issues[number]
    next unless live  # issue not found on GitHub — skip silently

    if changed?(row, live)
      if dry_run
        io.puts "DRY-RUN UPDATE ##{number}: #{row['Title']}"
        would_update += 1
      else
        patch_issue(number, row)
        updated += 1
      end
    end
    # else: nothing changed — skip
  end

  new_rows.each do |row|
    if dry_run
      io.puts "DRY-RUN CREATE: #{row['Title']}"
      would_create += 1
    else
      post_issue(row)
      created += 1
    end
  end

  if dry_run
    { would_update: would_update, would_create: would_create }
  else
    { updated: updated, created: created }
  end
end