ace-git 0.27.0 → 0.28.0

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: 8f05486971c36b968a3eeeb42f4bfdeda24b0a3d672732dd5ff532ab4a7db034
4
- data.tar.gz: 21fe708e731585aba811f719acc8705b906b2c2e11cf249f9d5279223890ea69
3
+ metadata.gz: f2aefd55e04cf20182ce9302454f857fb836a9948f8c5d3287d574fda05e73d0
4
+ data.tar.gz: 630a48152d3aaa43df4d6ec23dac65f6f2496fb1ea4fa7b4dbe968a677843751
5
5
  SHA512:
6
- metadata.gz: a4439500ea545b8c557af9e6b436852b14bebec56f4e44b4f36c72c005851d72d29256cef3a70fcff6de50900bc2e101d5f55ef93a7b48c850b69c200157ddca
7
- data.tar.gz: 705d2d95b952af1c2bd44a8da79b1173210b00313744c3dbd554b9d22d76983534b5db3552655a8fd797584accc4c774b205bb5710cb8e8b0fd61ddddf0fc80e
6
+ metadata.gz: 38abefdfea8dc06b4b30804daaa0b9e9327a3d9042c6671c6bae876896bfc8473c5f364444142726008d49d91c50d6ad7bb4cdb8e92243f1f0c515c050030a77
7
+ data.tar.gz: 760780054d64d4cd58134ab8c6e3db5a47a8daf45dbc7080195e716a5a55b17535b986f0dbc7d383bedc2108a87e27aa3c2b8fd2bdde7ff1834654240839f2b2
data/CHANGELOG.md CHANGED
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.28.0] - 2026-10-04
11
+
12
+ ### Added
13
+ - PR receipts include merge-commit proof and `pr` JSON failures carry the classified error category on stdout (parseable non-success; text and nonzero exit unchanged).
14
+
10
15
  ## [0.27.0] - 2026-10-03
11
16
 
12
17
  ### Added
data/docs/usage.md CHANGED
@@ -199,6 +199,18 @@ ace-git pr merge 25 --expected-head SHA --method squash
199
199
  - A create request whose outcome is unknown (transport failure after send)
200
200
  reports an unknown outcome with the exact identity to reconcile; it never
201
201
  retries automatically.
202
+ - With `--format json`, a failed operation prints the classified error as
203
+ JSON on stdout (`{"error": {"category": ..., "message": ...}}` — e.g.
204
+ `expected_head_conflict`, `unsupported_capability`, `unknown_outcome`)
205
+ before the nonzero exit; text mode explains the same failure on stderr.
206
+
207
+ Provider notes (Forgejo): the delivery lifecycle rides the repository-bound
208
+ Forgejo API v1 and requires Forgejo >= 8.0 (probed before mutations; the
209
+ provider refuses below the documented capability floor). Drafts use the
210
+ forge's WIP-title convention (`draft: true` creates a `WIP:`-prefixed
211
+ title; `pr ready` strips it and proves the ready state by read-back).
212
+ Same-server fork sources are supported via the declared `--head-repo`
213
+ URL; cross-host sources refuse before any mutation.
202
214
 
203
215
  ### `ace-git version`
204
216
 
@@ -290,7 +302,7 @@ Both providers implement the same issue-tracking contract (issue lookup, comment
290
302
  create/update/delete, label add/remove, state transitions) so task issue
291
303
  synchronization stays forge-neutral; `ace-task` owns the sync orchestration.
292
304
 
293
- Configure servers in `.ace/git.yml` (or project config) under `git.servers`, then
305
+ Configure servers in `.ace/git/config.yml` under `git.servers`, then
294
306
  resolve them by name, by default, or from a git remote URL. Every failure path is
295
307
  classified (missing CLI, unauthenticated, unreachable, malformed output, object
296
308
  not found) with no silent fallbacks.
@@ -13,7 +13,9 @@ module Ace
13
13
  # (mutually exclusive; remote resolution when neither is given) and
14
14
  # `--format json`. Success output carries the resolved server,
15
15
  # provider, and exact PR identity; failures exit nonzero with the
16
- # classified provider error and never claim success.
16
+ # classified provider error and never claim success. JSON failures
17
+ # put the error category and message on stdout so machine callers
18
+ # can parse the classification; text goes to stderr via the runner.
17
19
  module Pr
