class-metrix 1.0.0 → 1.1.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.prettierrc.json +41 -0
  3. data/.qlty/.gitignore +7 -0
  4. data/.qlty/configs/.yamllint.yaml +8 -0
  5. data/.qlty/qlty.toml +108 -0
  6. data/.rubocop.yml +31 -25
  7. data/.vscode/README.md +255 -47
  8. data/.vscode/extensions.json +8 -13
  9. data/.vscode/keybindings.json +0 -0
  10. data/.vscode/settings.json +81 -11
  11. data/.vscode/tasks.json +231 -0
  12. data/CHANGELOG.md +33 -1
  13. data/README.md +107 -23
  14. data/Rakefile +64 -1
  15. data/Steepfile +26 -0
  16. data/config/brakeman.yml +37 -0
  17. data/docs/ARCHITECTURE.md +90 -48
  18. data/docs/CHANGELOG_EVOLUTION_EXAMPLE.md +95 -0
  19. data/docs/QLTY_INTEGRATION.md +181 -0
  20. data/docs/RELEASE_GUIDE.md +318 -0
  21. data/docs/SLACK_INTEGRATION.md +227 -0
  22. data/examples/README.md +23 -17
  23. data/examples/basic_usage.rb +19 -19
  24. data/examples/debug_levels_demo.rb +15 -16
  25. data/examples/debug_mode_demo.rb +12 -13
  26. data/examples/inheritance_and_modules.rb +45 -45
  27. data/lib/class_metrix/extractor.rb +1 -1
  28. data/lib/class_metrix/extractors/constants_extractor.rb +1 -1
  29. data/lib/class_metrix/extractors/methods_extractor.rb +1 -1
  30. data/lib/class_metrix/extractors/multi_type_extractor.rb +2 -2
  31. data/lib/class_metrix/formatters/base/base_formatter.rb +3 -3
  32. data/lib/class_metrix/formatters/components/footer_component.rb +3 -3
  33. data/lib/class_metrix/formatters/components/generic_header_component.rb +2 -2
  34. data/lib/class_metrix/formatters/components/header_component.rb +4 -4
  35. data/lib/class_metrix/formatters/components/missing_behaviors_component.rb +7 -7
  36. data/lib/class_metrix/formatters/components/table_component/row_processor.rb +8 -5
  37. data/lib/class_metrix/formatters/components/table_component/table_data_extractor.rb +4 -1
  38. data/lib/class_metrix/formatters/components/table_component/table_renderer.rb +2 -2
  39. data/lib/class_metrix/formatters/components/table_component.rb +5 -4
  40. data/lib/class_metrix/formatters/csv_formatter.rb +3 -3
  41. data/lib/class_metrix/formatters/markdown_formatter.rb +3 -4
  42. data/lib/class_metrix/formatters/shared/markdown_table_builder.rb +2 -2
  43. data/lib/class_metrix/formatters/shared/table_builder.rb +8 -6
  44. data/lib/class_metrix/version.rb +1 -1
  45. data/sig/class_metrix.rbs +8 -0
  46. data/sig/extractor.rbs +54 -0
  47. data/sig/extractors.rbs +84 -0
  48. data/sig/formatters_base.rbs +59 -0
  49. data/sig/formatters_components.rbs +133 -0
  50. data/sig/formatters_main.rbs +20 -0
  51. data/sig/formatters_shared.rbs +102 -0
  52. data/sig/manifest.yaml +32 -0
  53. data/sig/utils.rbs +57 -0
  54. data/sig/value_processor.rbs +11 -0
  55. data/sig/version.rbs +4 -0
  56. metadata +94 -4
  57. data/RELEASE_GUIDE.md +0 -158
  58. data/sig/class/metrix.rbs +0 -6
