commenter 0.6.1 → 0.7.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 +4 -4
- data/CLAUDE.md +1 -1
- data/README.adoc +12 -0
- data/lib/commenter/cli.rb +18 -0
- data/lib/commenter/sheet_validator.rb +55 -0
- data/lib/commenter/version.rb +1 -1
- data/lib/commenter.rb +1 -0
- data/spec/commenter/sheet_validator_spec.rb +44 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 94c3f6c75b5bf2bc60da48e3b38f3bfcbc17eb259d29834bc9b4a496da1a70fb
|
|
4
|
+
data.tar.gz: 5533dfb8fab486205a4f6a164ee5604561354d116e36018fc487913d036cf56a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66614ec628ece4764cb10b33fc6213de4dad08fc72dba5a89a2c0cebda64848795f7a7372b0ed8b44b081ec4a8daa4b80f5605867986672a32ac7c26f2778545
|
|
7
|
+
data.tar.gz: 866aa00a35e504930f882ca391d335d7bb7602e77da086148712797e9772da0683ae5055350aaf2515a4ea8b620793c3780e2c0dae8fe63486e55410a8c19e07
|
data/CLAUDE.md
CHANGED
|
@@ -50,7 +50,7 @@ Core flow: `Parser` → `CommentSheet` (metadata + `Comment` objects) → YAML /
|
|
|
50
50
|
- `Parser::TrackChangeDocxParser` — redline DOCX import: streams `word/document.xml` with Nokogiri XML::Reader (redlines can exceed 100 MB), captures `w:ins`/`w:del`/`w:moveFrom`/`w:moveTo` as comment entries (`proposed_change` renders the change itself, e.g. `Insert: "text"`; clause resolved from the nearest preceding heading including sub-clauses; element resolved from Table/Figure/Formula/NOTE references in the same clause; self-closing paragraph-mark markers skipped), plus reviewer `w:comment` threads as `-CNNN` remark entries (remark verbatim in `comments`, instruction reworded in `proposed_change`, empty `observations` for the owner). Stamps `observations` from the `observations`/`accept_all` options.
|
|
51
51
|
- `Commenter::Filler` — writes comments into the DOCX template table; maps observation status text (`accept(ed)?`, `noted`, `reject(ed)?`, …) to shading colors.
|
|
52
52
|
- GitHub integration — `GitHubIssueCreator` (`github-create`, `lib/commenter/github_integration.rb`), `GitHubIssueRetriever` (`github-retrieve`, `lib/commenter/github_issue_retriever.rb`), and `GitHubSync` (`github-sync`, subclass of the creator). Each loads its own config YAML and Octokit client, and rewrites the comments YAML in place after the run. Duplicate detection verifies issue numbers already recorded in the YAML, then searches issue bodies for a deterministic `urn:commenter:` marker appended to every created issue, then falls back to a title search over a configurable Liquid `unique_id` template (stage-aware by default: `[DIS] GB-001`). The same comment ID at different ballot stages creates separate issues. github-retrieve fills observations from open and closed issues alike.
|
|
53
|
-
- `Commenter::Cli` (`lib/commenter/cli.rb`) — Thor CLI with subcommands `import`, `merge`, `stats`, `diff`, `fill`, `export`, `github-create`, `github-sync`, `github-retrieve`.
|
|
53
|
+
- `Commenter::Cli` (`lib/commenter/cli.rb`) — Thor CLI with subcommands `import`, `merge`, `stats`, `diff`, `validate`, `fill`, `export`, `github-create`, `github-sync`, `github-retrieve`.
|
|
54
54
|
|
|
55
55
|
### Schemas
|
|
56
56
|
|
data/README.adoc
CHANGED
|
@@ -234,6 +234,18 @@ issue counts as *open*; no disposition at all counts as *undecided*). Use
|
|
|
234
234
|
`--format yaml` for machine-readable output, and `-o report.md` to write to a
|
|
235
235
|
file — the Markdown pastes directly into a GitHub issue or WG minutes.
|
|
236
236
|
|
|
237
|
+
=== Validating a comment sheet
|
|
238
|
+
|
|
239
|
+
The shipped schemas power IDE validation; `commenter validate` checks the
|
|
240
|
+
same structure from the command line — unknown versions, missing ids or
|
|
241
|
+
comment text, duplicate ids, and unrecognized comment types — and exits
|
|
242
|
+
non-zero when errors are found, so it fits CI and pre-flight checks:
|
|
243
|
+
|
|
244
|
+
[source,shell]
|
|
245
|
+
----
|
|
246
|
+
commenter validate ballot.yaml
|
|
247
|
+
----
|
|
248
|
+
|
|
237
249
|
=== Comparing ballots between stages
|
|
238
250
|
|
|
239
251
|
The same comment ID (`DE-001`) recurs at every ballot stage; comparing two
|
data/lib/commenter/cli.rb
CHANGED
|
@@ -86,6 +86,24 @@ module Commenter
|
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
desc "validate INPUT.yaml", "Check a comment sheet for structural problems"
|
|
90
|
+
def validate(input_yaml)
|
|
91
|
+
comment_sheet = CommentSheet.from_yaml(File.read(input_yaml))
|
|
92
|
+
problems = SheetValidator.call(comment_sheet)
|
|
93
|
+
|
|
94
|
+
if problems.empty?
|
|
95
|
+
puts "OK: #{comment_sheet.comments.length} comments, no problems found"
|
|
96
|
+
return
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
problems.each do |problem|
|
|
100
|
+
where = problem[:comment] ? "#{problem[:comment]}: " : ""
|
|
101
|
+
puts "#{problem[:severity].to_s.upcase}: #{where}#{problem[:message]}"
|
|
102
|
+
end
|
|
103
|
+
errors = problems.count { |problem| problem[:severity] == :error }
|
|
104
|
+
raise Commenter::Error, "#{errors} error(s) found in #{input_yaml}"
|
|
105
|
+
end
|
|
106
|
+
|
|
89
107
|
desc "fill INPUT.yaml", "Fill DOCX template from YAML comments"
|
|
90
108
|
option :output, type: :string, aliases: :o, default: "filled_comments.docx", desc: "Output DOCX file"
|
|
91
109
|
option :template, type: :string, aliases: :t, desc: "Custom template file"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Commenter
|
|
4
|
+
# Structural validation of a comment sheet — the checks the CLI schemas
|
|
5
|
+
# express, living next to the model so the vocabulary stays in one place.
|
|
6
|
+
# Returns a list of problems; entries are hashes with :severity (:error or
|
|
7
|
+
# :warning), :comment (id when the problem belongs to one comment), and
|
|
8
|
+
# :message. An empty list means the sheet is valid.
|
|
9
|
+
module SheetValidator
|
|
10
|
+
VERSIONS = %w[2012-03 osd].freeze
|
|
11
|
+
STAGES = %w[WD CD DIS FDIS PRF PUB].freeze
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def call(sheet)
|
|
16
|
+
problems = []
|
|
17
|
+
unless VERSIONS.include?(sheet.version)
|
|
18
|
+
problems << { severity: :error,
|
|
19
|
+
message: "unknown version #{sheet.version.inspect} (expected #{VERSIONS.join(" or ")})" }
|
|
20
|
+
end
|
|
21
|
+
if sheet.stage && !STAGES.include?(sheet.stage)
|
|
22
|
+
problems << { severity: :warning,
|
|
23
|
+
message: "unusual stage #{sheet.stage.inspect} (expected one of #{STAGES.join(", ")})" }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sheet.comments.each_with_index do |comment, index|
|
|
27
|
+
problems.concat(comment_problems(comment, index))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
duplicates = sheet.comments.group_by { |comment| comment.id.to_s }
|
|
31
|
+
.reject { |id, _| id.empty? }
|
|
32
|
+
.select { |_, comments| comments.length > 1 }
|
|
33
|
+
.keys
|
|
34
|
+
duplicates.sort.each do |id|
|
|
35
|
+
problems << { severity: :error, comment: id, message: "duplicate comment id #{id}" }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
problems
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def comment_problems(comment, index)
|
|
42
|
+
problems = []
|
|
43
|
+
label = comment.id.to_s.empty? ? "comment ##{index + 1}" : comment.id
|
|
44
|
+
|
|
45
|
+
problems << { severity: :error, comment: label, message: "missing id" } if comment.id.to_s.strip.empty?
|
|
46
|
+
problems << { severity: :error, comment: label, message: "missing comment text" } if comment.comments.to_s.strip.empty?
|
|
47
|
+
unless comment.type.to_s.strip.empty? || CommentType.known?(comment.type)
|
|
48
|
+
problems << { severity: :warning, comment: label,
|
|
49
|
+
message: "unrecognized comment type #{comment.type.inspect} (no label will be minted for it)" }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
problems
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/commenter/version.rb
CHANGED
data/lib/commenter.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Commenter
|
|
|
14
14
|
autoload :Ballot, "commenter/ballot"
|
|
15
15
|
autoload :BallotReport, "commenter/ballot_report"
|
|
16
16
|
autoload :BallotDiff, "commenter/ballot_diff"
|
|
17
|
+
autoload :SheetValidator, "commenter/sheet_validator"
|
|
17
18
|
autoload :Comment, "commenter/comment"
|
|
18
19
|
autoload :CommentSheet, "commenter/comment_sheet"
|
|
19
20
|
autoload :GitHubSession, "commenter/github_session"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.describe Commenter::SheetValidator do
|
|
6
|
+
def sheet(comments, version: "2012-03", stage: nil)
|
|
7
|
+
Commenter::CommentSheet.new(version: version, stage: stage, comments: comments)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def comment(id, text: "Text", type: "technical")
|
|
11
|
+
Commenter::Comment.new(id: id, body: id.to_s.split("-").first, comments: text, type: type)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "accepts a clean sheet" do
|
|
15
|
+
expect(described_class.call(sheet([comment("DE-001")]))).to eq([])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "reports unknown versions and unusual stages" do
|
|
19
|
+
problems = described_class.call(sheet([comment("DE-001")], version: "2018-01", stage: "CUSTOM"))
|
|
20
|
+
|
|
21
|
+
expect(problems).to include(severity: :error, message: a_string_including("unknown version"))
|
|
22
|
+
expect(problems).to include(severity: :warning, message: a_string_including("unusual stage"))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "reports missing ids, missing text, and duplicate ids as errors" do
|
|
26
|
+
problems = described_class.call(sheet([
|
|
27
|
+
comment("", text: "No id"),
|
|
28
|
+
comment("DE-001"),
|
|
29
|
+
comment("DE-001"),
|
|
30
|
+
comment("DE-002", text: "")
|
|
31
|
+
]))
|
|
32
|
+
|
|
33
|
+
errors = problems.select { |problem| problem[:severity] == :error }
|
|
34
|
+
expect(errors.map { |problem| problem[:message] }).to include("missing id", "missing comment text",
|
|
35
|
+
"duplicate comment id DE-001")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "warns about unrecognized comment types without failing" do
|
|
39
|
+
problems = described_class.call(sheet([comment("DE-001", type: "ge/te")]))
|
|
40
|
+
|
|
41
|
+
expect(problems).to contain_exactly(severity: :warning, comment: "DE-001",
|
|
42
|
+
message: a_string_including("unrecognized comment type"))
|
|
43
|
+
end
|
|
44
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: commenter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
@@ -169,6 +169,7 @@ files:
|
|
|
169
169
|
- lib/commenter/parser.rb
|
|
170
170
|
- lib/commenter/parser/osd_xlsx_parser.rb
|
|
171
171
|
- lib/commenter/parser/track_change_docx_parser.rb
|
|
172
|
+
- lib/commenter/sheet_validator.rb
|
|
172
173
|
- lib/commenter/version.rb
|
|
173
174
|
- schema/iso_comment_2012-03.yaml
|
|
174
175
|
- schema/iso_comment_osd.yaml
|
|
@@ -185,6 +186,7 @@ files:
|
|
|
185
186
|
- spec/commenter/github_integration_spec.rb
|
|
186
187
|
- spec/commenter/github_sync_spec.rb
|
|
187
188
|
- spec/commenter/osd_xlsx_parser_spec.rb
|
|
189
|
+
- spec/commenter/sheet_validator_spec.rb
|
|
188
190
|
- spec/commenter/track_change_docx_parser_spec.rb
|
|
189
191
|
- spec/commenter_spec.rb
|
|
190
192
|
- spec/spec_helper.rb
|