18
20
  # Shared plumbing for all pr subcommands.
19
21
  class BaseCommand < Ace::Support::Cli::Command
@@ -24,6 +26,19 @@ module Ace
24
26
  option :remote, type: :string, desc: "Git remote used for server resolution when nothing is selected"
25
27
  option :format, type: :string, default: "text", desc: "Output format: text, json"
26
28
 
29
+ ERROR_CATEGORIES = {
30
+ "ProviderAuthenticationError" => "authentication",
31
+ "ProviderUnreachableError" => "unreachable",
32
+ "ProviderMalformedOutputError" => "malformed",
33
+ "ProviderObjectNotFoundError" => "not_found",
34
+ "ProviderCliMissingError" => "cli_missing",
35
+ "ProviderIdentityMismatchError" => "identity_mismatch",
36
+ "ProviderConflictingMatchesError" => "conflicting_matches",
37
+ "ProviderExpectedHeadConflictError" => "expected_head_conflict",
38
+ "ProviderUnsupportedCapabilityError" => "unsupported_capability",
39
+ "ProviderUnknownOutcomeError" => "unknown_outcome"
40
+ }.freeze
41
+
27
42
  private
28
43
 
29
44
  def lifecycle(options)
@@ -47,6 +62,18 @@ module Ace
47
62
  end
48
63
  end
49
64
 
65
+ # JSON mode keeps the classified failure parseable on stdout;
66
+ # the human-readable line still reaches stderr through the
67
+ # raised Cli::Error with a nonzero exit.
68
+ def render_failure(options, error)
69
+ return unless options[:format] == "json"
70
+
71
+ puts JSON.pretty_generate(
72
+ error: {category: ERROR_CATEGORIES.fetch(error.class.name.split("::").last, "error"),
73
+ message: error.message}
74
+ )
75
+ end
76
+
50
77
  def format_value(value)
51
78
  case value
52
79
  when Hash
@@ -73,7 +100,8 @@ module Ace
73
100
  head_ref: pr.head_ref,
74
101
  head_repository: pr.head_repository_url,
75
102
  base_ref: pr.base_ref,
76
- base_repository: pr.base_repository_url
103
+ base_repository: pr.base_repository_url,
104
+ merge_commit: pr.merge_commit_sha
77
105
  )
78
106
  end
79
107
  end
@@ -103,6 +131,7 @@ module Ace
103
131
  merge_commit: pr.merge_commit_sha
104
132
  )
105
133
  rescue Ace::Git::Error, ArgumentError => e
134
+ render_failure(options, e)
106
135
  raise Ace::Support::Cli::Error.new(e.message)
107
136
  end
108
137
  end
@@ -131,6 +160,7 @@ module Ace
131
160
  )
132
161
  emit_receipt(options, "created", receipt)
133
162
  rescue Ace::Git::Error, ArgumentError => e
163
+ render_failure(options, e)
134
164
  raise Ace::Support::Cli::Error.new(e.message)
135
165
  end
136
166
  end
@@ -153,6 +183,7 @@ module Ace
153
183
  )
154
184
  emit_receipt(options, "updated", receipt)
155
185
  rescue Ace::Git::Error, ArgumentError => e
186
+ render_failure(options, e)
156
187
  raise Ace::Support::Cli::Error.new(e.message)
157
188
  end
158
189
  end
@@ -168,6 +199,7 @@ module Ace
168
199
  receipt = lifecycle(options).ready(identifier, expected_head: expected_head)
169
200
  emit_receipt(options, "readied", receipt)
170
201
  rescue Ace::Git::Error, ArgumentError => e
202
+ render_failure(options, e)
171
203
  raise Ace::Support::Cli::Error.new(e.message)
172
204
  end
173
205
  end
@@ -184,6 +216,7 @@ module Ace
184
216
  receipt = lifecycle(options).merge(identifier, expected_head: expected_head, method: method)
185
217
  emit_receipt(options, "merged", receipt)
186
218
  rescue Ace::Git::Error, ArgumentError => e
219
+ render_failure(options, e)
187
220
  raise Ace::Support::Cli::Error.new(e.message)
188
221
  end
189
222
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module Git
5
- VERSION = "0.27.0"
5
+ VERSION = "0.28.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-git
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 0.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-10-03 00:00:00.000000000 Z
10
+ date: 2026-10-04 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-support-config