gitbroker 0.6.3 → 0.6.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f6274054ed60618fb8616a0749d40c1b4cb52ca6e404c1e6cf7db5680974f3a
4
- data.tar.gz: 6804bcf3df622af5f6e3c28982c0f02253344030d17d2e7abf33386a53e0930f
3
+ metadata.gz: be4bff227a1a036f59d8124a89b2f6dc782dda63c5b6d471f7e51f9fde126e5d
4
+ data.tar.gz: c984663cf01008495cca098619d95e5476b57b6d9b8626c7bb047f20dee8f576
5
5
  SHA512:
6
- metadata.gz: cf810ab366134baa979fa36e90fe717e9651565c82456a52f18e2bb80e8a485cbdbaac654f17d92b91c9c0591d314402026beda26b7e213e9058cf88f012d8e1
7
- data.tar.gz: 1af26124d306502ac9f731538e40604d1b948cd8147dd9ce23ddd5aa1e50a462273be93a00d79d7640ebd2a00fa8d29d6a206fbf353e172701cb912ddbf8189e
6
+ metadata.gz: 0ec15dc9d6642178cf85e8ba9ddc874b6662af3e88f0106d45797c1839a4baf62bce28e16261f28acdb1124b4fb056f46001804bd846e082681a0d9f9a2b2aac
7
+ data.tar.gz: b3b4fb6d648a3bb7e9cf0e4fdc5032da58b6794df9eae5adbc62eb8606145d2317beabbc7bbee2c043f2076470908e07e0bd015ff36bfa9c5d15400c22027251
@@ -14,16 +14,17 @@ module Gitbroker
14
14
 
15
15
  REF = %r{\A\w[\w./-]{0,200}\z}
16
16
 
17
- def initialize(dir:, head_ref:, expected_sha:, base_ref:, runner: Runner.new)
17
+ def initialize(dir:, head_ref:, expected_sha:, base_ref:, remote: "origin", runner: Runner.new)
18
18
  @dir = dir
19
19
  @head_ref = head_ref.to_s
20
20
  @expected = expected_sha.to_s
21
21
  @base_ref = base_ref.to_s
22
+ @remote = remote.to_s
22
23
  @runner = runner
23
24
  end
24
25
 
25
26
  def publish!
26
- return failed("No branch name to push.") unless valid_ref?(@head_ref) && valid_ref?(@base_ref)
27
+ return failed("No branch name to push.") unless valid_ref?(@head_ref) && valid_ref?(@base_ref) && valid_ref?(@remote)
27
28
  return failed("No starting head to protect.") unless @expected.match?(/\A[0-9a-f]{7,40}\z/)
28
29
  return failed("A rebase or merge is still in progress in the worktree: finish it first.") if in_progress?
29
30
  return failed("The worktree has uncommitted changes.") unless git("status", "--porcelain").strip.empty?
@@ -31,16 +32,16 @@ module Gitbroker
31
32
  head = git("rev-parse", "HEAD").strip
32
33
  return Result.new(:nothing, "Nothing to push: the branch did not change.") if head.start_with?(@expected) || @expected.start_with?(head)
33
34
 
34
- git("fetch", "--quiet", "origin", @base_ref)
35
- unless @runner.git_success?(@dir, "merge-base", "--is-ancestor", "origin/#{@base_ref}", "HEAD")
36
- return failed("The branch is not on top of origin/#{@base_ref}: nothing pushed.")
35
+ git("fetch", "--quiet", @remote, @base_ref)
36
+ unless @runner.git_success?(@dir, "merge-base", "--is-ancestor", "#{@remote}/#{@base_ref}", "HEAD")
37
+ return failed("The branch is not on top of #{@remote}/#{@base_ref}: nothing pushed.")
37
38
  end
38
39
  unless git("rev-list", "--merges", "#{@expected}..HEAD").strip.empty?
39
40
  return failed("The branch contains merge commits; it must be a clean rebase: nothing pushed.")
40
41
  end
41
42
 
42
- git("push", lease_option, "origin", "HEAD:refs/heads/#{@head_ref}")
43
- Result.new(:pushed, "Pushed #{@head_ref} rebased onto origin/#{@base_ref}.")
43
+ git("push", lease_option, @remote, "HEAD:refs/heads/#{@head_ref}")
44
+ Result.new(:pushed, "Pushed #{@head_ref} rebased onto #{@remote}/#{@base_ref}.")
44
45
  rescue Error => e
45
46
  failed("Push failed: #{e.message.lines.first.to_s.strip}")
46
47
  end
