attio 0.1.1
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 +7 -0
- data/.codecov.yml +52 -0
- data/.github/CODEOWNERS +28 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +28 -0
- data/.github/dependabot.yml +54 -0
- data/.github/pull_request_template.md +40 -0
- data/.github/workflows/ci.yml +112 -0
- data/.github/workflows/dependabot-auto-merge.yml +45 -0
- data/.github/workflows/pr_checks.yml +145 -0
- data/.github/workflows/release.yml +147 -0
- data/.gitignore +10 -0
- data/.rspec +4 -0
- data/.rubocop.yml +133 -0
- data/.yardopts +18 -0
- data/CHANGELOG.md +34 -0
- data/CODE_OF_CONDUCT.md +37 -0
- data/CONTRIBUTING.md +280 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +127 -0
- data/LICENSE.txt +21 -0
- data/README.md +292 -0
- data/Rakefile +57 -0
- data/SECURITY.md +59 -0
- data/attio.gemspec +34 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/danger/Dangerfile +121 -0
- data/docs/.nojekyll +0 -0
- data/docs/Attio/AuthenticationError.html +152 -0
- data/docs/Attio/Client.html +1373 -0
- data/docs/Attio/ConnectionPool/TimeoutError.html +148 -0
- data/docs/Attio/ConnectionPool.html +944 -0
- data/docs/Attio/Error.html +152 -0
- data/docs/Attio/HttpClient/ConnectionError.html +152 -0
- data/docs/Attio/HttpClient/TimeoutError.html +152 -0
- data/docs/Attio/HttpClient.html +1329 -0
- data/docs/Attio/Logger.html +747 -0
- data/docs/Attio/NotFoundError.html +152 -0
- data/docs/Attio/RateLimitError.html +152 -0
- data/docs/Attio/RequestLogger.html +780 -0
- data/docs/Attio/Resources/Attributes.html +508 -0
- data/docs/Attio/Resources/Base.html +624 -0
- data/docs/Attio/Resources/Lists.html +1002 -0
- data/docs/Attio/Resources/Objects.html +415 -0
- data/docs/Attio/Resources/Records.html +1465 -0
- data/docs/Attio/Resources/Users.html +415 -0
- data/docs/Attio/Resources/Workspaces.html +324 -0
- data/docs/Attio/Resources.html +141 -0
- data/docs/Attio/RetryHandler.html +1023 -0
- data/docs/Attio/ServerError.html +152 -0
- data/docs/Attio/ValidationError.html +152 -0
- data/docs/Attio.html +397 -0
- data/docs/SETUP.md +117 -0
- data/docs/_index.html +378 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +503 -0
- data/docs/example.rb +119 -0
- data/docs/file.CHANGELOG.html +124 -0
- data/docs/file.README.html +371 -0
- data/docs/file_list.html +64 -0
- data/docs/frames.html +22 -0
- data/docs/index.html +371 -0
- data/docs/js/app.js +344 -0
- data/docs/js/full_list.js +242 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +750 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/attio/client.rb +118 -0
- data/lib/attio/connection_pool.rb +69 -0
- data/lib/attio/errors.rb +9 -0
- data/lib/attio/http_client.rb +100 -0
- data/lib/attio/logger.rb +110 -0
- data/lib/attio/resources/attributes.rb +26 -0
- data/lib/attio/resources/base.rb +55 -0
- data/lib/attio/resources/lists.rb +56 -0
- data/lib/attio/resources/objects.rb +20 -0
- data/lib/attio/resources/records.rb +158 -0
- data/lib/attio/resources/users.rb +20 -0
- data/lib/attio/resources/workspaces.rb +13 -0
- data/lib/attio/retry_handler.rb +70 -0
- data/lib/attio/version.rb +3 -0
- data/lib/attio.rb +60 -0
- data/run_tests.rb +52 -0
- data/test_basic.rb +51 -0
- data/test_typhoeus.rb +31 -0
- metadata +160 -0
data/README.md
ADDED
@@ -0,0 +1,292 @@
|
|
1
|
+
# Attio Ruby Client
|
2
|
+
|
3
|
+
[](https://idl3.github.io/attio)
|
4
|
+
[](https://badge.fury.io/rb/attio)
|
5
|
+
|
6
|
+
Ruby client for the [Attio CRM API](https://developers.attio.com/). This library provides easy access to the Attio API, allowing you to manage records, objects, lists, and more.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'attio'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle install
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install attio
|
23
|
+
|
24
|
+
## Quick Start
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'attio'
|
28
|
+
|
29
|
+
# Initialize the client with your API key
|
30
|
+
client = Attio.client(api_key: 'your-api-key-here')
|
31
|
+
|
32
|
+
# List people records
|
33
|
+
people = client.records.list(object: 'people', limit: 10)
|
34
|
+
|
35
|
+
# Create a new person
|
36
|
+
person = client.records.create(
|
37
|
+
object: 'people',
|
38
|
+
data: {
|
39
|
+
name: 'Jane Doe',
|
40
|
+
email: 'jane@example.com',
|
41
|
+
phone: '+1-555-0123'
|
42
|
+
}
|
43
|
+
)
|
44
|
+
|
45
|
+
# Get a specific person
|
46
|
+
person = client.records.get(object: 'people', id: person['id'])
|
47
|
+
|
48
|
+
# Update a person
|
49
|
+
updated_person = client.records.update(
|
50
|
+
object: 'people',
|
51
|
+
id: person['id'],
|
52
|
+
data: { name: 'Jane Smith' }
|
53
|
+
)
|
54
|
+
|
55
|
+
# Delete a person
|
56
|
+
client.records.delete(object: 'people', id: person['id'])
|
57
|
+
```
|
58
|
+
|
59
|
+
## Usage
|
60
|
+
|
61
|
+
### Client Configuration
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
# Basic client with default timeout (30 seconds)
|
65
|
+
client = Attio.client(api_key: 'your-api-key')
|
66
|
+
|
67
|
+
# Client with custom timeout
|
68
|
+
client = Attio::Client.new(api_key: 'your-api-key', timeout: 60)
|
69
|
+
```
|
70
|
+
|
71
|
+
### Working with Records
|
72
|
+
|
73
|
+
#### Listing Records
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# List all people
|
77
|
+
people = client.records.list(object: 'people')
|
78
|
+
|
79
|
+
# List with filters
|
80
|
+
filtered_people = client.records.list(
|
81
|
+
object: 'people',
|
82
|
+
filters: {
|
83
|
+
name: { contains: 'John' },
|
84
|
+
company: { target_object: 'companies', target_record_id: 'company-123' }
|
85
|
+
},
|
86
|
+
limit: 50
|
87
|
+
)
|
88
|
+
|
89
|
+
# List with sorting
|
90
|
+
sorted_people = client.records.list(
|
91
|
+
object: 'people',
|
92
|
+
sorts: [{ field: 'created_at', direction: 'desc' }],
|
93
|
+
limit: 25
|
94
|
+
)
|
95
|
+
```
|
96
|
+
|
97
|
+
#### Creating Records
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
# Create a person
|
101
|
+
person = client.records.create(
|
102
|
+
object: 'people',
|
103
|
+
data: {
|
104
|
+
name: 'John Doe',
|
105
|
+
email: 'john@example.com',
|
106
|
+
phone: '+1-555-0123',
|
107
|
+
company: {
|
108
|
+
target_object: 'companies',
|
109
|
+
target_record_id: 'company-123'
|
110
|
+
}
|
111
|
+
}
|
112
|
+
)
|
113
|
+
|
114
|
+
# Create a company
|
115
|
+
company = client.records.create(
|
116
|
+
object: 'companies',
|
117
|
+
data: {
|
118
|
+
name: 'Acme Corp',
|
119
|
+
domain: 'acme.com',
|
120
|
+
industry: 'Technology'
|
121
|
+
}
|
122
|
+
)
|
123
|
+
```
|
124
|
+
|
125
|
+
#### Updating Records
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
# Update a person's email
|
129
|
+
client.records.update(
|
130
|
+
object: 'people',
|
131
|
+
id: 'person-123',
|
132
|
+
data: { email: 'newemail@example.com' }
|
133
|
+
)
|
134
|
+
|
135
|
+
# Update multiple fields
|
136
|
+
client.records.update(
|
137
|
+
object: 'people',
|
138
|
+
id: 'person-123',
|
139
|
+
data: {
|
140
|
+
name: 'John Smith',
|
141
|
+
phone: '+1-555-9999',
|
142
|
+
notes: 'Updated contact information'
|
143
|
+
}
|
144
|
+
)
|
145
|
+
```
|
146
|
+
|
147
|
+
### Working with Other Resources
|
148
|
+
|
149
|
+
#### Objects
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
# List all object types
|
153
|
+
objects = client.objects.list
|
154
|
+
|
155
|
+
# Get a specific object schema
|
156
|
+
people_object = client.objects.get(id: 'people')
|
157
|
+
```
|
158
|
+
|
159
|
+
#### Lists
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
# List all lists
|
163
|
+
lists = client.lists.list
|
164
|
+
|
165
|
+
# Get entries from a specific list
|
166
|
+
entries = client.lists.entries(id: 'list-123')
|
167
|
+
```
|
168
|
+
|
169
|
+
#### Workspaces
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
# List workspaces
|
173
|
+
workspaces = client.workspaces.list
|
174
|
+
|
175
|
+
# Get current workspace
|
176
|
+
workspace = client.workspaces.get
|
177
|
+
```
|
178
|
+
|
179
|
+
#### Attributes
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
# List attributes for an object
|
183
|
+
attributes = client.attributes.list(object: 'people')
|
184
|
+
|
185
|
+
# Create a custom attribute
|
186
|
+
attribute = client.attributes.create(
|
187
|
+
object: 'people',
|
188
|
+
data: {
|
189
|
+
title: 'Custom Field',
|
190
|
+
api_slug: 'custom_field',
|
191
|
+
type: 'text'
|
192
|
+
}
|
193
|
+
)
|
194
|
+
```
|
195
|
+
|
196
|
+
#### Users
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
# List workspace users
|
200
|
+
users = client.users.list
|
201
|
+
|
202
|
+
# Get current user
|
203
|
+
user = client.users.me
|
204
|
+
```
|
205
|
+
|
206
|
+
### Error Handling
|
207
|
+
|
208
|
+
The client will raise appropriate exceptions for different error conditions:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
begin
|
212
|
+
client.records.get(object: 'people', id: 'invalid-id')
|
213
|
+
rescue Attio::NotFoundError => e
|
214
|
+
puts "Record not found: #{e.message}"
|
215
|
+
rescue Attio::AuthenticationError => e
|
216
|
+
puts "Authentication failed: #{e.message}"
|
217
|
+
rescue Attio::RateLimitError => e
|
218
|
+
puts "Rate limit exceeded. Retry after: #{e.retry_after}"
|
219
|
+
rescue Attio::APIError => e
|
220
|
+
puts "API error: #{e.message}"
|
221
|
+
end
|
222
|
+
```
|
223
|
+
|
224
|
+
## Configuration Options
|
225
|
+
|
226
|
+
| Option | Type | Default | Description |
|
227
|
+
|--------|------|---------|-------------|
|
228
|
+
| `api_key` | String | Required | Your Attio API key |
|
229
|
+
| `timeout` | Integer | 30 | Request timeout in seconds |
|
230
|
+
|
231
|
+
## API Coverage
|
232
|
+
|
233
|
+
This client supports all major Attio API endpoints:
|
234
|
+
|
235
|
+
- ✅ Records (CRUD operations, querying)
|
236
|
+
- ✅ Objects (list, get schema)
|
237
|
+
- ✅ Lists (list, get entries)
|
238
|
+
- ✅ Workspaces (list, get current)
|
239
|
+
- ✅ Attributes (list, create, update)
|
240
|
+
- ✅ Users (list, get current user)
|
241
|
+
|
242
|
+
## Development
|
243
|
+
|
244
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
245
|
+
|
246
|
+
### Running Tests
|
247
|
+
|
248
|
+
```bash
|
249
|
+
bundle exec rspec
|
250
|
+
```
|
251
|
+
|
252
|
+
### Generating Documentation
|
253
|
+
|
254
|
+
```bash
|
255
|
+
# Generate YARD documentation
|
256
|
+
bundle exec rake docs:generate
|
257
|
+
|
258
|
+
# Open documentation in browser
|
259
|
+
bundle exec rake docs:open
|
260
|
+
|
261
|
+
# Serve documentation locally
|
262
|
+
bundle exec rake docs:serve
|
263
|
+
```
|
264
|
+
|
265
|
+
### Code Coverage
|
266
|
+
|
267
|
+
```bash
|
268
|
+
bundle exec rake coverage:report
|
269
|
+
```
|
270
|
+
|
271
|
+
## Contributing
|
272
|
+
|
273
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/idl3/attio.
|
274
|
+
|
275
|
+
1. Fork the repository
|
276
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
277
|
+
3. Make your changes and add tests
|
278
|
+
4. Ensure all tests pass (`bundle exec rspec`)
|
279
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
280
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
281
|
+
7. Create a new Pull Request
|
282
|
+
|
283
|
+
## License
|
284
|
+
|
285
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
286
|
+
|
287
|
+
## Support
|
288
|
+
|
289
|
+
- 📖 [API Documentation](https://developers.attio.com/)
|
290
|
+
- 🐛 [Issues](https://github.com/idl3/attio/issues)
|
291
|
+
- 💬 [Discussions](https://github.com/idl3/attio/discussions)
|
292
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "yard"
|
6
|
+
require "yard/rake/yardoc_task"
|
7
|
+
|
8
|
+
YARD::Rake::YardocTask.new do |t|
|
9
|
+
t.files = ['lib/**/*.rb']
|
10
|
+
t.options = ['--output-dir', 'docs']
|
11
|
+
end
|
12
|
+
rescue LoadError
|
13
|
+
# YARD is not available
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec::Core::RakeTask.new(:spec)
|
17
|
+
|
18
|
+
task default: :spec
|
19
|
+
|
20
|
+
namespace :coverage do
|
21
|
+
desc "Run tests with coverage report"
|
22
|
+
task :report do
|
23
|
+
ENV['COVERAGE'] = 'true'
|
24
|
+
Rake::Task["spec"].execute
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
namespace :docs do
|
29
|
+
desc "Generate YARD documentation"
|
30
|
+
task :generate do
|
31
|
+
if defined?(YARD)
|
32
|
+
Rake::Task["yard"].execute
|
33
|
+
else
|
34
|
+
puts "YARD is not available. Please install it with: gem install yard"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Generate and open documentation"
|
39
|
+
task :open => :generate do
|
40
|
+
if File.exist?("docs/index.html")
|
41
|
+
system("open docs/index.html")
|
42
|
+
else
|
43
|
+
puts "Documentation not found. Run 'rake docs:generate' first."
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Clean generated documentation"
|
48
|
+
task :clean do
|
49
|
+
FileUtils.rm_rf("docs") if File.exist?("docs")
|
50
|
+
puts "Documentation cleaned."
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Serve documentation locally (requires 'gem install yard')"
|
54
|
+
task :serve do
|
55
|
+
system("yard server --reload")
|
56
|
+
end
|
57
|
+
end
|
data/SECURITY.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
## Supported Versions
|
4
|
+
|
5
|
+
We release patches for security vulnerabilities. Which versions are eligible for receiving such patches depends on the CVSS v3.0 Rating:
|
6
|
+
|
7
|
+
| Version | Supported |
|
8
|
+
| ------- | ------------------ |
|
9
|
+
| 1.x.x | :white_check_mark: |
|
10
|
+
| < 1.0 | :x: |
|
11
|
+
|
12
|
+
## Reporting a Vulnerability
|
13
|
+
|
14
|
+
If you discover a security vulnerability within this project, please follow these steps:
|
15
|
+
|
16
|
+
1. **Do NOT** create a public GitHub issue
|
17
|
+
2. Send details to the maintainers through GitHub Security Advisories
|
18
|
+
3. Include the following in your report:
|
19
|
+
- Description of the vulnerability
|
20
|
+
- Steps to reproduce
|
21
|
+
- Possible impact
|
22
|
+
- Suggested fix (if any)
|
23
|
+
|
24
|
+
### What to expect
|
25
|
+
|
26
|
+
- Acknowledgment of your report within 48 hours
|
27
|
+
- Regular updates on our progress
|
28
|
+
- Credit for responsible disclosure (unless you prefer to remain anonymous)
|
29
|
+
|
30
|
+
## Security Best Practices
|
31
|
+
|
32
|
+
When using this gem:
|
33
|
+
|
34
|
+
1. **API Key Management**
|
35
|
+
- Never commit API keys to version control
|
36
|
+
- Use environment variables or secure credential management
|
37
|
+
- Rotate API keys regularly
|
38
|
+
|
39
|
+
2. **Dependencies**
|
40
|
+
- Keep the gem updated to the latest version
|
41
|
+
- Monitor security advisories
|
42
|
+
- Use `bundle audit` to check for vulnerable dependencies
|
43
|
+
|
44
|
+
3. **Data Handling**
|
45
|
+
- Be cautious with sensitive data in logs
|
46
|
+
- Use HTTPS for all API communications
|
47
|
+
- Implement proper error handling to avoid information leakage
|
48
|
+
|
49
|
+
## Security Features
|
50
|
+
|
51
|
+
This gem includes:
|
52
|
+
- Automatic API key masking in logs
|
53
|
+
- SSL/TLS verification by default
|
54
|
+
- Rate limiting protection
|
55
|
+
- Input validation and sanitization
|
56
|
+
|
57
|
+
## Contact
|
58
|
+
|
59
|
+
For security concerns, please use GitHub Security Advisories or contact the maintainers directly through GitHub.
|
data/attio.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'lib/attio/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "attio"
|
5
|
+
spec.version = Attio::VERSION
|
6
|
+
spec.authors = ["Ernest Sim"]
|
7
|
+
spec.email = ["ernest.codes@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = %q{Ruby client for the Attio API}
|
10
|
+
spec.description = %q{A Ruby library for interacting with the Attio API, providing easy access to CRM functionality}
|
11
|
+
spec.homepage = "https://github.com/idl3/attio"
|
12
|
+
spec.license = "MIT"
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
14
|
+
|
15
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
19
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_dependency "typhoeus", "~> 1.4"
|
31
|
+
|
32
|
+
# Development dependencies
|
33
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
34
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "attio"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/danger/Dangerfile
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Make it more obvious that a PR is a work in progress and shouldn't be merged yet
|
4
|
+
warn("PR is classed as Work in Progress") if github.pr_title.include? "WIP"
|
5
|
+
|
6
|
+
# Warn when there is a big PR
|
7
|
+
warn("Big PR") if git.lines_of_code > 500
|
8
|
+
|
9
|
+
# Don't let testing shortcuts get into main by accident
|
10
|
+
fail("fdescribe left in tests") if `grep -r fdescribe spec/ `.length > 1
|
11
|
+
fail("fit left in tests") if `grep -r fit spec/ `.length > 1
|
12
|
+
|
13
|
+
# Ensure a clean commit history
|
14
|
+
if git.commits.any? { |c| c.message =~ /^fixup!/ }
|
15
|
+
fail("Please squash fixup! commits before merging")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check for proper conventional commit format
|
19
|
+
if github.pr_title !~ /^(feat|fix|docs|style|refactor|perf|test|chore|ci|build)(\(.+\))?: .+/
|
20
|
+
warn("PR title doesn't follow conventional commit format. Please use format: 'type(scope): description'")
|
21
|
+
end
|
22
|
+
|
23
|
+
# Ensure description is present for non-trivial changes
|
24
|
+
if github.pr_body.length < 10 && git.lines_of_code > 20
|
25
|
+
warn("Please provide a more detailed PR description for changes of this size")
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if package files have been updated
|
29
|
+
package_updated = git.modified_files.include?("attio.gemspec") || git.modified_files.include?("Gemfile")
|
30
|
+
if package_updated
|
31
|
+
message("📦 Package files have been updated")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Encourage changelog updates for non-trivial changes
|
35
|
+
has_app_changes = git.modified_files.any? { |file| file.start_with?("lib/") }
|
36
|
+
has_changelog_changes = git.modified_files.include?("CHANGELOG.md")
|
37
|
+
|
38
|
+
if has_app_changes && !has_changelog_changes
|
39
|
+
# Skip for certain PR types
|
40
|
+
unless github.pr_title =~ /^(chore|ci|docs|style|test):/
|
41
|
+
warn("Consider updating CHANGELOG.md for this change")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check for TODO comments in the diff
|
46
|
+
git.diff.each do |file|
|
47
|
+
file.patch.lines.each_with_index do |line, index|
|
48
|
+
if line.start_with?("+") && line.include?("TODO")
|
49
|
+
warn("TODO comment added", file: file.path, line: index + 1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Encourage tests for new features
|
55
|
+
has_new_features = git.diff.any? { |file| file.patch.include?("+def ") && file.path.start_with?("lib/") }
|
56
|
+
has_test_changes = git.modified_files.any? { |file| file.start_with?("spec/") }
|
57
|
+
|
58
|
+
if has_new_features && !has_test_changes
|
59
|
+
warn("New features should include tests")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Check for debugging code
|
63
|
+
debugging_patterns = [
|
64
|
+
"binding.pry",
|
65
|
+
"debugger",
|
66
|
+
"puts",
|
67
|
+
"p ",
|
68
|
+
"pp ",
|
69
|
+
"console.log"
|
70
|
+
]
|
71
|
+
|
72
|
+
git.diff.each do |file|
|
73
|
+
debugging_patterns.each do |pattern|
|
74
|
+
if file.patch.include?("+") && file.patch.include?(pattern)
|
75
|
+
fail("Debugging code found: #{pattern} in #{file.path}")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Encourage documentation for public API changes
|
81
|
+
public_api_changes = git.diff.any? do |file|
|
82
|
+
file.path.start_with?("lib/") &&
|
83
|
+
file.patch.include?("+ def ") &&
|
84
|
+
!file.patch.include?("+ def self.") # Skip private class methods
|
85
|
+
end
|
86
|
+
|
87
|
+
if public_api_changes
|
88
|
+
message("📝 Public API changes detected. Consider updating documentation.")
|
89
|
+
end
|
90
|
+
|
91
|
+
# Check for secrets or sensitive information
|
92
|
+
sensitive_patterns = [
|
93
|
+
/api[_-]?key/i,
|
94
|
+
/secret/i,
|
95
|
+
/password/i,
|
96
|
+
/token/i,
|
97
|
+
/auth/i
|
98
|
+
]
|
99
|
+
|
100
|
+
git.diff.each do |file|
|
101
|
+
file.patch.lines.each_with_index do |line, index|
|
102
|
+
if line.start_with?("+")
|
103
|
+
sensitive_patterns.each do |pattern|
|
104
|
+
if line.match?(pattern) && !line.include?("# ") # Not a comment
|
105
|
+
warn("Potential sensitive information detected", file: file.path, line: index + 1)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Performance reminders for certain file types
|
113
|
+
performance_sensitive_files = git.modified_files.select { |file| file.include?("client") || file.include?("http") }
|
114
|
+
if performance_sensitive_files.any?
|
115
|
+
message("⚡ Performance-sensitive files modified. Consider impact on API call efficiency.")
|
116
|
+
end
|
117
|
+
|
118
|
+
# Remind about version bumping for releases
|
119
|
+
if git.modified_files.include?("lib/attio/version.rb")
|
120
|
+
message("🔖 Version file updated. Don't forget to update CHANGELOG.md and create a release tag.")
|
121
|
+
end
|
data/docs/.nojekyll
ADDED
File without changes
|