collavre_github 0.4.1 → 0.5.1

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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/collavre_github/creatives/integrations_controller.rb +61 -12
  3. data/app/controllers/collavre_github/webhooks_controller.rb +25 -4
  4. data/app/javascript/collavre_github.js +706 -0
  5. data/app/jobs/collavre_github/initial_markdown_sync_job.rb +19 -0
  6. data/app/jobs/collavre_github/markdown_sync_job.rb +16 -0
  7. data/app/models/collavre_github/repository_link.rb +7 -0
  8. data/app/services/collavre_github/client.rb +50 -0
  9. data/app/services/collavre_github/markdown_sync/content_processor.rb +113 -0
  10. data/app/services/collavre_github/markdown_sync/incremental_sync_service.rb +231 -0
  11. data/app/services/collavre_github/markdown_sync/initial_import_service.rb +190 -0
  12. data/app/services/collavre_github/tools/concerns/github_client_finder.rb +17 -0
  13. data/app/services/collavre_github/tools/github_pr_commits_service.rb +7 -10
  14. data/app/services/collavre_github/tools/github_pr_details_service.rb +21 -24
  15. data/app/services/collavre_github/tools/github_pr_diff_service.rb +13 -16
  16. data/app/services/collavre_github/webhook_provisioner.rb +18 -3
  17. data/app/views/collavre_github/auth/setup.html.erb +48 -3
  18. data/app/views/collavre_github/integrations/_modal.html.erb +18 -3
  19. data/config/locales/en.yml +9 -0
  20. data/config/locales/ko.yml +9 -0
  21. data/config/routes.rb +3 -1
  22. data/db/migrate/20260412000000_add_markdown_sync_to_repository_links.rb +10 -0
  23. data/db/migrate/20260416000000_add_markdown_root_creative_index.rb +5 -0
  24. data/lib/collavre_github/version.rb +1 -1
  25. data/lib/tasks/mock_import.rake +98 -0
  26. metadata +10 -1
@@ -23,17 +23,14 @@ module CollavreGithub
23
23
 
24
24
  sig { params(creative_id: Integer, repo: String, pr_number: Integer).returns(T::Hash[Symbol, T.untyped]) }
25
25
  def call(creative_id:, repo:, pr_number:)
26
- client = find_github_client(creative_id, repo)
27
- return { error: "GitHub account not found for this creative and repository" } unless client
26
+ with_github_client(creative_id: creative_id, repo: repo, error_context: "fetch PR commits") do |client|
27
+ messages = client.pull_request_commit_messages(repo, pr_number)
28
28
 
29
- messages = client.pull_request_commit_messages(repo, pr_number)
30
-
31
- {
32
- commits: messages.map.with_index(1) { |msg, i| { index: i, message: msg } },
33
- count: messages.size
34
- }
35
- rescue StandardError => e
36
- { error: "Failed to fetch PR commits: #{e.message}" }
29
+ {
30
+ commits: messages.map.with_index(1) { |msg, i| { index: i, message: msg } },
31
+ count: messages.size
32
+ }
33
+ end
37
34
  end
38
35
  end
39
36
  end
@@ -22,31 +22,28 @@ module CollavreGithub
22
22
 
23
23
  sig { params(creative_id: Integer, repo: String, pr_number: Integer).returns(T::Hash[Symbol, T.untyped]) }
24
24
  def call(creative_id:, repo:, pr_number:)
25
- client = find_github_client(creative_id, repo)
26
- return { error: "GitHub account not found for this creative and repository" } unless client
25
+ with_github_client(creative_id: creative_id, repo: repo, error_context: "fetch PR details") do |client|
26
+ pr = client.pull_request_details(repo, pr_number)
27
+ return { error: "Pull request not found" } unless pr
27
28
 