data/lib/gitbroker/cli.rb CHANGED
@@ -111,10 +111,25 @@ module Gitbroker
111
111
  end
112
112
 
113
113
  return run_daemon if foreground
114
+ return set_up_separate_instance(options[:name] || Socket.gethostname) if separate_instance?
114
115
 
115
116
  set_up(options[:name] || Socket.gethostname)
116
117
  end
117
118
 
119
+ # A GITBROKER_CONFIG_DIR that is not the default is another companion (say, one for a local dev server). The background
120
+ # service belongs to the default one, so this one is paired and then kept in this window; it never touches the service.
121
+ def separate_instance?
122
+ custom = @env["GITBROKER_CONFIG_DIR"]
123
+ custom && File.expand_path(custom) != File.expand_path(Config.default_dir(@env.reject { |key, _| key == "GITBROKER_CONFIG_DIR" }))
124
+ end
125
+
126
+ def set_up_separate_instance(name)
127
+ Login.new(config:, out: @out, name:).run unless config.paired?
128
+ @out.puts "This companion uses its own settings (#{config.dir}), so the background service is left alone. Keeping it in this " \
129
+ "window, connected to #{config.server}; press Ctrl-C to stop it."
130
+ run_daemon
131
+ end
132
+
118
133
  def run_daemon
119
134
  raise Error, "This machine is not paired. Run `gitbroker start` in a terminal to pair it." unless config.paired?
120
135
 
@@ -304,6 +319,7 @@ module Gitbroker
304
319
  parser.on("--head-ref REF") { options[:head_ref] = _1 }
305
320
  parser.on("--expected SHA") { options[:expected_sha] = _1 }
306
321
  parser.on("--base REF") { options[:base_ref] = _1 }
322
+ parser.on("--remote NAME") { options[:remote] = _1 }
307
323
  end.parse!(@argv)
308
324
  result = BranchPublisher.new(**options).publish!
309
325
  @out.puts result.message
@@ -61,6 +61,16 @@ module Gitbroker
61
61
  end
62
62
  end
63
63
 
64
+ # The remote that is `full_name` on GitHub (origin first when several are): a checkout found through its `github` remote
65
+ # has an origin that is something else, so fetching and pushing must name the remote, never assume origin.
66
+ def remote_for(dir, full_name)
67
+ wanted = full_name.to_s.downcase
68
+ matches = remote_urls(dir).select { |_name, url| RepoScanner.full_name_from(url).to_s.downcase == wanted }.map(&:first)
69
+ (matches.include?("origin") ? "origin" : matches.find { _1.match?(REMOTE_NAME) }) || "origin"
70
+ end
71
+
72
+ REMOTE_NAME = /\A\w[\w.-]{0,60}\z/
73
+
64
74
  def repository_from(remotes)
65
75
  remotes.sort_by { |name, _url| name == "origin" ? 0 : 1 }.lazy.filter_map { |_name, url| RepoScanner.full_name_from(url) }.first
66
76
  end
@@ -17,13 +17,13 @@ module Gitbroker
17
17
  @runner = runner
18
18
  end
19
19
 
20
- def neutralize!(dir, repo_path:, number:, base_ref:)
20
+ def neutralize!(dir, repo_path:, number:, base_ref:, remote: "origin")
21
21
  raise Error, "Invalid base branch #{base_ref.inspect}" unless Worktree.valid_ref?(base_ref)
22
22
  raise Error, "Invalid PR number #{number.inspect}" unless number.to_s.match?(/\A[1-9]\d{0,9}\z/)
23
23
 
24
24
  @dir = File.realpath(dir)
25
25
  base = "refs/gitbroker/base-#{number}"
26
- @runner.git(repo_path, "fetch", "--quiet", "origin", "+refs/heads/#{base_ref}:#{base}")
26
+ @runner.git(repo_path, "fetch", "--quiet", remote, "+refs/heads/#{base_ref}:#{base}")
27
27
 
28
28
  removed = paths(@runner.git(@dir, "ls-files", "-z", "--", *REMOVE))
29
29
  removed.each { delete(_1) }
@@ -58,7 +58,7 @@ module Gitbroker
58
58
  cross_repository: task["cross_repository"] == true)
59
59
  # Agents report real paths (macOS: /private/var, not /var); progress paths are matched against this form.
60
60
  dir = File.realpath(dir)
61
- restored = task["untrusted"] ? @neutralizer.neutralize!(dir, repo_path:, number: task["pr_number"], base_ref: base_ref(task)) : []
61
+ restored = task["untrusted"] ? @neutralizer.neutralize!(dir, repo_path:, number: task["pr_number"], base_ref: base_ref(task), remote: GitContext.remote_for(repo_path, task["repo"])) : []
62
62
  task = task.merge("prompt" => prompt_for(task))