@@ -0,0 +1,227 @@
1
+ # Slack Integration for ClassMetrix CI/CD
2
+
3
+ This document explains how to set up Slack notifications for ClassMetrix GitHub Actions workflows.
4
+
5
+ ## Overview
6
+
7
+ ClassMetrix uses Slack notifications to keep your team informed about CI/CD pipeline status. The integration provides minimal, focused notifications:
8
+
9
+ - **CI Pipeline**: One notification when the entire CI pipeline completes (success/failure/partial)
10
+ - **Release Pipeline**: One notification for release success, one for release failure
11
+
12
+ All notifications are sent to a single channel: `#cicd-notifications`
13
+
14
+ ## Features
15
+
16
+ ### CI Notifications
17
+
18
+ - ✅ **Pipeline Status**: Overall CI result with individual job statuses
19
+ - 🔗 **Direct Links**: Links to workflow runs and repository
20
+ - 📊 **Job Breakdown**: Status of tests, security, quality, and compatibility checks
21
+ - 🎯 **Contextual Info**: Branch, trigger type, and repository details
22
+
23
+ ### Release Notifications
24
+
25
+ - 🚀 **Release Success**: Version info, installation commands, and useful links
26
+ - ❌ **Release Failure**: Detailed failure information and troubleshooting context
27
+ - 📦 **RubyGems Links**: Direct links to published gems
28
+ - 📚 **GitHub Release**: Links to release notes and documentation
29
+
30
+ ## Setup Instructions
31
+
32
+ ### 1. Create Slack Webhook
33
+
34
+ 1. Go to your Slack workspace
35
+ 2. Navigate to **Apps** → **Incoming Webhooks**
36
+ 3. Click **Add to Slack**
37
+ 4. Choose the `#cicd-notifications` channel (create it if it doesn't exist)
38
+ 5. Copy the webhook URL (starts with `https://hooks.slack.com/services/...`)
39
+
40
+ ### 2. Add GitHub Secret
41
+
42
+ 1. Go to your GitHub repository: `https://github.com/patrick204nqh/class-metrix`
43
+ 2. Navigate to **Settings** → **Secrets and variables** → **Actions**
44
+ 3. Click **New repository secret**
45
+ 4. Name: `SLACK_WEBHOOK_URL`
46
+ 5. Value: Your Slack webhook URL
47
+ 6. Click **Add secret**
48
+
49
+ ### 3. Create Slack Channel
50
+
51
+ Create a `#cicd-notifications` channel in your Slack workspace where all CI/CD notifications will be posted.
52
+
53
+ ## Notification Examples
54
+
55
+ ### CI Pipeline Complete (Success)
56
+
57
+ ```
58
+ ✅ CI Pipeline Complete
59
+ Repository: your-org/class-metrix
60
+ Branch: main
61
+ Trigger: push
62
+ Status: success
63
+ Tests: success
64
+ Security: success
65
+ Quality: success
66
+ Compatibility: success
67
+ ```
68
+
69
+ ### CI Pipeline Complete (Failure)
70
+
71
+ ```
72
+ ❌ CI Pipeline Complete
73
+ Repository: your-org/class-metrix
74
+ Branch: feature-branch
75
+ Trigger: pull_request
76
+ Status: failure
77
+ Tests: failure
78
+ Security: success
79
+ Quality: success
80
+ Compatibility: success
81
+ ```
82
+
83
+ ### Release Success
84
+
85
+ ```
86
+ 🚀 ClassMetrix Release Complete
87
+ Version: v1.2.3
88
+ Trigger: Manual
89
+ Installation: gem install class-metrix -v 1.2.3
90
+ Links: 📦 RubyGems • 📚 GitHub Release
91
+ ```
92
+
93
+ ### Release Failure
94
+
95
+ ```
96
+ ❌ ClassMetrix Release Failed
97
+ Failed Step: Build & Publish
98
+ Version: v1.2.3
99
+ Reason: Gem build or RubyGems publishing failed
100
+ Repository: your-org/class-metrix
101
+ Workflow Run: View Logs
102
+ Triggered By: username
103
+ ```
104
+
105
+ ## Workflow Integration
106
+
107
+ ### Main CI Workflow (`.github/workflows/main.yml`)
108
+
109
+ - Runs on push to main/master and pull requests
110
+ - Sends one notification after all jobs complete
111
+ - Includes status of: tests, security scan, quality checks, compatibility
112
+ - Only sends notifications if `SLACK_WEBHOOK_URL` secret is configured
113
+
114
+ ### Release Workflow (`.github/workflows/release.yml`)
115
+
116
+ - Runs on version tags or manual dispatch
117
+ - Sends success notification with installation instructions and links
118
+ - Sends failure notification with detailed troubleshooting information
119
+ - Includes RubyGems and GitHub release links
120
+
121
+ ## Testing the Integration
122
+
123
+ ### Test CI Notifications
124
+
125
+ 1. Make a small change to your code
126
+ 2. Push to a branch or create a pull request
127
+ 3. Check the `#cicd-notifications` channel for the CI completion message
128
+
129
+ ### Test Release Notifications
130
+
131
+ 1. Create a test release using workflow dispatch:
132
+ ```bash
133
+ # Go to Actions → Release Gem → Run workflow
134
+ # Enable "Dry run" to test without publishing
135
+ ```
136
+ 2. Check the channel for release notifications
137
+
138
+ ### Manual Testing Script
139
+
140
+ You can test the Slack webhook directly:
141
+
142
+ ```bash
143
+ #!/bin/bash
144
+ # Save as bin/test_slack_integration
145
+
146
+ WEBHOOK_URL="YOUR_SLACK_WEBHOOK_URL"
147
+
148
+ curl -X POST -H 'Content-type: application/json' \
149
+ --data '{
150
+ "channel": "#cicd-notifications",
151
+ "username": "GitHub Actions CI",
152
+ "icon_emoji": ":robot_face:",
153
+ "text": "🧪 Testing Slack integration for ClassMetrix CI/CD"
154
+ }' \
155
+ "$WEBHOOK_URL"
156
+ ```
157
+
158
+ ## Troubleshooting
159
+
160
+ ### No Notifications Received
161
+
162
+ 1. **Check Secret**: Verify `SLACK_WEBHOOK_URL` is set correctly in GitHub repository secrets
163
+ 2. **Check Channel**: Ensure `#cicd-notifications` channel exists and webhook has access
164
+ 3. **Check Webhook**: Test webhook URL manually using curl or Postman
165
+ 4. **Check Logs**: View workflow run logs for any Slack notification errors
166
+
167
+ ### Webhook URL Issues
168
+
169
+ - Ensure the URL starts with `https://hooks.slack.com/services/`
170
+ - Verify the webhook is still active in Slack settings
171
+ - Check that the webhook has permission to post to the channel
172
+
173
+ ### Missing Notifications
174
+
175
+ - Notifications only send if workflows complete (not cancelled mid-run)
176
+ - CI notifications require all jobs to finish (test, security, quality, compatibility)
177
+ - Release notifications only send if `dry_run` is not enabled
178
+
179
+ ## Customization
180
+
181
+ ### Changing the Channel
182
+
183
+ To send notifications to a different channel, update the `"channel"` field in both workflow files:
184
+
185
+ ```yaml
186
+ "channel": "#your-custom-channel"
187
+ ```
188
+
189
+ ### Adding More Notifications
190
+
191
+ The current setup provides minimal notifications. To add more:
192
+
193
+ 1. Review the conversation summary for previously removed notifications
194
+ 2. Add new notification steps to appropriate workflow jobs
195
+ 3. Follow the same webhook format for consistency
196
+
197
+ ### Notification Format
198
+
199
+ All notifications use Slack's rich attachment format with:
200
+
201
+ - Color coding (green for success, red for failure, yellow for warnings)
202
+ - Structured fields for easy scanning
203
+ - Direct links to relevant resources
204
+ - Contextual information (branch, trigger, repository)
205
+
206
+ ## Security Considerations
207
+
208
+ - **Webhook URL**: Keep the `SLACK_WEBHOOK_URL` secret secure
209
+ - **Channel Access**: Ensure only appropriate team members have access to the notifications channel
210
+ - **Information Exposure**: Current notifications don't expose sensitive code or secrets
211
+ - **Rate Limiting**: Slack has rate limits for webhook calls (not typically an issue with minimal notifications)
212
+
213
+ ## Support
214
+
215
+ For issues with Slack integration:
216
+
217
+ 1. Check this documentation first
218
+ 2. Review GitHub Actions workflow logs
219
+ 3. Test webhook URL manually
220
+ 4. Verify Slack workspace permissions
221
+ 5. Create an issue in the ClassMetrix repository if problems persist
222
+
223
+ ## Related Documentation
224
+
225
+ - [GitHub Actions Documentation](https://docs.github.com/en/actions)
226
+ - [Slack Incoming Webhooks](https://api.slack.com/messaging/webhooks)
227
+ - [ClassMetrix Release Guide](./RELEASE_GUIDE.md)
data/examples/README.md CHANGED
@@ -16,6 +16,7 @@ ruby examples/inheritance_and_modules.rb # Inheritance and module analysis
16
16
  ### Core Examples
17
17
 
18
18
  - **`basic_usage.rb`** - Basic constant and method extraction
19
+
19
20
  - Simple class comparison
20
21
  - Filtering and multi-type extraction
21
22
  - Hash expansion basics
@@ -122,43 +123,48 @@ ClassMetrix.extract(:constants)
122
123
  ## 📊 Example Output
123
124
 
124
125
  ### Basic Comparison
126
+
125
127
  ```markdown
126
- | Constant | User | Admin |
127
- |----------|---------|---------|
128
- | ROLE | user | admin |
129
- | TIMEOUT | 3600 | 7200 |
128
+ | Constant | User | Admin |
129
+ | -------- | ---- | ----- |
130
+ | ROLE | user | admin |
131
+ | TIMEOUT | 3600 | 7200 |
130
132
  ```
131
133
 
132
134
  ### With Inheritance
135
+
133
136
  ```markdown
134
- | Constant | DatabaseService | CacheService |
135
- |---------------|-----------------|--------------|
136
- | SERVICE_NAME | database | cache |
137
- | SERVICE_VERSION| 1.0 | 1.0 |
138
- | DEFAULT_TIMEOUT| 30 | 30 |
137
+ | Constant | DatabaseService | CacheService |
138
+ | --------------- | --------------- | ------------ |
139
+ | SERVICE_NAME | database | cache |
140
+ | SERVICE_VERSION | 1.0 | 1.0 |
141
+ | DEFAULT_TIMEOUT | 30 | 30 |
139
142
  ```
140
143
 
141
144
  ### Hash Expansion
145
+
142
146
  ```markdown
143
- | Method | Service1 | Service2 |
144
- |---------------|-----------------|-----------------|
145
- | config | {...} | {...} |
146
- | config.host | localhost | production.com |
147
- | config.port | 3000 | 443 |
148
- | config.ssl | ❌ | ✅ |
147
+ | Method | Service1 | Service2 |
148
+ | ----------- | --------- | -------------- |
149
+ | config | {...} | {...} |
150
+ | config.host | localhost | production.com |
151
+ | config.port | 3000 | 443 |
152
+ | config.ssl | ❌ | ✅ |
149
153
  ```
150
154
 
151
155
  ## 🛠️ API Reference
152
156
 
153
157
  ### Extraction Types
158
+
154
159
  - `:constants` - Class constants
155
160
  - `:class_methods` - Class methods
156
161
 
157
162
  ### Options
163
+
158
164
  - `.from(classes)` - Classes to analyze (array)
159
165
  - `.filter(pattern)` - Filter by name (regex or string)
160
166
  - `.include_inherited` - Include parent class behaviors
161
- - `.include_modules` - Include module behaviors
167
+ - `.include_modules` - Include module behaviors
162
168
  - `.include_all` - Include inherited + modules
163
169
  - `.expand_hashes` - Expand hash values (shows main rows by default)
164
170
  - `.show_only_main` - Show only main rows (collapsed hashes) - **Default**
@@ -197,6 +203,6 @@ ruby examples/inheritance_and_modules.rb
197
203
  # Advanced features
198
204
  ruby examples/advanced/hash_expansion.rb
199
205
 
200
- # Real-world scenarios
206
+ # Real-world scenarios
201
207
  ruby examples/real_world/microservices_audit.rb
202
208
  ```
@@ -11,11 +11,11 @@ puts "=" * 30
11
11
  class User
12
12
  ROLE = "user"
13
13
  MAX_LOGIN_ATTEMPTS = 3
14
-
14
+
15
15
  def self.permissions
16
16
  ["read"]
17
17
  end
18
-
18
+
19
19
  def self.session_timeout
20
20
  3600
21
21
  end
@@ -24,11 +24,11 @@ end
24
24
  class Admin
25
25
  ROLE = "admin"
26
26
  MAX_LOGIN_ATTEMPTS = 5
27
-
27
+
28
28
  def self.permissions
29
29
  ["read", "write", "admin"]
30
30
  end
31
-
31
+
32
32
  def self.session_timeout
33
33
  7200
34
34
  end
@@ -40,33 +40,33 @@ classes = [User, Admin]
40
40
  puts "\n1. Constants Comparison"
41
41
  puts "-" * 25
42
42
  result = ClassMetrix.extract(:constants)
43
- .from(classes)
44
- .to_markdown
43
+ .from(classes)
44
+ .to_markdown
45
45
  puts result
46
46
 
47
47
  # 2. Extract class methods
48
- puts "\n2. Class Methods Comparison"
48
+ puts "\n2. Class Methods Comparison"
49
49
  puts "-" * 25
50
50
  result = ClassMetrix.extract(:class_methods)
51
- .from(classes)
52
- .to_markdown
51
+ .from(classes)
52
+ .to_markdown
53
53
  puts result
54
54
 
55
55
  # 3. Combined extraction
56
56
  puts "\n3. Combined Analysis"
57
57
  puts "-" * 25
58
58
  result = ClassMetrix.extract(:constants, :class_methods)
59
- .from(classes)
60
- .to_markdown
59
+ .from(classes)
60
+ .to_markdown
61
61
  puts result
62
62
 
63
63
  # 4. Filtered analysis
64
64
  puts "\n4. Filtered Analysis (ROLE and permissions only)"
65
65
  puts "-" * 25
66
66
  result = ClassMetrix.extract(:constants, :class_methods)
67
- .from(classes)
68
- .filter(/ROLE|permissions/)
69
- .to_markdown
67
+ .from(classes)
68
+ .filter(/ROLE|permissions/)
69
+ .to_markdown
70
70
  puts result
71
71
 
72
72
  # 5. Hash expansion
@@ -75,14 +75,14 @@ puts "-" * 25
75
75
 
76
76
  class ConfigExample
77
77
  SETTINGS = { timeout: 30, retries: 3, ssl: true }.freeze
78
-
78
+
79
79
  def self.database_config
80
80
  { host: "localhost", port: 5432, pool_size: 5 }
81
81
  end
82
82
  end
83
83
 
84
84
  result = ClassMetrix.extract(:constants, :class_methods)
85
- .from([ConfigExample])
86
- .expand_hashes
87
- .to_markdown
88
- puts result
85
+ .from([ConfigExample])
86
+ .expand_hashes
87
+ .to_markdown
88
+ puts result
@@ -9,7 +9,7 @@ require_relative '../lib/class_metrix'
9
9
  # Example classes
10
10
  class ServiceA
11
11
  CONFIG = { host: 'localhost', port: 3000, timeout: 30 }
12
-
12
+
13
13
  def self.get_settings
14
14
  { cache: true, retries: 3 }
15
15
  end
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  class ServiceB
19
19
  CONFIG = { host: 'remote', port: 8080 }
20
-
20
+
21
21
  def self.get_settings
22
22
  { cache: false, retries: 1 }
23
23
  end
@@ -30,36 +30,35 @@ puts
30
30
  levels = [:basic, :detailed, :verbose]
31
31
 
32
32
  levels.each do |level|
33
- puts "\n" + "="*50
33
+ puts "\n" + "=" * 50
34
34
  puts "DEBUG LEVEL: #{level.upcase}"
35
- puts "="*50
36
-
35
+ puts "=" * 50
36
+
37
37
  begin
38
38
  result = ClassMetrix.extract(:constants, :class_methods)
39
- .from([ServiceA, ServiceB])
40
- .expand_hashes
41
- .debug(level) # Set debug level
42
- .to_markdown
43
-
39
+ .from([ServiceA, ServiceB])
40
+ .expand_hashes
41
+ .debug(level) # Set debug level
42
+ .to_markdown
43
+
44
44
  puts "\n--- Result Summary ---"
45
45
  puts "Report generated successfully! ✅"
46
46
  puts "Lines in output: #{result.lines.count}"
47
-
48
47
  rescue => e
49
48
  puts "Error: #{e.class}: #{e.message}"
50
49
  end
51
-
50
+
52
51
  puts "\n"
53
52
  end
54
53
 
55
- puts "\n" + "="*50
54
+ puts "\n" + "=" * 50
56
55
  puts "DEBUG LEVEL SUMMARY"
57
- puts "="*50
56
+ puts "=" * 50
58
57
  puts
59
58
  puts ":basic - Key decisions and summaries only"
60
- puts ":detailed - More context and intermediate steps"
59
+ puts ":detailed - More context and intermediate steps"
61
60
  puts ":verbose - Full details including individual value processing"
62
61
  puts
63
62
  puts "Use :basic for general troubleshooting"
64
63
  puts "Use :detailed for understanding data flow"
65
- puts "Use :verbose for deep debugging of specific values"
64
+ puts "Use :verbose for deep debugging of specific values"
@@ -9,7 +9,7 @@ require_relative '../lib/class_metrix'
9
9
  # Example classes with different types of values
10
10
  class SafeService
11
11
  CONFIG = { host: 'localhost', port: 3000 }
12
-
12
+
13
13
  def self.timeout_config
14
14
  { connect: 30, read: 60 }
15
15
  end
@@ -18,7 +18,7 @@ end
18
18
  class ProblematicService
19
19
  # This constant is a Class object (not a Hash)
20
20
  CONFIG_CLASS = SafeService
21
-
21
+
22
22
  def self.service_config
23
23
  SafeService::CONFIG
24
24
  end
@@ -29,11 +29,11 @@ class ProblematicObject
29
29
  def inspect
30
30
  raise "Inspect not allowed!"
31
31
  end
32
-
32
+
33
33
  def to_s
34
34
  raise "To_s not allowed!"
35
35
  end
36
-
36
+
37
37
  def class
38
38
  raise "Class not allowed!"
39
39
  end
@@ -41,7 +41,7 @@ end
41
41
 
42
42
  class WeirdService
43
43
  BROKEN_OBJECT = ProblematicObject.new
44
-
44
+
45
45
  def self.get_config
46
46
  { normal: 'value', broken: ProblematicObject.new }
47
47
  end
@@ -58,18 +58,17 @@ puts
58
58
 
59
59
  begin
60
60
  result = ClassMetrix.extract(:constants, :class_methods)
61
- .from([SafeService, ProblematicService, WeirdService])
62
- .expand_hashes
63
- .handle_errors
64
- .debug # Enable debug mode
65
- .to_markdown
66
-
61
+ .from([SafeService, ProblematicService, WeirdService])
62
+ .expand_hashes
63
+ .handle_errors
64
+ .debug # Enable debug mode
65
+ .to_markdown
66
+
67
67
  puts "\n=== Generated Report ==="
68
68
  puts result[0..500] + "..." if result.length > 500
69
69
  puts "\nReport generated successfully! ✅"
70
70
  puts "Note: Debug output above shows how problematic objects were handled safely."
71
-
72
71
  rescue => e
73
72
  puts "Error: #{e.class}: #{e.message}"
74
73
  puts "This should not happen with the safety improvements!"
75
- end
74
+ end