28
- pr = client.pull_request_details(repo, pr_number)
29
- return { error: "Pull request not found" } unless pr
30
-
31
- {
32
- number: pr.number,
33
- title: pr.title,
34
- body: pr.body.to_s.truncate(2000),
35
- state: pr.state,
36
- merged: pr.merged,
37
- author: pr.user&.login,
38
- created_at: pr.created_at&.iso8601,
39
- updated_at: pr.updated_at&.iso8601,
40
- merged_at: pr.merged_at&.iso8601,
41
- additions: pr.additions,
42
- deletions: pr.deletions,
43
- changed_files: pr.changed_files,
44
- html_url: pr.html_url,
45
- base_branch: pr.base&.ref,
46
- head_branch: pr.head&.ref
47
- }
48
- rescue StandardError => e
49
- { error: "Failed to fetch PR details: #{e.message}" }
29
+ {
30
+ number: pr.number,
31
+ title: pr.title,
32
+ body: pr.body.to_s.truncate(2000),
33
+ state: pr.state,
34
+ merged: pr.merged,
35
+ author: pr.user&.login,
36
+ created_at: pr.created_at&.iso8601,
37
+ updated_at: pr.updated_at&.iso8601,
38
+ merged_at: pr.merged_at&.iso8601,
39
+ additions: pr.additions,
40
+ deletions: pr.deletions,
41
+ changed_files: pr.changed_files,
42
+ html_url: pr.html_url,
43
+ base_branch: pr.base&.ref,
44
+ head_branch: pr.head&.ref
45
+ }
46
+ end
50
47
  end
51
48
  end
52
49
  end
@@ -35,22 +35,19 @@ module CollavreGithub
35
35
  def call(creative_id:, repo:, pr_number:, max_length: nil)
36
36
  max_length ||= DIFF_MAX_LENGTH
37
37
 
38
- client = find_github_client(creative_id, repo)
39
- return { error: "GitHub account not found for this creative and repository" } unless client
40
-
41
- diff = client.pull_request_diff(repo, pr_number)
42
- return { error: "Could not fetch diff", diff: nil } unless diff
43
-
44
- truncated = diff.length > max_length
45
- diff_text = truncated ? "#{diff[0, max_length]}\n...\n[Diff truncated to #{max_length} characters]" : diff
46
-
47
- {
48
- diff: diff_text,
49
- truncated: truncated,
50
- original_length: diff.length
51
- }
52
- rescue StandardError => e
53
- { error: "Failed to fetch PR diff: #{e.message}" }
38
+ with_github_client(creative_id: creative_id, repo: repo, error_context: "fetch PR diff") do |client|
39
+ diff = client.pull_request_diff(repo, pr_number)
40
+ return { error: "Could not fetch diff", diff: nil } unless diff
41
+
42
+ truncated = diff.length > max_length
43
+ diff_text = truncated ? "#{diff[0, max_length]}\n...\n[Diff truncated to #{max_length} characters]" : diff
44
+
45
+ {
46
+ diff: diff_text,
47
+ truncated: truncated,
48
+ original_length: diff.length
49
+ }
50
+ end
54
51
  end
55
52
  end
56
53
  end
@@ -1,6 +1,7 @@
1
1
  module CollavreGithub
2
2
  class WebhookProvisioner
3
3
  EVENTS = %w[pull_request].freeze
4
+ EVENTS_WITH_PUSH = %w[pull_request push].freeze
4
5
  CONTENT_TYPE = "json".freeze
5
6
 
6
7
  def self.ensure_for_links(account:, links:, webhook_url:)
@@ -23,8 +24,15 @@ module CollavreGithub
23
24
  end
24
25
 
25
26
  def remove_for_repositories(repositories)
27
+ # Batch-query to avoid N+1: find all repo names that still have links
28
+ linked_names = CollavreGithub::RepositoryLink
29
+ .where(repository_full_name: repositories)
30
+ .distinct
31
+ .pluck(:repository_full_name)
32
+ .to_set
33
+
26
34
  repositories.each do |repository_full_name|