63
63
  agent = Agents.for(@config, worktree: dir)
64
64
  say(id, "#{task["kind"]} on #{task["repo"]}##{task["pr_number"]}: starting (#{agent.name}, #{task["mode"] == "terminal" ? "terminal" : "autonomous"})")
@@ -143,7 +143,8 @@ module Gitbroker
143
143
  def publish_branch(task, outcome, dir)
144
144
  return outcome unless publishes_branch?(task)
145
145
 
146
- result = BranchPublisher.new(dir:, head_ref: task["head_ref"], expected_sha: task["head_sha"], base_ref: base_ref(task)).publish!
146
+ result = BranchPublisher.new(dir:, head_ref: task["head_ref"], expected_sha: task["head_sha"], base_ref: base_ref(task),
147
+ remote: GitContext.remote_for(dir, task["repo"])).publish!
147
148
  say(task["task_id"], result.message)
148
149
  return outcome unless result.failed?
149
150
 
@@ -155,7 +156,7 @@ module Gitbroker
155
156
  return unless publishes_branch?(task)
156
157
 
157
158
  [ RbConfig.ruby, ServiceInstaller.launcher, "publish-branch", "--dir", dir, "--head-ref", task["head_ref"].to_s,
158
- "--expected", task["head_sha"].to_s, "--base", base_ref(task) ]
159
+ "--expected", task["head_sha"].to_s, "--base", base_ref(task), "--remote", GitContext.remote_for(dir, task["repo"]) ]
159
160
  end
160
161
 
161
162
  def publishes_branch?(task) = task["kind"] == "update_branch" && task["cross_repository"] != true && !task["read_only"]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gitbroker
4
- VERSION = "0.6.3"
4
+ VERSION = "0.6.5"
5
5
  end
@@ -24,7 +24,8 @@ module Gitbroker
24
24
  validate!(full_name:, number:, head_sha:, kind:)
25
25
  dir = File.join(@root, full_name.downcase.tr("/", "-"), "pr-#{number}-#{kind}")
26
26
 
27
- @runner.git(repo_path, "fetch", "--quiet", "origin", "+refs/pull/#{number}/head:refs/gitbroker/pr-#{number}")
27
+ remote = GitContext.remote_for(repo_path, full_name)
28
+ @runner.git(repo_path, "fetch", "--quiet", remote, "+refs/pull/#{number}/head:refs/gitbroker/pr-#{number}")
28
29
  unless @runner.git_success?(repo_path, "cat-file", "-e", "#{head_sha}^{commit}")
29
30
  raise Error, "Head #{head_sha[0, 7]} is not in the fetched PR; the PR may have moved. Start the task again from the card."
30
31
  end
@@ -41,7 +42,7 @@ module Gitbroker
41
42
  @runner.git(repo_path, "worktree", "add", "--quiet", *target, dir, head_sha)
42
43
  end
43
44
  if branch
44
- cross_repository ? drop_upstream(repo_path, local) : track_upstream(repo_path, local, head_ref)
45
+ cross_repository ? drop_upstream(repo_path, local) : track_upstream(repo_path, local, head_ref, remote)
45
46
  end
46
47
  dir
47
48
  end
@@ -93,11 +94,11 @@ module Gitbroker
93
94
  raise Error, "Branch #{local} has commits that are not on the PR head; push or delete it, then start the task again."
94
95
  end
95
96
 
96
- def track_upstream(repo_path, local, head_ref)
97
+ def track_upstream(repo_path, local, head_ref, remote)
97
98
  return unless self.class.valid_ref?(head_ref)
98
- return unless @runner.git_success?(repo_path, "fetch", "--quiet", "origin", "+refs/heads/#{head_ref}:refs/remotes/origin/#{head_ref}")
99
+ return unless @runner.git_success?(repo_path, "fetch", "--quiet", remote, "+refs/heads/#{head_ref}:refs/remotes/#{remote}/#{head_ref}")
99
100
 
100
- @runner.git(repo_path, "branch", "--quiet", "--set-upstream-to=origin/#{head_ref}", local)
101
+ @runner.git(repo_path, "branch", "--quiet", "--set-upstream-to=#{remote}/#{head_ref}", local)
101
102
  end
102
103
 
103
104
  def drop_upstream(repo_path, local)
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "gitbroker",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "Skills for working on Git Broker agent tasks: the gitbroker MCP tools, write rules and report_task."
5
5
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitbroker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuri Sidorov (@newstler)