Module: Mighost::API

Defined in:
lib/mighost/api.rb

Overview

Public API for programmatic access. This is the stable interface for external consumers (e.g. railbow).

Class Method Summary collapse

Class Method Details

.all_snapshots(limit: nil) ⇒ Object

Returns [Snapshot]



36
37
38
39
# File 'lib/mighost/api.rb', line 36

def all_snapshots(limit: nil)
  records = Snapshot.all_snapshots
  limit&.positive? ? records.first(limit) : records
end

.dismiss(version) ⇒ Object



143
144
145
# File 'lib/mighost/api.rb', line 143

def dismiss(version)
  Snapshot.dismiss(version)
end

.dismissed_countObject



151
152
153
# File 'lib/mighost/api.rb', line 151

def dismissed_count
  Snapshot.dismissed_versions.count
end

.find_or_recover_snapshot(version) ⇒ Object

Returns Snapshot (with git/worktree fallback) or nil



31
32
33
# File 'lib/mighost/api.rb', line 31

def find_or_recover_snapshot(version)
  Snapshot.find_or_recover(version)
end

.find_snapshot(version) ⇒ Object

Returns Snapshot or nil



26
27
28
# File 'lib/mighost/api.rb', line 26

def find_snapshot(version)
  Snapshot.find_by_version(version)
end

.orphaned_migrations(include_dismissed: false) ⇒ Object

Returns [OrphanedMigration]



21
22
23
# File 'lib/mighost/api.rb', line 21

def orphaned_migrations(include_dismissed: false)
  OrphanDetector.detect(include_dismissed: include_dismissed)
end

.rollback_version!(version) ⇒ Object

Executes rollback. Raises SnapshotNotFound or RollbackFailed on failure.



42
43
44
# File 'lib/mighost/api.rb', line 42

def rollback_version!(version)
  Rollbacker.rollback_version!(version)
end

.scan!(rescan: false) ⇒ Object

Scan: capture files, search git, search worktrees. Returns git_recovered:, worktree_recovered:, branch:, sha:, details:[]



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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/mighost/api.rb', line 48

def scan!(rescan: false)
  migration_paths = if defined?(Rails) && Rails.application
    Rails.application.config.paths["db/migrate"].to_ary
  else
    ["db/migrate"]
  end

  migrated_versions = Mighost::Base.connection
    .select_values("SELECT version FROM schema_migrations")
    .map(&:to_s)

  captured = 0
  git_recovered = 0
  worktree_recovered = 0
  details = []

  # Phase 1: Capture existing migration files
  migration_paths.each do |path|
    Dir.glob(File.join(path, "*.rb")).each do |file|
      basename = File.basename(file)
      version = basename.split("_").first

      next unless migrated_versions.include?(version)
      next if !rescan && Snapshot.find_by_version(version)

      Capturer.new(version, file).capture
      details << {type: :captured, filename: basename}
      captured += 1
    end
  end

  # Phase 2: Search git for orphaned migrations
  orphan_versions = migrated_versions.reject do |version|
    migration_paths.any? { |p| Dir.glob(File.join(p, "#{version}_*.rb")).any? }
  end

  orphan_versions.each do |version|
    existing = Snapshot.find_by_version(version)
    next if !rescan && existing&.source.present?

    git_data = GitRecovery.find_migration(version)
    next unless git_data

    Snapshot.store(
      version: version,
      content: git_data[:content],
      filename: git_data[:filename],
      branch_name: git_data[:branch],
      git_sha: git_data[:sha],
      source: "git",
      author_name: git_data[:author_name],
      author_email: git_data[:author_email]
    )
    details << {type: :git_recovered, filename: git_data[:filename], branch: git_data[:branch]}
    git_recovered += 1
  end

  # Phase 3: Search worktrees for uncommitted migrations
  remaining_orphans = orphan_versions.reject do |version|
    existing = Snapshot.find_by_version(version)
    !rescan && existing&.source.present?
  end

  remaining_orphans.each do |version|
    wt_data = WorktreeRecovery.find_migration(version)
    next unless wt_data

    Snapshot.store(
      version: version,
      content: wt_data[:content],
      filename: wt_data[:filename],
      branch_name: wt_data[:branch],
      source: "worktree",
      author_name: wt_data[:author_name],
      author_email: wt_data[:author_email]
    )
    details << {type: :worktree_recovered, filename: wt_data[:filename], branch: wt_data[:branch]}
    worktree_recovered += 1
  end

  # Store scan metadata
  branch = GitMetadata.current_branch
  sha = GitMetadata.current_sha
  Snapshot.(branch: branch, sha: sha)

  {
    captured: captured,
    git_recovered: git_recovered,
    worktree_recovered: worktree_recovered,
    branch: branch,
    sha: sha,
    details: details
  }
end

.undismiss(version) ⇒ Object



147
148
149
# File 'lib/mighost/api.rb', line 147

def undismiss(version)
  Snapshot.undismiss(version)
end