27
- next if CollavreGithub::RepositoryLink.where(repository_full_name: repository_full_name).exists?
35
+ next if linked_names.include?(repository_full_name)
28
36
 
29
37
  remove_webhook(repository_full_name)
30
38
  end
@@ -84,7 +92,7 @@ module CollavreGithub
84
92
  repository_full_name,
85
93
  url: webhook_url,
86
94
  secret: secret,
87
- events: EVENTS,
95
+ events: events_for(repository_full_name),
88
96
  content_type: CONTENT_TYPE
89
97
  )
90
98
  end
@@ -95,11 +103,18 @@ module CollavreGithub
95
103
  hook_id,
96
104
  url: webhook_url,
97
105
  secret: secret,
98
- events: EVENTS,
106
+ events: events_for(repository_full_name),
99
107
  content_type: CONTENT_TYPE
100
108
  )
101
109
  end
102
110
 
111
+ def events_for(repository_full_name)
112
+ has_markdown_sync = CollavreGithub::RepositoryLink
113
+ .where(repository_full_name: repository_full_name, markdown_sync_enabled: true)
114
+ .exists?
115
+ has_markdown_sync ? EVENTS_WITH_PUSH : EVENTS
116
+ end
117
+
103
118
  def primary_link_for(repository_full_name)
104
119
  CollavreGithub::RepositoryLink
105
120
  .where(repository_full_name: repository_full_name)
@@ -101,7 +101,13 @@
101
101
  </div>
102
102
  </div>
103
103
 
104
- <!-- Step 3: Summary -->
104
+ <!-- Step 3: Markdown Sync -->
105
+ <div class="step" id="step-markdown-sync">
106
+ <p class="step-subtext"><%= t('collavre_github.markdown_sync.step_description', default: 'Enable Markdown Sync to import .md files as read-only creatives. Auto-synced on push.') %></p>
107
+ <div id="markdown-sync-list" class="list-box"></div>
108
+ </div>
109
+
110
+ <!-- Step 4: Summary -->
105
111
  <div class="step" id="step-summary">
106
112
  <p class="step-subtext"><%= t('collavre_github.integration.summary') %></p>
107
113
  <p id="webhook-instructions" class="step-subtext" style="display:none;"><%= t('collavre_github.integration.webhook_instructions') %></p>
@@ -139,10 +145,11 @@
139
145
  var loadReposError = wizard.dataset.loadReposError;
140
146
  var saveErrorMsg = wizard.dataset.saveError;
141
147
 
142
- var steps = ['organization', 'repositories', 'summary', 'done'];
148
+ var steps = ['organization', 'repositories', 'markdown-sync', 'summary', 'done'];
143
149
  var currentStepIndex = 0;
144
150
  var selectedOrg = null;
145
151
  var selectedRepos = new Set();
152
+ var markdownSyncRepos = new Set();
146
153
  var webhookDetails = {};
147
154
 
148
155
  var prevBtn = document.getElementById('prev-btn');
@@ -278,6 +285,39 @@
278
285
  });
279
286
  }
280
287
 
