Skip to content

Commit 852a8f9

Browse files
committed
Check for option documentation in CI
1 parent 2646e78 commit 852a8f9

File tree

2 files changed

+179
-0
lines changed

2 files changed

+179
-0
lines changed

.github/scripts/check_config_doc.rb

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
lib = File.expand_path('lib', __dir__)
2+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3+
require 'datadog'
4+
5+
require 'yaml'
6+
7+
regenerate_todo = ARGV.include?('--regenerate-todo')
8+
ignore_todo = ARGV.include?('--ignore-todo')
9+
10+
DOCS = File.read('docs/GettingStarted.md')
11+
12+
todos = if !regenerate_todo && !ignore_todo && File.exist?('.github/check_config_doc_todo.yml')
13+
YAML.safe_load(File.read('.github/check_config_doc_todo.yml'))
14+
else
15+
{
16+
'library' => [],
17+
'integrations' => Hash.new { |h, k| h[k] = [] }
18+
}
19+
end
20+
21+
total_todos = 0
22+
total_oks = 0
23+
24+
def walk(config, path = nil, &block)
25+
config.to_h.each do |key, value|
26+
if value.is_a?(Datadog::Core::Configuration::Base)
27+
walk(value, "#{path}#{key}.", &block)
28+
else
29+
block.call("#{path}#{key}")
30+
end
31+
end
32+
end
33+
34+
library_offences = []
35+
36+
walk(Datadog.configuration) do |full_name|
37+
if !DOCS.include?(full_name)
38+
total_todos += 1
39+
if regenerate_todo || !todos['library']&.include?(full_name)
40+
library_offences << full_name
41+
end
42+
else
43+
total_oks += 1
44+
end
45+
end
46+
47+
integration_offences = Hash.new { |h, k| h[k] = [] }
48+
49+
Datadog::Tracing::Contrib::REGISTRY.to_h.each do |integration_name, _|
50+
config = Datadog.configuration.tracing[integration_name]
51+
walk(config) do |full_name|
52+
# Convert `_` in the integration name to any character or no character, as we have
53+
# different cases, e.g. DelayedJob, Action Cable.
54+
name_match = integration_name.to_s.gsub('_', '.?')
55+
56+
matcher = Regexp.new('^### ' + name_match + '\s*\n(.*?)(?=^### |\z)', Regexp::IGNORECASE | Regexp::MULTILINE)
57+
58+
section = DOCS[matcher, 1]
59+
if section
60+
if !section.include?(full_name)
61+
total_todos += 1
62+
if regenerate_todo || !todos['integrations'][integration_name.to_s]&.include?(full_name)
63+
integration_offences[integration_name.to_s] << full_name
64+
end
65+
else
66+
total_oks += 1
67+
end
68+
else
69+
total_todos += 1
70+
if regenerate_todo || !todos['integrations'][integration_name.to_s]&.include?('all')
71+
integration_offences[integration_name.to_s] = 'all'
72+
end
73+
end
74+
end
75+
end
76+
77+
integration_offences_count = integration_offences.values.flatten.size
78+
total_offences = library_offences.size + integration_offences_count
79+
80+
def green(str)
81+
"\e[32m#{str}\e[0m"
82+
end
83+
84+
def yellow(str)
85+
"\e[33m#{str}\e[0m"
86+
end
87+
88+
def print_library_offence_details(offences, search_dir, exclude_dir = '')
89+
offences.each do |offence|
90+
STDERR.puts " • #{offence}"
91+
search_term = "option :#{offence.split('.')[-1]}"
92+
matches = `grep -nE --exclude-dir=#{exclude_dir} '^[^#]*#{search_term}' -R #{search_dir}`
93+
lines = matches.lines
94+
if lines.size == 1
95+
STDERR.puts " #{lines[0].strip}"
96+
elsif lines.size > 1
97+
STDERR.puts " Found in multiple places:"
98+
lines.each do |line|
99+
STDERR.puts " #{line.strip}"
100+
end
101+
end
102+
end
103+
end
104+
105+
puts green("😁 Total options documented: #{total_oks}") if total_oks > 0
106+
107+
puts yellow("🧐 Total offences ignored by TODOs: #{total_todos}") if !ignore_todo && !regenerate_todo && total_todos > 0
108+
109+
if regenerate_todo
110+
todos = {
111+
'library' => library_offences,
112+
'integrations' => integration_offences
113+
}
114+
File.write('.github/check_config_doc_todo.yml', todos.to_yaml)
115+
puts green("✒️ #{total_offences} total TODOs updated in .github/check_config_doc_todo.yml")
116+
elsif total_offences > 0
117+
if library_offences.size > 0
118+
STDERR.puts "❗️Library configuration options not documented: #{library_offences.size}"
119+
print_library_offence_details(library_offences, "lib", "lib/datadog/tracing/contrib")
120+
STDERR.puts
121+
STDERR.puts " Please document them in docs/GettingStarted.md, section `## Additional configuration`"
122+
STDERR.puts
123+
end
124+
125+
if integration_offences_count > 0
126+
STDERR.puts "️️️❗️Integration configuration options not documented: #{integration_offences_count}"
127+
integration_offences.each do |integration, offences|
128+
if offences == 'all'
129+
STDERR.puts " ▸ Integration '#{integration}'"
130+
STDERR.puts " • Documentation section not found!"
131+
else
132+
STDERR.puts " ▸ Integration '#{integration}'"
133+
print_library_offence_details(offences, "lib/datadog/tracing/contrib/#{integration}")
134+
end
135+
end
136+
STDERR.puts
137+
STDERR.puts " Please document them in docs/GettingStarted.md, section `## Integration instrumentation`"
138+
end
139+
140+
STDERR.puts
141+
STDERR.puts "😭 Total offences found: #{total_offences}"
142+
exit 1
143+
end
144+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Check for missing documentation for library configuration options
2+
3+
on: # yamllint disable-line rule:truthy
4+
push:
5+
branches:
6+
- master
7+
# A workaround to trigger the workflow for pull requests from forked repository,
8+
# which does not have access to secrets.
9+
#
10+
# This is also useful for testing the workflow without opening a pull request.
11+
- tmp/*
12+
pull_request:
13+
branches:
14+
- master
15+
16+
# Default permissions for all jobs
17+
permissions: {}
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-22.04
22+
permissions: {}
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
26+
with:
27+
persist-credentials: false
28+
29+
# - name: Set up Ruby
30+
# uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
31+
# with:
32+
# ruby-version: "3.4"
33+
34+
- name: Check for missing documentation
35+
run: ruby .github/scripts/check_config_doc.rb

0 commit comments

Comments
 (0)