browser_review_gate 0.2.0 → 0.2.2

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: 7511e93bcb04cb1c8afa751bb179553eb29e70f4d0173e5c4b9fe899009f83ed
4
- data.tar.gz: 638a66f37095d8421b21528f5718e9a550644112cffdca8695b0978f7f9ff646
3
+ metadata.gz: '09d5a330baa46a948f70191ba4537ba0d5c7097ed8c6d89e497a5f872eb6e671'
4
+ data.tar.gz: 48b41886a6ebbd39bb67c62af4e1f19b5c9ae52ae3dea622dfdfe8c0708336f6
5
5
  SHA512:
6
- metadata.gz: 3bf5fba978609414d2a0a191bee336805ec9c8ce7923c94c1f4e44bb135037b1252d44c549a7a29961575f7a9776da2161ecbd5e23028d54ac281c4e5878425d
7
- data.tar.gz: 6b4350eb758928d89cb1ba3dd0b7da3e26b0c1d192c76b306bf30a600b2a9412b17066fcee02c9ce47717bc14a2869ead36bf5338e4d300bc73f2d760cb4fd62
6
+ metadata.gz: 19564cbe10913982e3bf22af716e9e147ce1a38ffa5dfa47035e0083cbecb9bc63f7f78789a97fe1776a1f51065a3ab900d1cdcf854f527f40ae4327f6029a8b
7
+ data.tar.gz: b33fe20d59959593e0bb9a881f047065a89700f6c9f30e8a3ffe7aa6d69574180ef7b714261301e05c399b6bb43afaffc8dd9dc8761c529ad256ac2dfc19f84f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.2
4
+
5
+ - Requires json 2.7 or newer. Ruby 3.2 ships json 2.6, which ignores `script_safe`, so PR text in the
6
+ assessment prompt was not escaped there.
7
+ - Links to the source code, changelog and issues.
8
+
9
+ ## 0.2.1
10
+
11
+ - A reviewer who approved or asked for changes on the latest commit while their request was paused
12
+ is not asked again once the browser run is published. The notice names them instead. Someone whose
13
+ review is on an older commit, or who only commented, is still asked again.
14
+
3
15
  ## 0.2.0
4
16
 
5
17
  Re-run `browser-review-gate install` after updating: the workflow and the playbook change.
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2026 JetRockets
3
+ Copyright (c) 2026 Islam Gagiev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -81,20 +81,39 @@ module BrowserReviewGate
81
81
  @log.puts "Took back reviewer requests until browser verification is available."
82
82
  end
83
83
 
84
- # Asks the people whose requests were taken back, now that review may proceed.
84
+ # Asks the people whose requests were taken back, now that review may proceed. Someone who
85
+ # reviewed the latest commit while the request was paused is not asked again.
85
86
  def restore_requests(number, pull_request, comments)
86
87
  waiting = paused(comments)
87
- reviewers = waiting["reviewers"] - [ pull_request.dig("user", "login") ]
88
- return if reviewers.empty? && waiting["teams"].empty?
88
+ waiting["reviewers"] -= [ pull_request.dig("user", "login") ]
89
+ return if waiting.values.all?(&:empty?)
89
90
 
90
- @github.request_reviewers(number, reviewers: reviewers, team_reviewers: waiting["teams"])
91
- write_notice(number, comments, "#{author(pull_request)}Review requested again from #{names(waiting)}: browser verification no longer holds it back.",
92
- "reviewers" => [], "teams" => [])
93
- @log.puts "Requested review again from #{names(waiting)}."
91
+ reviewed = reviewed_head(number, pull_request) & waiting["reviewers"]
92
+ asked = { "reviewers" => waiting["reviewers"] - reviewed, "teams" => waiting["teams"] }
93
+ unless asked.values.all?(&:empty?)
94
+ @github.request_reviewers(number, reviewers: asked["reviewers"], team_reviewers: asked["teams"])
95
+ end
96
+ write_notice(number, comments, "#{author(pull_request)}#{restored_notice(asked, reviewed)}", "reviewers" => [], "teams" => [])
97
+ @log.puts restored_notice(asked, reviewed)
94
98
  rescue Error => error
95
99
  @log.puts "Review was not requested again: #{error.message.lines.first.to_s.strip}"
96
100
  end
97
101
 
102
+ # People whose last review approved or asked for changes on the head commit.
103
+ def reviewed_head(number, pull_request)
104
+ head_sha = pull_request.fetch("head").fetch("sha")
105
+ last = @github.reviews(number).group_by { |review| review.dig("user", "login") }.transform_values(&:last)
106
+ last.select { |_login, review| review["commit_id"] == head_sha && %w[APPROVED CHANGES_REQUESTED].include?(review["state"]) }.keys
107
+ end
108
+
109
+ def restored_notice(asked, reviewed)
110
+ parts = []
111
+ parts << "Review requested again from #{names(asked)}: browser verification no longer holds it back." unless asked.values.all?(&:empty?)
112
+ parts << "#{reviewed.map { |name| Markdown.escape(name) }.join(", ")} already reviewed the latest commit, so " \
113
+ "#{reviewed.one? ? "was" : "were"} not asked again." if reviewed.any?
114
+ parts.join(" ")
115
+ end
116
+
98
117
  def notice_comment(comments)
99
118
  comments.reverse.find { |comment| comment.dig("user", "login") == Assessment::AUTHOR && comment["body"].to_s.match?(PAUSED) }
100
119
  end
@@ -92,6 +92,11 @@ module BrowserReviewGate
92
92
  input: { reviewers: reviewers, team_reviewers: team_reviewers })
93
93
  end
94
94
 
95
+ # Submitted reviews, oldest first.
96
+ def reviews(number)
97
+ pages("repos/#{repository}/pulls/#{number}/reviews")
98
+ end
99
+
95
100
  def request_reviewers(number, reviewers:, team_reviewers:)
96
101
  api("repos/#{repository}/pulls/#{number}/requested_reviewers", method: "POST",
97
102
  input: { reviewers: reviewers, team_reviewers: team_reviewers })
@@ -1,3 +1,3 @@
1
1
  module BrowserReviewGate
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,18 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browser_review_gate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
- - JetRockets
7
+ - Islam Gagiev
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: json
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '2.7'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '2.7'
12
26
  description: CI decides whether a pull request needs a browser run and takes back
13
27
  reviewer requests until an AI coding agent (Claude Code, Cursor, Codex) has exercised
14
28
  the change in a browser and published what it observed. One command sets a project
15
29
  up.
30
+ email:
31
+ - omniacinis@gmail.com
16
32
  executables:
17
33
  - browser-review-gate
18
34
  extensions: []
@@ -51,9 +67,16 @@ files:
51
67
  - lib/browser_review_gate/templates/workflow.yml.erb
52
68
  - lib/browser_review_gate/version.rb
53
69
  - lib/generators/browser_review_gate/install/install_generator.rb
70
+ homepage: https://github.com/Halvanhelv/browser_review_gate
54
71
  licenses:
55
72
  - MIT
56
- metadata: {}
73
+ metadata:
74
+ allowed_push_host: https://rubygems.org
75
+ homepage_uri: https://github.com/Halvanhelv/browser_review_gate
76
+ source_code_uri: https://github.com/Halvanhelv/browser_review_gate
77
+ changelog_uri: https://github.com/Halvanhelv/browser_review_gate/blob/master/CHANGELOG.md
78
+ bug_tracker_uri: https://github.com/Halvanhelv/browser_review_gate/issues
79
+ rubygems_mfa_required: 'true'
57
80
  rdoc_options: []
58
81
  require_paths:
59
82
  - lib
@@ -68,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
91
  - !ruby/object:Gem::Version
69
92
  version: '0'
70
93
  requirements: []
71
- rubygems_version: 4.0.1
94
+ rubygems_version: 3.6.9
72
95
  specification_version: 4
73
96
  summary: Keeps human review of a pull request behind a browser run of its browser-visible
74
97
  changes.