288
+ function populateMarkdownSync() {
289
+ var syncList = document.getElementById('markdown-sync-list');
290
+ syncList.innerHTML = '';
291
+ var repos = Array.from(selectedRepos);
292
+ if (!repos.length) {
293
+ syncList.innerHTML = '<p style="padding:0.5em;color:#999;">No repositories selected.</p>';
294
+ return;
295
+ }
296
+ repos.forEach(function(fullName) {
297
+ var label = document.createElement('label');
298
+ label.className = 'list-item';
299
+
300
+ var input = document.createElement('input');
301
+ input.type = 'checkbox';
302
+ input.value = fullName;
303
+ input.checked = markdownSyncRepos.has(fullName);
304
+ input.addEventListener('change', function() {
305
+ if (input.checked) {
306
+ markdownSyncRepos.add(fullName);
307
+ } else {
308
+ markdownSyncRepos.delete(fullName);
309
+ }
310
+ });
311
+
312
+ var span = document.createElement('span');
313
+ span.textContent = fullName + ' — Markdown Sync';
314
+
315
+ label.appendChild(input);
316
+ label.appendChild(span);
317
+ syncList.appendChild(label);
318
+ });
319
+ }
320
+
281
321
  function updateSummary() {
282
322
  var summaryList = document.getElementById('summary-repos');
283
323
  var summaryEmpty = document.getElementById('summary-empty');
@@ -320,7 +360,11 @@
320
360
 
321
361
  function saveSelection() {
322
362
  clearError();
323
- var payload = { repositories: Array.from(selectedRepos) };
363
+ var markdownSync = {};
364
+ Array.from(selectedRepos).forEach(function(repo) {
365
+ markdownSync[repo] = markdownSyncRepos.has(repo);
366
+ });
367
+ var payload = { repositories: Array.from(selectedRepos), markdown_sync: markdownSync };
324
368
 
325
369
  fetch('/github/creatives/' + creativeId + '/integration', {
326
370
  method: 'PATCH',
@@ -371,6 +415,7 @@
371
415
  var nextIndex = currentStepIndex + 1;
372
416
  showStep(nextIndex);
373
417
  if (steps[nextIndex] === 'repositories') loadRepositories();
418
+ if (steps[nextIndex] === 'markdown-sync') populateMarkdownSync();
374
419
  });
375
420
 
376
421
  finishBtn.addEventListener('click', function() {
@@ -10,6 +10,11 @@
10
10
  data-delete-error="<%= t('collavre_github.integration.delete_error', default: 'Failed to remove the Github integration.') %>"
11
11
  data-delete-button-label="<%= t('collavre_github.integration.delete_button', default: 'Remove integration') %>"
12
12
  data-delete-select-warning="<%= t('collavre_github.integration.delete_select_warning', default: 'Select repositories to delete.') %>"
13
+ data-resync-button-label="<%= t('collavre_github.integration.resync_button', default: 'Resync all') %>"
14
+ data-resync-confirm="<%= t('collavre_github.integration.resync_confirm', default: 'Re-import all markdown files from the selected repositories?') %>"
15
+ data-resync-success="<%= t('collavre_github.integration.resync_success', default: 'Re-sync started. The tree will update shortly.') %>"
16
+ data-resync-error="<%= t('collavre_github.integration.resync_error', default: 'Failed to start re-sync.') %>"
17
+ data-resync-select-warning="<%= t('collavre_github.integration.resync_select_warning', default: 'Select repositories to resync.') %>"
13
18
  style="display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:10000;align-items:center;justify-content:center;">
14
19
  <div class="popup-box" style="min-width:360px;max-width:90vw;">
15
20
  <button type="button" id="close-github-modal" class="popup-close-btn">&times;</button>
@@ -27,9 +32,14 @@
27
32
  <div id="github-existing-connections" style="display:none;margin-top:1.25em;">
28
33
  <p style="margin-bottom:0.5em;"><%= t('collavre_github.integration.existing_intro', default: 'Connected repositories:') %></p>
29
34
  <ul id="github-existing-repo-list" style="padding-left:1.2em;margin-bottom:0.75em;color:var(--color-text);"></ul>
30
- <button type="button" id="github-delete-btn" class="btn btn-danger" style="display:none;">
31
- <%= t('collavre_github.integration.delete_button', default: 'Remove integration') %>
32
- </button>
35
+ <div style="display:flex;gap:0.5em;flex-wrap:wrap;">
36
+ <button type="button" id="github-delete-btn" class="btn btn-danger" style="display:none;">
37
+ <%= t('collavre_github.integration.delete_button', default: 'Remove integration') %>
38
+ </button>
39
+ <button type="button" id="github-resync-btn" class="btn btn-secondary" style="display:none;">
40
+ <%= t('collavre_github.integration.resync_button', default: 'Resync all') %>
41
+ </button>
42
+ </div>
33
43
  </div>
34
44
  </div>
35
45
 
@@ -43,6 +53,11 @@
43
53
  <div id="github-repository-list" class="github-list github-modal-list-box" style="max-height:240px;overflow:auto;"></div>
44
54
  </div>
45
55
 
56
+ <div class="github-wizard-step" id="github-step-markdown-sync" style="display:none;">
57
+ <p class="github-modal-subtext"><%= t('collavre_github.markdown_sync.step_description', default: 'Enable Markdown Sync to import .md files as read-only creatives. Changes are auto-synced on push to the default branch.') %></p>
58
+ <div id="github-markdown-sync-list" class="github-list github-modal-list-box" style="max-height:240px;overflow:auto;"></div>
59
+ </div>
60
+
46
61
  <div class="github-wizard-step" id="github-step-summary" style="display:none;">
47
62
  <p class="github-modal-subtext"><%= t('collavre_github.integration.summary', default: 'The following repositories will be linked to this Creative:') %></p>
48
63
  <p id="github-webhook-instructions" class="github-modal-subtext" style="display:none;margin-bottom:0.5em;"><%= t('collavre_github.integration.webhook_instructions', default: 'Configure each repository with the webhook details below.') %></p>
@@ -16,6 +16,11 @@ en:
16
16
  delete_error: "Failed to remove the Github integration."
17
17
  delete_button: "Remove integration"
18
18
  delete_select_warning: "Select repositories to delete."
19
+ resync_button: "Resync all"
20
+ resync_confirm: "Re-import all markdown files from the selected repositories?"
21
+ resync_success: "Re-sync started. The tree will update shortly."
22
+ resync_error: "Failed to start re-sync."
23
+ resync_select_warning: "Select repositories to resync."
19
24
  connect: "Sign in with your Github account to start linking."
20
25
  login_button: "Sign in with Github"
21
26
  choose_org: "Select the organization that owns the repositories."
@@ -34,6 +39,10 @@ en:
34
39
  auth:
35
40
  login_first: "Please log in first to connect your GitHub account"
36
41
  connected: "GitHub account connected successfully"
42
+ markdown_sync:
43
+ step_description: "Enable Markdown Sync to import .md files as read-only creatives. Changes are auto-synced on push to the default branch."
44
+ not_enabled: "Markdown sync is not enabled for this repository."
45
+ resync_started: "Re-sync started. The tree will update shortly."
37
46
  errors:
38
47
  not_connected: "GitHub account not connected"
39
48
  forbidden: "You don't have permission to perform this action"
@@ -16,6 +16,11 @@ ko:
16
16
  delete_error: "Github 연동 삭제에 실패했습니다."
17
17
  delete_button: "연동 삭제"
18
18
  delete_select_warning: "삭제할 Repository를 선택하세요."
19
+ resync_button: "전체 다시 싱크"
20
+ resync_confirm: "선택한 저장소의 마크다운 파일을 전체 다시 가져오시겠습니까?"
21
+ resync_success: "재동기화가 시작되었습니다. 잠시 후 트리가 업데이트됩니다."
22
+ resync_error: "재동기화를 시작하지 못했습니다."
23
+ resync_select_warning: "재동기화할 저장소를 선택하세요."
19
24
  connect: "Github 계정으로 로그인하여 연동을 시작하세요."
20
25
  login_button: "Github으로 로그인"
21
26
  choose_org: "저장소가 속한 조직을 선택하세요."
@@ -34,6 +39,10 @@ ko:
34
39
  auth:
35
40
  login_first: "GitHub 계정을 연결하려면 먼저 로그인하세요"
36
41
  connected: "GitHub 계정이 연결되었습니다"
42
+ markdown_sync:
43
+ step_description: "Markdown Sync를 활성화하면 .md 파일이 읽기전용 크리에이티브로 가져와집니다. 기본 브랜치에 push하면 자동으로 동기화됩니다."
44
+ not_enabled: "이 저장소에 Markdown Sync가 활성화되어 있지 않습니다."
45
+ resync_started: "재동기화가 시작되었습니다. 곧 트리가 업데이트됩니다."
37
46
  errors:
38
47
  not_connected: "GitHub 계정이 연결되지 않았습니다"
39
48
  forbidden: "이 작업을 수행할 권한이 없습니다"
data/config/routes.rb CHANGED
@@ -16,6 +16,8 @@ CollavreGithub::Engine.routes.draw do
16
16
 
17
17
  # Creative integration endpoints
18
18
  resources :creatives, only: [] do
19
- resource :integration, module: :creatives, only: [ :show, :update, :destroy ]
19
+ resource :integration, module: :creatives, only: [ :show, :update, :destroy ] do
20
+ post :resync, on: :member
21
+ end
20
22
  end
21
23
  end
@@ -0,0 +1,10 @@
1
+ class AddMarkdownSyncToRepositoryLinks < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :github_repository_links, :markdown_sync_enabled, :boolean, default: false, null: false
4
+ add_column :github_repository_links, :markdown_root_creative_id, :integer
5
+ add_column :github_repository_links, :last_synced_at, :datetime
6
+ add_column :github_repository_links, :sync_branch, :string
7
+
8
+ add_index :github_repository_links, :markdown_sync_enabled
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class AddMarkdownRootCreativeIndex < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_index :github_repository_links, :markdown_root_creative_id, where: "markdown_root_creative_id IS NOT NULL", if_not_exists: true
4
+ end
5
+ end
@@ -1,3 +1,3 @@
1
1
  module CollavreGithub
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :collavre_github do
4
+ desc "Import markdown files from mock GitHub server into a creative tree"
5
+ task mock_import: :environment do
6
+ puts "=== GitHub Markdown Mock Import ==="
7
+ puts ""
8
+
9
+ # 1. Find or create user
10
+ user = User.first
11
+ abort "No user found. Run db:seed first." unless user
12
+ puts "User: #{user.name} (#{user.email})"
13
+
14
+ # 2. Find or create GitHub account (mock)
15
+ account = CollavreGithub::Account.find_or_initialize_by(user: user)
16
+ if account.new_record?
17
+ account.assign_attributes(
18
+ github_uid: "mock-12345",
19
+ login: "dev-user",
20
+ name: "Dev User (Mock)",
21
+ token: "mock-token-#{SecureRandom.hex(10)}"
22
+ )
23
+ account.save!
24
+ puts "Created mock GitHub account: #{account.login}"
25
+ else
26
+ puts "Using existing GitHub account: #{account.login}"
27
+ end
28
+
29
+ # 3. Find or create a root creative for the import
30
+ repo_name = ENV.fetch("MOCK_REPO", "dev-user/my-app")
31
+ root = Collavre::Creative.find_by(description: "GitHub Docs")
32
+ unless root
33
+ parent = Collavre::Creative.roots.first
34
+ root = Collavre::Creative.create!(
35
+ description: "GitHub Docs",
36
+ parent: parent,
37
+ user: user
38
+ )
39
+ puts "Created root creative: #{root.id} — 'GitHub Docs'"
40
+ end
41
+
42
+ # 4. Clean up existing sync (if re-running)
43
+ existing_link = root.github_repository_links.find_by(
44
+ github_account: account,
45
+ repository_full_name: repo_name
46
+ )
47
+ if existing_link
48
+ puts "Cleaning up existing sync..."
49
+ # Archive old markdown tree
50
+ if existing_link.markdown_root_creative
51
+ existing_link.markdown_root_creative.descendants.each do |c|
52
+ c.destroy if c.data.is_a?(Hash) && c.data.dig("source", "type") == "github_markdown"
53
+ end
54
+ existing_link.markdown_root_creative.destroy
55
+ end
56
+ existing_link.update!(markdown_root_creative_id: nil, last_synced_at: nil)
57
+ end
58
+
59
+ # 5. Create or reuse RepositoryLink
60
+ link = root.github_repository_links.find_or_create_by!(
61
+ github_account: account,
62
+ repository_full_name: repo_name
63
+ )
64
+ link.update!(markdown_sync_enabled: true, sync_branch: "main")
65
+ puts "RepositoryLink: #{link.id} — #{repo_name} (markdown_sync: enabled)"
66
+
67
+ # 6. Run InitialImportService
68
+ puts ""
69
+ puts "Starting import from mock server..."
70
+ puts "(Make sure mock server is running: bin/rails collavre_github:mock_server)"
71
+ puts ""
72
+
73
+ begin
74
+ result = CollavreGithub::MarkdownSync::InitialImportService.new(
75
+ repository_link: link,
76
+ user: user
77
+ ).call
78
+
79
+ if result
80
+ puts ""
81
+ puts "✅ Import complete!"
82
+ puts " Created #{result.size} creatives"
83
+ puts " Root creative: #{link.reload.markdown_root_creative_id}"
84
+ puts " Last synced: #{link.last_synced_at}"
85
+ puts ""
86
+ puts " Open the app and navigate to the 'GitHub Docs' creative to see the tree."
87
+ else
88
+ puts "⚠️ No markdown files found in the repository."
89
+ end
90
+ rescue StandardError => e
91
+ puts "❌ Import failed: #{e.message}"
92
+ puts e.backtrace.first(5).join("\n")
93
+ puts ""
94
+ puts "Is the mock server running? Start it with:"
95
+ puts " bin/rails collavre_github:mock_server"
96
+ end
97
+ end
98
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collavre_github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Collavre
@@ -66,10 +66,16 @@ files:
66
66
  - app/controllers/collavre_github/auth_controller.rb
67
67
  - app/controllers/collavre_github/creatives/integrations_controller.rb
68
68
  - app/controllers/collavre_github/webhooks_controller.rb
69
+ - app/javascript/collavre_github.js
70
+ - app/jobs/collavre_github/initial_markdown_sync_job.rb
71
+ - app/jobs/collavre_github/markdown_sync_job.rb
69
72
  - app/models/collavre_github/account.rb
70
73
  - app/models/collavre_github/application_record.rb
71
74
  - app/models/collavre_github/repository_link.rb
72
75
  - app/services/collavre_github/client.rb
76
+ - app/services/collavre_github/markdown_sync/content_processor.rb
77
+ - app/services/collavre_github/markdown_sync/incremental_sync_service.rb
78
+ - app/services/collavre_github/markdown_sync/initial_import_service.rb
73
79
  - app/services/collavre_github/tools/concerns/github_client_finder.rb
74
80
  - app/services/collavre_github/tools/github_pr_commits_service.rb
75
81
  - app/services/collavre_github/tools/github_pr_details_service.rb
@@ -84,10 +90,13 @@ files:
84
90
  - db/migrate/20250927000000_add_webhook_secret_to_github_repository_links.rb
85
91
  - db/migrate/20250928105957_add_github_gemini_prompt_to_creatives.rb
86
92
  - db/migrate/20260219095224_remove_github_gemini_prompt_from_creatives.rb
93
+ - db/migrate/20260412000000_add_markdown_sync_to_repository_links.rb
94
+ - db/migrate/20260416000000_add_markdown_root_creative_index.rb
87
95
  - db/seeds.rb
88
96
  - lib/collavre_github.rb
89
97
  - lib/collavre_github/engine.rb
90
98
  - lib/collavre_github/version.rb
99
+ - lib/tasks/mock_import.rake
91
100
  - lib/tasks/mock_server.rake
92
101
  homepage: https://collavre.com
93
102
  licenses: