ace-git 0.32.0 → 0.33.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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 183166f8ce864a5503f765212e4a0a89e26ec22f03dca7ab8a918c9499ec064a
|
|
4
|
+
data.tar.gz: 5c3eaa10c29b1873bf504cecaff12ac77806740f1bf1ee1e3c8372081c9d18e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21397a89baadadc17c0c18ce73c3fb558a6195133381e6f26df5e4ab897e025cff8aaa563b2cb6169400d8a5a7f43c2ff7c8549d6af261389d0690ba40c35fef
|
|
7
|
+
data.tar.gz: 2067ddf2e8871231ed33e0392aa922a429114b68c25dd9c3fe914c3d88d0df185ecc3ebebb2b4f9a1433a9a882c9c6aa147978616a2c03c31a2967508fd3e790
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to ace-git will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.33.0] - 2026-11-10
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Include PR authors and semantic issue bodies in provider evidence. Verify scoped formal reviewer identity and exact HEAD; reject oversized or invalid UTF-8 PR bodies instead of truncating them.
|
|
8
15
|
## [0.32.0] - 2026-10-30
|
|
9
16
|
|
|
10
17
|
### Added
|
|
@@ -363,7 +363,14 @@ module Ace
|
|
|
363
363
|
raise ArgumentError, "--body-file is required" unless path
|
|
364
364
|
raise ArgumentError, "Body file not found: #{path}" unless File.file?(path)
|
|
365
365
|
|
|
366
|
-
File.
|
|
366
|
+
body = File.binread(path, limit) || +""
|
|
367
|
+
if limit && body.bytesize >= limit
|
|
368
|
+
raise ArgumentError, "Body file exceeds #{limit - 1} bytes: #{path}"
|
|
369
|
+
end
|
|
370
|
+
body.force_encoding(Encoding::UTF_8)
|
|
371
|
+
raise ArgumentError, "Body file must contain valid UTF-8: #{path}" unless body.valid_encoding?
|
|
372
|
+
|
|
373
|
+
body
|
|
367
374
|
rescue SystemCallError => e
|
|
368
375
|
raise ArgumentError, "Cannot read body file #{path}: #{e.message}"
|
|
369
376
|
end
|
|
@@ -16,7 +16,11 @@ module Ace
|
|
|
16
16
|
:head_repository_url, :base_repository_url, :merge_commit_sha
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
-
ProviderIssue = Data.define(:server_name, :number, :title, :state, :author, :url, :labels)
|
|
19
|
+
ProviderIssue = Data.define(:server_name, :number, :title, :state, :author, :url, :labels, :body) do
|
|
20
|
+
def initialize(body: nil, **fields)
|
|
21
|
+
super(body: body, **fields)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
20
24
|
|
|
21
25
|
# Normalized check/CI evidence for one check run.
|
|
22
26
|
ProviderCheck = Data.define(:server_name, :name, :state, :conclusion, :url)
|
|
@@ -16,9 +16,10 @@ module Ace
|
|
|
16
16
|
CORRELATION = /\A[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}\z/
|
|
17
17
|
MARKER = /\n\n<!-- ace-approval:([a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}) sha256:([0-9a-f]{64}) -->\z/
|
|
18
18
|
|
|
19
|
-
def initialize(provider:, request:, list:, official: false, pending_reuse: false)
|
|
19
|
+
def initialize(provider:, request:, list:, official: false, pending_reuse: false, expected_reviewer: nil)
|
|
20
20
|
@provider, @request, @list, @official = provider, request, list, official
|
|
21
21
|
@pending_reuse = pending_reuse
|
|
22
|
+
@expected_reviewer = expected_reviewer
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def approve(number:, expected_head:, body:, correlation:)
|
|
@@ -44,7 +45,7 @@ module Ace
|
|
|
44
45
|
end
|
|
45
46
|
lock.flock(File::LOCK_EX)
|
|
46
47
|
pr = current!(number, expected_head)
|
|
47
|
-
actor = identity!(@request.call(:get, :actor, nil))
|
|
48
|
+
actor = @expected_reviewer ? [nil, @expected_reviewer] : identity!(@request.call(:get, :actor, nil))
|
|
48
49
|
deny_author!(pr, actor)
|
|
49
50
|
rows = reviews!(number)
|
|
50
51
|
matches = rows.select { |row| row.fetch("body").include?("<!-- ace-approval:#{correlation} ") }
|
|
@@ -52,14 +53,18 @@ module Ace
|
|
|
52
53
|
existing = matches.first
|
|
53
54
|
row!(existing) if existing
|
|
54
55
|
if existing && (existing["body"] != sent_body || existing["commit_id"] != expected_head ||
|
|
55
|
-
identity!(existing["user"])
|
|
56
|
+
!matches_actor?(actor, identity!(existing["user"])))
|
|
56
57
|
raise ProviderConflictingMatchesError, "Approval correlation is already bound to different evidence"
|
|
57
58
|
end
|
|
58
59
|
# A provider may reuse its current pending object on direct create.
|
|
59
60
|
# Only an exact known, comment-free pending review is resumable, and
|
|
60
61
|
# only when the adapter proves explicit commit preservation on reuse.
|
|
61
62
|
owned_pending = rows.select do |row|
|
|
62
|
-
row["state"] == "PENDING"
|
|
63
|
+
next false unless row["state"] == "PENDING"
|
|
64
|
+
|
|
65
|
+
# A repository-scoped Forgejo token can only see its own
|
|
66
|
+
# pending reviews. Preserve every visible unrelated pending.
|
|
67
|
+
@expected_reviewer || (row["user"].is_a?(Hash) && row["user"]["id"] == actor.first)
|
|
63
68
|
end
|
|
64
69
|
unrelated = owned_pending.any? { |row| !existing || row["id"] != existing["id"] }
|
|
65
70
|
if unrelated
|
|
@@ -140,6 +145,10 @@ module Ace
|
|
|
140
145
|
[user["id"], user["login"]]
|
|
141
146
|
end
|
|
142
147
|
|
|
148
|
+
def matches_actor?(expected, actual)
|
|
149
|
+
expected.first ? expected == actual : expected.last.casecmp?(actual.last)
|
|
150
|
+
end
|
|
151
|
+
|
|
143
152
|
def deny_author!(pr, actor)
|
|
144
153
|
unless pr.author.is_a?(String) && !pr.author.empty?
|
|
145
154
|
raise ProviderMalformedOutputError, "PR author is unverified"
|
|
@@ -199,7 +208,7 @@ module Ace
|
|
|
199
208
|
row["state"] == "APPROVED" && row["commit_id"] == expected_head &&
|
|
200
209
|
!row["dismissed"] && !row["stale"] && (!@official || row["official"] == true) &&
|
|
201
210
|
(!latest || latest["id"] == row["id"]) && (!expected_body || row["body"] == expected_body) &&
|
|
202
|
-
(!actor || actor
|
|
211
|
+
(!actor || matches_actor?(actor, actual_actor)) && row["html_url"].is_a?(String) &&
|
|
203
212
|
row["html_url"].start_with?("#{pr.url}#")
|
|
204
213
|
raise ProviderIdentityMismatchError, "Review is not the effective exact-head formal approval"
|
|
205
214
|
end
|
data/lib/ace/git/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.33.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michal Czyz
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10
|
|
10
|
+
date: 2026-11-10 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: ace-support-config
|