pylon-api 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fcfe4ab02c112c8898998add96fc34ff4846029b2fc10bf2e2ce13c1f907a565
4
+ data.tar.gz: d8fd25a0307bbdc62e1a8921a95cf5859382f52d27303d25fec825db7f416ee7
5
+ SHA512:
6
+ metadata.gz: 7205621d5fe56ec66b58974d632eaa03e5be978a42e508656ad59583d499d348eef1ae91e6838da9f2ee3f9add0113f7e45151cce4578aebcd786cb2065a86ff
7
+ data.tar.gz: d0bd80e6ba44a85fb9d083263cf0ae74904d5fce043fb18de248cf6e4ff8807905b4dedc5508afc05af9c293c1b2f8778b860602969c48992b58a7896fe01c6a
data/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] - 2024-03-21
8
+
9
+ ### Added
10
+ - Initial release of the Pylon API Ruby client
11
+ - Comprehensive client implementation with support for all major API endpoints:
12
+ - Accounts management
13
+ - Attachments handling
14
+ - Contacts management
15
+ - Custom fields
16
+ - Issues tracking
17
+ - Knowledge base articles
18
+ - Tags management
19
+ - Teams management
20
+ - Ticket forms
21
+ - User roles
22
+ - Users management
23
+ - Robust error handling with specific error classes:
24
+ - `Pylon::AuthenticationError`
25
+ - `Pylon::ResourceNotFoundError`
26
+ - `Pylon::ValidationError`
27
+ - `Pylon::ApiError`
28
+ - Pagination support for list endpoints
29
+ - Debug mode for request/response logging
30
+ - Comprehensive test suite with RSpec
31
+ - YARD documentation for all methods
32
+ - MIT License
33
+
34
+ [0.1.0]: https://github.com/benjodo/pylon-api/releases/tag/v0.1.0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Aptible
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # Pylon API Ruby Client
2
+
3
+ A Ruby client for the [Pylon API](https://docs.usepylon.com/pylon-docs/developer/api/api-reference).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'pylon-api'
11
+ ```
12
+
13
+ And then execute:
14
+ ```bash
15
+ $ bundle install
16
+ ```
17
+
18
+ Or install it yourself as:
19
+ ```bash
20
+ $ gem install pylon-api
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ First, initialize a client with your API key:
26
+
27
+ ```ruby
28
+ require 'pylon'
29
+
30
+ client = Pylon::Client.new(api_key: 'your_api_key')
31
+
32
+ # Enable debug mode to see request/response details
33
+ client = Pylon::Client.new(api_key: 'your_api_key', debug: true)
34
+ ```
35
+
36
+ ### Examples
37
+
38
+ #### Current User
39
+
40
+ ```ruby
41
+ # Get current user details
42
+ user, response = client.get_current_user
43
+ ```
44
+
45
+ #### Accounts
46
+
47
+ ```ruby
48
+ # List accounts with pagination
49
+ accounts, response = client.list_accounts(page: 1, per_page: 20)
50
+
51
+ # Get a specific account
52
+ account, response = client.get_account('account_id')
53
+ ```
54
+
55
+ #### Issues
56
+
57
+ ```ruby
58
+ # List issues (requires time range, max 30 days)
59
+ start_time = Time.now.utc - 86400 # 24 hours ago
60
+ end_time = Time.now.utc
61
+
62
+ issues, response = client.list_issues(
63
+ start_time: start_time.strftime("%Y-%m-%dT%H:%M:%SZ"),
64
+ end_time: end_time.strftime("%Y-%m-%dT%H:%M:%SZ"),
65
+ page: 1,
66
+ per_page: 20,
67
+ status: 'open' # optional filter
68
+ )
69
+
70
+ # Create an issue
71
+ issue, response = client.create_issue(
72
+ title: 'New Issue',
73
+ description: 'Issue description'
74
+ )
75
+ ```
76
+
77
+ #### Teams
78
+
79
+ ```ruby
80
+ # List teams
81
+ teams, response = client.list_teams(page: 1, per_page: 20)
82
+
83
+ # Create a team
84
+ team, response = client.create_team(name: 'Engineering')
85
+
86
+ # Get a specific team
87
+ team, response = client.get_team('team_id')
88
+ ```
89
+
90
+ #### Users
91
+
92
+ ```ruby
93
+ # List users
94
+ users, response = client.list_users(page: 1, per_page: 20)
95
+
96
+ # Create a user
97
+ user, response = client.create_user(
98
+ email: 'user@example.com',
99
+ name: 'John Doe'
100
+ )
101
+ ```
102
+
103
+ ## Development
104
+
105
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
106
+
107
+ For more information about the project, including contributing guidelines and development setup, see the [main project README](../README.md).
108
+
109
+ ## Contributing
110
+
111
+ Bug reports and pull requests are welcome on GitHub. Please see the [main project README](../README.md) for more details.
@@ -0,0 +1,387 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pylon
4
+ # Client for interacting with the Pylon API
5
+ #
6
+ # @example
7
+ # client = Pylon::Client.new(api_key: 'your_api_key')
8
+ # issues = client.list_issues(start_time: '2024-03-01T00:00:00Z', end_time: '2024-03-31T23:59:59Z')
9
+ class Client
10
+ # Base URL for the Pylon API
11
+ BASE_URL = "https://api.usepylon.com"
12
+
13
+ # @return [String] The API key used for authentication
14
+ attr_reader :api_key, :debug
15
+
16
+ # Initialize a new Pylon API client
17
+ #
18
+ # @param api_key [String] Your Pylon API key
19
+ # @param base_url [String] Optional base URL for the API (defaults to production)
20
+ # @param debug [Boolean] Whether to enable debug mode for request/response logging
21
+ def initialize(api_key:, base_url: BASE_URL, debug: false)
22
+ @api_key = api_key
23
+ @base_url = base_url
24
+ @debug = debug
25
+ end
26
+
27
+ # List all accounts with pagination
28
+ #
29
+ # @param page [Integer] Page number for pagination
30
+ # @param per_page [Integer] Number of items per page
31
+ # @return [Array<Hash>] List of accounts
32
+ def list_accounts(page: 1, per_page: 20)
33
+ get("/accounts", query: { page: page, per_page: per_page })
34
+ end
35
+
36
+ # Get details for a specific account
37
+ #
38
+ # @param account_id [String] The ID of the account to retrieve
39
+ # @return [Hash] Account details
40
+ def get_account(account_id)
41
+ get("/accounts/#{account_id}")
42
+ end
43
+
44
+ # Create a new attachment
45
+ #
46
+ # @param file [String] The file content to upload
47
+ # @return [Hash] Created attachment details
48
+ def create_attachment(file)
49
+ post("/attachments", body: { file: file })
50
+ end
51
+
52
+ # Get details for a specific attachment
53
+ #
54
+ # @param attachment_id [String] The ID of the attachment to retrieve
55
+ # @return [Hash] Attachment details
56
+ def get_attachment(attachment_id)
57
+ get("/attachments/#{attachment_id}")
58
+ end
59
+
60
+ # List all contacts with pagination
61
+ #
62
+ # @param page [Integer] Page number for pagination
63
+ # @param per_page [Integer] Number of items per page
64
+ # @return [Array<Hash>] List of contacts
65
+ def list_contacts(page: 1, per_page: 20)
66
+ get("/contacts", query: { page: page, per_page: per_page })
67
+ end
68
+
69
+ # Create a new contact
70
+ #
71
+ # @param params [Hash] Contact parameters
72
+ # @return [Hash] Created contact details
73
+ def create_contact(params)
74
+ post("/contacts", body: params)
75
+ end
76
+
77
+ # Get details for a specific contact
78
+ #
79
+ # @param contact_id [String] The ID of the contact to retrieve
80
+ # @return [Hash] Contact details
81
+ def get_contact(contact_id)
82
+ get("/contacts/#{contact_id}")
83
+ end
84
+
85
+ # Update an existing contact
86
+ #
87
+ # @param contact_id [String] The ID of the contact to update
88
+ # @param params [Hash] Updated contact parameters
89
+ # @return [Hash] Updated contact details
90
+ def update_contact(contact_id, params)
91
+ patch("/contacts/#{contact_id}", body: params)
92
+ end
93
+
94
+ # List all custom fields with pagination
95
+ #
96
+ # @param page [Integer] Page number for pagination
97
+ # @param per_page [Integer] Number of items per page
98
+ # @return [Array<Hash>] List of custom fields
99
+ def list_custom_fields(page: 1, per_page: 20)
100
+ get("/custom_fields", query: { page: page, per_page: per_page })
101
+ end
102
+
103
+ # Create a new custom field
104
+ #
105
+ # @param params [Hash] Custom field parameters
106
+ # @return [Hash] Created custom field details
107
+ def create_custom_field(params)
108
+ post("/custom_fields", body: params)
109
+ end
110
+
111
+ # Lists issues within a specified time range (max 30 days)
112
+ #
113
+ # @param start_time [String] Start time in RFC3339 format
114
+ # @param end_time [String] End time in RFC3339 format
115
+ # @param page [Integer] Page number for pagination
116
+ # @param per_page [Integer] Number of items per page
117
+ # @param filters [Hash] Additional filters to apply
118
+ # @return [Array<Hash>] List of issues
119
+ # @raise [ArgumentError] If start_time or end_time is missing
120
+ def list_issues(start_time:, end_time:, page: 1, per_page: 20, **filters)
121
+ raise ArgumentError, "start_time is required" unless start_time
122
+ raise ArgumentError, "end_time is required" unless end_time
123
+
124
+ get("/issues", query: filters.merge(
125
+ start_time: start_time,
126
+ end_time: end_time,
127
+ page: page,
128
+ per_page: per_page
129
+ ))
130
+ end
131
+
132
+ # Create a new issue
133
+ #
134
+ # @param params [Hash] Issue parameters
135
+ # @return [Hash] Created issue details
136
+ def create_issue(params)
137
+ post("/issues", body: params)
138
+ end
139
+
140
+ # Get details for a specific issue
141
+ #
142
+ # @param issue_id [String] The ID of the issue to retrieve
143
+ # @return [Hash] Issue details
144
+ def get_issue(issue_id)
145
+ get("/issues/#{issue_id}")
146
+ end
147
+
148
+ # Update an existing issue
149
+ #
150
+ # @param issue_id [String] The ID of the issue to update
151
+ # @param params [Hash] Updated issue parameters
152
+ # @return [Hash] Updated issue details
153
+ def update_issue(issue_id, params)
154
+ patch("/issues/#{issue_id}", body: params)
155
+ end
156
+
157
+ # List all knowledge base articles with pagination
158
+ #
159
+ # @param page [Integer] Page number for pagination
160
+ # @param per_page [Integer] Number of items per page
161
+ # @return [Array<Hash>] List of articles
162
+ def list_articles(page: 1, per_page: 20)
163
+ get("/knowledge_base/articles", query: { page: page, per_page: per_page })
164
+ end
165
+
166
+ # Get details for a specific article
167
+ #
168
+ # @param article_id [String] The ID of the article to retrieve
169
+ # @return [Hash] Article details
170
+ def get_article(article_id)
171
+ get("/knowledge_base/articles/#{article_id}")
172
+ end
173
+
174
+ # Get details for the current user
175
+ #
176
+ # @return [Hash] Current user details
177
+ def get_current_user
178
+ get("/me")
179
+ end
180
+
181
+ # List all tags with pagination
182
+ #
183
+ # @param page [Integer] Page number for pagination
184
+ # @param per_page [Integer] Number of items per page
185
+ # @return [Array<Hash>] List of tags
186
+ def list_tags(page: 1, per_page: 20)
187
+ get("/tags", query: { page: page, per_page: per_page })
188
+ end
189
+
190
+ # Create a new tag
191
+ #
192
+ # @param name [String] The name of the tag
193
+ # @param color [String] Optional hex color code for the tag
194
+ # @return [Hash] Created tag details
195
+ def create_tag(name:, color: nil)
196
+ post("/tags", body: { name: name, color: color }.compact)
197
+ end
198
+
199
+ # List all teams with pagination
200
+ #
201
+ # @param page [Integer] Page number for pagination
202
+ # @param per_page [Integer] Number of items per page
203
+ # @return [Array<Hash>] List of teams
204
+ def list_teams(page: 1, per_page: 20)
205
+ get("/teams", query: { page: page, per_page: per_page })
206
+ end
207
+
208
+ # Create a new team
209
+ #
210
+ # @param params [Hash] Team parameters
211
+ # @return [Hash] Created team details
212
+ def create_team(params)
213
+ post("/teams", body: params)
214
+ end
215
+
216
+ # Get details for a specific team
217
+ #
218
+ # @param team_id [String] The ID of the team to retrieve
219
+ # @return [Hash] Team details
220
+ def get_team(team_id)
221
+ get("/teams/#{team_id}")
222
+ end
223
+
224
+ # List all ticket forms with pagination
225
+ #
226
+ # @param page [Integer] Page number for pagination
227
+ # @param per_page [Integer] Number of items per page
228
+ # @return [Array<Hash>] List of ticket forms
229
+ def list_ticket_forms(page: 1, per_page: 20)
230
+ get("/ticket-forms", query: { page: page, per_page: per_page })
231
+ end
232
+
233
+ # Create a new ticket form
234
+ #
235
+ # @param name [String] The name of the form
236
+ # @param fields [Array<Hash>] Array of form field definitions
237
+ # @return [Hash] Created ticket form details
238
+ def create_ticket_form(name:, fields: [])
239
+ post("/ticket-forms", body: { name: name, fields: fields })
240
+ end
241
+
242
+ # List all user roles with pagination
243
+ #
244
+ # @param page [Integer] Page number for pagination
245
+ # @param per_page [Integer] Number of items per page
246
+ # @return [Array<Hash>] List of user roles
247
+ def list_user_roles(page: 1, per_page: 20)
248
+ get("/user_roles", query: { page: page, per_page: per_page })
249
+ end
250
+
251
+ # Get details for a specific user role
252
+ #
253
+ # @param role_id [String] The ID of the role to retrieve
254
+ # @return [Hash] Role details
255
+ def get_user_role(role_id)
256
+ get("/user_roles/#{role_id}")
257
+ end
258
+
259
+ # List all users with pagination
260
+ #
261
+ # @param page [Integer] Page number for pagination
262
+ # @param per_page [Integer] Number of items per page
263
+ # @return [Array<Hash>] List of users
264
+ def list_users(page: 1, per_page: 20)
265
+ get("/users", query: { page: page, per_page: per_page })
266
+ end
267
+
268
+ # Create a new user
269
+ #
270
+ # @param params [Hash] User parameters
271
+ # @return [Hash] Created user details
272
+ def create_user(params)
273
+ post("/users", body: params)
274
+ end
275
+
276
+ # Get details for a specific user
277
+ #
278
+ # @param user_id [String] The ID of the user to retrieve
279
+ # @return [Hash] User details
280
+ def get_user(user_id)
281
+ get("/users/#{user_id}")
282
+ end
283
+
284
+ # Update an existing user
285
+ #
286
+ # @param user_id [String] The ID of the user to update
287
+ # @param params [Hash] Updated user parameters
288
+ # @return [Hash] Updated user details
289
+ def update_user(user_id, params)
290
+ patch("/users/#{user_id}", body: params)
291
+ end
292
+
293
+ private
294
+
295
+ # @return [Faraday::Connection] Configured Faraday connection
296
+ def connection
297
+ @connection ||= Faraday.new(@base_url) do |f|
298
+ f.request :json
299
+ f.request :multipart
300
+ f.response :json
301
+ f.response :logger if @debug
302
+ f.adapter Faraday.default_adapter
303
+ f.headers["Authorization"] = "Bearer #{api_key}"
304
+ f.headers["Content-Type"] = "application/json"
305
+ f.headers["Accept"] = "application/json"
306
+ end
307
+ end
308
+
309
+ # Handle API response and raise appropriate errors
310
+ #
311
+ # @param response [Faraday::Response] The API response
312
+ # @return [Array] Array containing response data and response object
313
+ # @raise [AuthenticationError] If authentication fails
314
+ # @raise [ResourceNotFoundError] If resource is not found
315
+ # @raise [ValidationError] If request parameters are invalid
316
+ # @raise [ApiError] For other API errors
317
+ def handle_response(response)
318
+ if @debug
319
+ puts "Request URL: #{response.env.url}"
320
+ puts "Response status: #{response.status}"
321
+ puts "Response body: #{response.body.inspect}"
322
+ end
323
+
324
+ case response.status
325
+ when 200..299
326
+ data = response.body
327
+ data = data["data"] if data.is_a?(Hash) && data.key?("data")
328
+ [data, response]
329
+ when 401
330
+ raise AuthenticationError, parse_error_message(response)
331
+ when 404
332
+ raise ResourceNotFoundError, parse_error_message(response)
333
+ when 422
334
+ raise ValidationError, parse_error_message(response)
335
+ else
336
+ raise ApiError.new(parse_error_message(response), response)
337
+ end
338
+ end
339
+
340
+ # Parse error message from response
341
+ #
342
+ # @param response [Faraday::Response] The API response
343
+ # @return [String] Error message
344
+ def parse_error_message(response)
345
+ if response.body.is_a?(Hash)
346
+ response.body["errors"]&.first || response.body["error"] || "HTTP #{response.status}"
347
+ else
348
+ "HTTP #{response.status}"
349
+ end
350
+ end
351
+
352
+ # Make a GET request
353
+ #
354
+ # @param path [String] The API endpoint path
355
+ # @param query [Hash] Query parameters
356
+ # @return [Array] Array containing response data and response object
357
+ def get(path, query: {})
358
+ handle_response(connection.get(path, query))
359
+ end
360
+
361
+ # Make a POST request
362
+ #
363
+ # @param path [String] The API endpoint path
364
+ # @param body [Hash] Request body
365
+ # @return [Array] Array containing response data and response object
366
+ def post(path, body: {})
367
+ handle_response(connection.post(path, body.to_json))
368
+ end
369
+
370
+ # Make a PATCH request
371
+ #
372
+ # @param path [String] The API endpoint path
373
+ # @param body [Hash] Request body
374
+ # @return [Array] Array containing response data and response object
375
+ def patch(path, body: {})
376
+ handle_response(connection.patch(path, body.to_json))
377
+ end
378
+
379
+ # Make a DELETE request
380
+ #
381
+ # @param path [String] The API endpoint path
382
+ # @return [Array] Array containing response data and response object
383
+ def delete(path)
384
+ handle_response(connection.delete(path))
385
+ end
386
+ end
387
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pylon
4
+ # Major version for breaking changes
5
+ MAJOR = 0
6
+ # Minor version for new features
7
+ MINOR = 1
8
+ # Patch version for bug fixes
9
+ PATCH = 0
10
+ # Pre-release version (optional)
11
+ PRE = nil
12
+
13
+ # Version string following SemVer
14
+ # @return [String] The current version of the gem
15
+ VERSION = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
16
+ end
data/lib/pylon.rb ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday/multipart"
5
+ require "json"
6
+
7
+ require_relative "pylon/version"
8
+ require_relative "pylon/client"
9
+
10
+ module Pylon
11
+ class Error < StandardError; end
12
+ class AuthenticationError < Error; end
13
+ class ResourceNotFoundError < Error; end
14
+ class ValidationError < Error; end
15
+
16
+ class ApiError < Error
17
+ attr_reader :response
18
+
19
+ def initialize(message = nil, response = nil)
20
+ super(message)
21
+ @response = response
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ namespace :version do
6
+ desc "Display current version"
7
+ task :show do
8
+ require_relative "../pylon/version"
9
+ puts "Current version: #{Pylon::VERSION}"
10
+ end
11
+
12
+ %w[major minor patch].each do |part|
13
+ desc "Bump #{part} version"
14
+ task part.to_sym do
15
+ require_relative "../pylon/version"
16
+
17
+ # Read version.rb
18
+ version_file = File.read("lib/pylon/version.rb")
19
+
20
+ # Update the version constant
21
+ current_value = Pylon.const_get(part.upcase)
22
+ new_value = current_value + 1
23
+
24
+ # Reset lower-order versions for major/minor bumps
25
+ case part
26
+ when "major"
27
+ version_file.gsub!(/MINOR = \d+/, "MINOR = 0")
28
+ version_file.gsub!(/PATCH = \d+/, "PATCH = 0")
29
+ when "minor"
30
+ version_file.gsub!(/PATCH = \d+/, "PATCH = 0")
31
+ end
32
+
33
+ version_file.gsub!(/#{part.upcase} = \d+/, "#{part.upcase} = #{new_value}")
34
+
35
+ # Write the new version
36
+ File.write("lib/pylon/version.rb", version_file)
37
+
38
+ # Update CHANGELOG.md
39
+ changelog = File.read("CHANGELOG.md")
40
+ new_version = Pylon::VERSION.sub(/\d+$/, new_value.to_s)
41
+
42
+ changelog_entry = <<~ENTRY
43
+ ## [#{new_version}] - #{Date.today.strftime('%Y-%m-%d')}
44
+
45
+ ### #{part == 'patch' ? 'Fixed' : 'Added'}
46
+ - TODO: Add #{part} version changes
47
+
48
+ [#{new_version}]: https://github.com/benjodo/pylon-api/compare/v#{Pylon::VERSION}...v#{new_version}
49
+
50
+ ENTRY
51
+
52
+ # Split the changelog into parts
53
+ header, *rest = changelog.split(/^## \[\d/)
54
+
55
+ # Reconstruct the changelog with the new entry
56
+ updated_changelog = [
57
+ header,
58
+ changelog_entry,
59
+ rest.empty? ? "" : "## [#{rest.join('## [')}"
60
+ ].join
61
+
62
+ File.write("CHANGELOG.md", updated_changelog)
63
+
64
+ puts "Bumped #{part} version to #{new_version}"
65
+ puts "Don't forget to:"
66
+ puts "1. Update CHANGELOG.md with your changes"
67
+ puts "2. Commit the changes"
68
+ puts "3. Create and push a new tag: git tag -a v#{new_version} -m 'Version #{new_version}'"
69
+ end
70
+ end
71
+
72
+ desc "Add a pre-release identifier (e.g., alpha, beta, rc)"
73
+ task :pre, [:identifier] do |_t, args|
74
+ abort "Please provide a pre-release identifier (e.g., alpha, beta, rc)" unless args[:identifier]
75
+
76
+ version_file = File.read("lib/pylon/version.rb")
77
+ version_file.gsub!(/PRE = .*$/, "PRE = '#{args[:identifier]}'")
78
+
79
+ File.write("lib/pylon/version.rb", version_file)
80
+
81
+ require_relative "../pylon/version"
82
+ puts "Updated version to #{Pylon::VERSION}"
83
+ end
84
+
85
+ desc "Remove pre-release identifier"
86
+ task :release do
87
+ version_file = File.read("lib/pylon/version.rb")
88
+ version_file.gsub!(/PRE = .*$/, "PRE = nil")
89
+
90
+ File.write("lib/pylon/version.rb", version_file)
91
+
92
+ require_relative "../pylon/version"
93
+ puts "Updated version to #{Pylon::VERSION}"
94
+ end
95
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pylon-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Odom
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.12.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.12.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday-multipart
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.22.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.22.0
111
+ description: A Ruby client library for interacting with the Pylon REST API
112
+ email:
113
+ - support@aptible.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - CHANGELOG.md
119
+ - LICENSE
120
+ - README.md
121
+ - lib/pylon.rb
122
+ - lib/pylon/client.rb
123
+ - lib/pylon/version.rb
124
+ - lib/tasks/version.rake
125
+ homepage: https://github.com/benjodo/pylon-api
126
+ licenses:
127
+ - MIT
128
+ metadata:
129
+ homepage_uri: https://github.com/benjodo/pylon-api
130
+ source_code_uri: https://github.com/benjodo/pylon-api
131
+ changelog_uri: https://github.com/benjodo/pylon-api/blob/main/CHANGELOG.md
132
+ documentation_uri: https://docs.usepylon.com/pylon-docs/developer/api/api-reference
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 3.0.0
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 3.3.7
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: Ruby client for the Pylon API
152
+ test_files: []