logister-ruby 0.2.7 → 0.2.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbdcfea4a9984f610510aa30780b8d94a54059bf329c387e5b47997f805ecafb
4
- data.tar.gz: 242e70a27ab5bcebcc11b1c99ce6f3acf7164a5a0ad5e482afd107bfa4fb705f
3
+ metadata.gz: 533fd3675cc1afc26e61d5bb20220cdd2e3d2fd643d51f0492f6c377eaa1c532
4
+ data.tar.gz: fae0c653ea921eb9d394f7c03c337a60141acd265d6ae54cd166b06b9e1ed219
5
5
  SHA512:
6
- metadata.gz: 58f9a2d891eec80c14c18a40ced354cdd3b19c98e88b583d709943c3b2aeab73d5af208d050566cf1ef9fc023f547972180f381a4648d585c5cd841622d145d3
7
- data.tar.gz: 8175e3a5b27a40ced8c9844acd56ff460e0c9655bd514e14feb94ee9edec02cbdb1b6021ef9deb6411a3fb837891c935d812d032707124c5f32147ed52ca3083
6
+ metadata.gz: 94689cef817604ea72eba2c9413335588561c19d986e6a4f8dd880777bea84dbf03b40318e0ad1c8ad7fb7c5a6b87430c9509786dcdf31c9f9005b4cefc1756b
7
+ data.tar.gz: 1fcdca232672d5af22036584285737e9a75ea6d5d5c3d7269452ee645185d820e407c14ac5c330a5a58514a7c996d274666c2619dff3923f84c6ee1fcb4f5f2d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.2.8 - 2026-06-18
4
+
5
+ - Added first-class source context configuration (`repository`, `commit_sha`, and `branch`) with `LOGISTER_*` and GitHub Actions environment variable support.
6
+ - Added `Logister.record_deployment` for posting release-to-commit deployment records to Logister.
7
+
3
8
  ## v0.2.7 - 2026-05-22
4
9
 
5
10
  - Added `Logister.report_span` and opt-in Rails request span capture for request load waterfall charts.
data/README.md CHANGED
@@ -293,6 +293,33 @@ Practical Insights recipes:
293
293
 
294
294
  Keep dashboard dimensions stable and low-cardinality. Good custom attribute keys include `service`, `region`, `queue`, `route`, `tenant_tier`, `provider`, and `feature_flag`. Avoid raw IDs, emails, request bodies, SQL text, and per-user values as top-level Insights dimensions.
295
295
 
296
+ ## GitHub source context and deployments
297
+
298
+ When a Logister project is connected to a GitHub repository, set source context once so error frames and releases can resolve to the exact commit:
299
+
300
+ ```ruby
301
+ Logister.configure do |config|
302
+ config.repository = ENV["LOGISTER_REPOSITORY"] || ENV["GITHUB_REPOSITORY"]
303
+ config.commit_sha = ENV["LOGISTER_COMMIT_SHA"] || ENV["GITHUB_SHA"]
304
+ config.branch = ENV["LOGISTER_BRANCH"] || ENV["GITHUB_REF_NAME"]
305
+ end
306
+ ```
307
+
308
+ CI/CD can also record the release-to-commit mapping directly:
309
+
310
+ ```ruby
311
+ Logister.record_deployment(
312
+ release: "checkout@2026.06.18",
313
+ environment: "production",
314
+ repository: "acme/checkout",
315
+ commit_sha: "4f8c2d1a9b7e6c5d4a3b2c1d0e9f8a7b6c5d4e3f",
316
+ branch: "main",
317
+ workflow_run_url: "https://github.com/acme/checkout/actions/runs/123"
318
+ )
319
+ ```
320
+
321
+ `config.deployment_endpoint` defaults to the configured ingest endpoint with `/ingest_events` replaced by `/deployments`. Set `LOGISTER_DEPLOYMENT_ENDPOINT` when your deployment endpoint cannot be derived from `LOGISTER_ENDPOINT`.
322
+
296
323
  ## Documentation
297
324
 
298
325
  - Ruby integration docs: https://docs.logister.org/integrations/ruby/
@@ -305,15 +332,15 @@ Keep dashboard dimensions stable and low-cardinality. Good custom attribute keys
305
332
 
306
333
  ## Release
307
334
 
308
- This repo runs CI on commits and pull requests. Version tags run the release workflow so RubyGems and GitHub Releases stay aligned:
335
+ This repo runs CI on commits and pull requests. After CI passes on `main`, the release-from-main workflow creates the matching version tag. Version tags run the release workflow so RubyGems and GitHub Releases stay aligned:
309
336
 
310
337
  ```bash
311
338
  # 1) bump version in lib/logister/version.rb
312
339
  # 2) update CHANGELOG.md
313
340
  # 3) commit changes
314
- # 4) push a matching tag, for example:
315
- git tag -a v0.2.7 -m "Release logister-ruby v0.2.7"
316
- git push origin main v0.2.7
341
+ # 4) merge to main, or push a matching tag manually:
342
+ git tag -a v0.2.8 -m "Release logister-ruby v0.2.8"
343
+ git push origin main v0.2.8
317
344
  ```
318
345
 
319
346
  The `.github/workflows/release.yml` workflow verifies the tag matches `Logister::VERSION`, runs tests, builds the gem, publishes to RubyGems with trusted publishing, and then creates or updates the matching GitHub release from `CHANGELOG.md`.
@@ -17,9 +17,11 @@ module Logister
17
17
 
18
18
  # Cache values that are static for the lifetime of this client so we
19
19
  # don't allocate on every send_request call.
20
- @uri = URI.parse(@configuration.endpoint).freeze
21
- @use_ssl = @uri.scheme == 'https'
22
- @auth_header = "Bearer #{@configuration.api_key}".freeze
20
+ @uri = URI.parse(@configuration.endpoint).freeze
21
+ @deployment_uri = URI.parse(@configuration.deployment_endpoint).freeze
22
+ @use_ssl = @uri.scheme == 'https'
23
+ @deployment_use_ssl = @deployment_uri.scheme == 'https'
24
+ @auth_header = "Bearer #{@configuration.api_key}".freeze
23
25
  end
24
26
 
25
27
  def publish(payload)
@@ -31,6 +33,12 @@ module Logister
31
33
  enqueue(payload)
32
34
  end
33
35
 
36
+ def publish_deployment(payload)
37
+ return false unless ready?
38
+
39
+ publish_deployment_sync(payload)
40
+ end
41
+
34
42
  def flush(timeout: 2)
35
43
  return true unless @configuration.async
36
44
 
@@ -112,6 +120,22 @@ module Logister
112
120
  end
113
121
  end
114
122
 
123
+ def publish_deployment_sync(payload)
124
+ attempts = 0
125
+ begin
126
+ attempts += 1
127
+ send_deployment_request(payload)
128
+ rescue StandardError => e
129
+ if attempts <= @configuration.max_retries
130
+ sleep(@configuration.retry_base_interval * (2**(attempts - 1)))
131
+ retry
132
+ end
133
+
134
+ @configuration.logger.warn("logister deployment publish failed: #{e.class} #{e.message}")
135
+ false
136
+ end
137
+ end
138
+
115
139
  def send_request(payload)
116
140
  request = Net::HTTP::Post.new(@uri)
117
141
  request['Content-Type'] = CONTENT_TYPE
@@ -131,6 +155,25 @@ module Logister
131
155
  raise "HTTP #{response.code}"
132
156
  end
133
157
 
158
+ def send_deployment_request(payload)
159
+ request = Net::HTTP::Post.new(@deployment_uri)
160
+ request['Content-Type'] = CONTENT_TYPE
161
+ request['Authorization'] = @auth_header
162
+ request.body = { deployment: payload }.to_json
163
+
164
+ response = Net::HTTP.start(
165
+ @deployment_uri.host,
166
+ @deployment_uri.port,
167
+ use_ssl: @deployment_use_ssl,
168
+ open_timeout: @configuration.timeout_seconds,
169
+ read_timeout: @configuration.timeout_seconds
170
+ ) { |http| http.request(request) }
171
+
172
+ return true if response.is_a?(Net::HTTPSuccess)
173
+
174
+ raise "HTTP #{response.code}"
175
+ end
176
+
134
177
  def monotonic_now
135
178
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
136
179
  end
@@ -2,20 +2,26 @@ require 'logger'
2
2
 
3
3
  module Logister
4
4
  class Configuration
5
- attr_accessor :api_key, :endpoint, :environment, :service, :release, :enabled, :timeout_seconds, :logger,
5
+ attr_accessor :api_key, :endpoint, :environment, :service, :release,
6
+ :repository, :commit_sha, :branch, :enabled, :timeout_seconds, :logger,
6
7
  :ignore_exceptions, :ignore_environments, :ignore_paths, :before_notify,
7
8
  :async, :queue_size, :max_retries, :retry_base_interval,
8
9
  :capture_db_metrics, :db_metric_min_duration_ms, :db_metric_sample_rate,
9
10
  :feature_flags_resolver, :dependency_resolver, :anonymize_ip,
10
11
  :max_breadcrumbs, :max_dependencies, :capture_request_spans,
11
12
  :capture_sql_breadcrumbs, :sql_breadcrumb_min_duration_ms
13
+ attr_writer :deployment_endpoint
12
14
 
13
15
  def initialize
14
16
  @api_key = ENV['LOGISTER_API_KEY']
15
17
  @endpoint = ENV.fetch('LOGISTER_ENDPOINT', 'https://logister.org/api/v1/ingest_events')
18
+ @deployment_endpoint = env_value('LOGISTER_DEPLOYMENT_ENDPOINT')
16
19
  @environment = ENV.fetch('RAILS_ENV', ENV.fetch('RACK_ENV', 'development'))
17
20
  @service = ENV.fetch('LOGISTER_SERVICE', 'ruby-app')
18
21
  @release = ENV['LOGISTER_RELEASE']
22
+ @repository = env_value('LOGISTER_REPOSITORY') || env_value('GITHUB_REPOSITORY')
23
+ @commit_sha = env_value('LOGISTER_COMMIT_SHA') || env_value('GITHUB_SHA')
24
+ @branch = env_value('LOGISTER_BRANCH') || env_value('GITHUB_REF_NAME')
19
25
  @enabled = true
20
26
  @timeout_seconds = 2
21
27
  @logger = Logger.new($stdout)
@@ -44,5 +50,16 @@ module Logister
44
50
  @capture_sql_breadcrumbs = true
45
51
  @sql_breadcrumb_min_duration_ms = 25.0
46
52
  end
53
+
54
+ def deployment_endpoint
55
+ @deployment_endpoint || endpoint.to_s.sub(%r{/ingest_events\z}, '/deployments')
56
+ end
57
+
58
+ private
59
+
60
+ def env_value(name)
61
+ value = ENV[name].to_s.strip
62
+ value.empty? ? nil : value
63
+ end
47
64
  end
48
65
  end
@@ -24,12 +24,18 @@ module Logister
24
24
  environment = config&.respond_to?(:environment) ? config.environment.to_s.presence : nil
25
25
  service = config&.respond_to?(:service) ? config.service.to_s.presence : nil
26
26
  release = config&.respond_to?(:release) ? config.release.to_s.presence : nil
27
+ repository = config&.respond_to?(:repository) ? config.repository.to_s.presence : nil
28
+ commit_sha = config&.respond_to?(:commit_sha) ? config.commit_sha.to_s.presence : nil
29
+ branch = config&.respond_to?(:branch) ? config.branch.to_s.presence : nil
27
30
 
28
31
  {
29
32
  deployment: {
30
33
  environment: environment || ENV["RAILS_ENV"].to_s.presence || ENV["RACK_ENV"].to_s.presence || "development",
31
34
  service: service || ENV["LOGISTER_SERVICE"].to_s.presence || "ruby-app",
32
35
  release: release || ENV["LOGISTER_RELEASE"].to_s.presence,
36
+ repository: repository || ENV["LOGISTER_REPOSITORY"].to_s.presence || ENV["GITHUB_REPOSITORY"].to_s.presence,
37
+ commit_sha: commit_sha || ENV["LOGISTER_COMMIT_SHA"].to_s.presence || ENV["GITHUB_SHA"].to_s.presence,
38
+ branch: branch || ENV["LOGISTER_BRANCH"].to_s.presence || ENV["GITHUB_REF_NAME"].to_s.presence,
33
39
  region: ENV["FLY_REGION"].to_s.presence || ENV["RAILS_REGION"].to_s.presence || ENV["AWS_REGION"].to_s.presence,
34
40
  hostname: Socket.gethostname.to_s.presence,
35
41
  processPid: Process.pid
@@ -18,8 +18,11 @@ module Logister
18
18
  @static_context = {
19
19
  environment: @configuration.environment,
20
20
  service: @configuration.service,
21
- release: @configuration.release
22
- }.freeze
21
+ release: @configuration.release,
22
+ repository: @configuration.repository,
23
+ commit_sha: @configuration.commit_sha,
24
+ branch: @configuration.branch
25
+ }.compact.freeze
23
26
 
24
27
  # Normalise ignore_environments once into a frozen Set of Strings so
25
28
  # ignored_environment? never allocates a mapped Array.
@@ -235,6 +238,40 @@ module Logister
235
238
  @client.publish(payload)
236
239
  end
237
240
 
241
+ def record_deployment(
242
+ release: nil,
243
+ environment: nil,
244
+ repository: nil,
245
+ commit_sha: nil,
246
+ branch: nil,
247
+ deployed_at: nil,
248
+ pull_request_number: nil,
249
+ pull_request_url: nil,
250
+ release_tag: nil,
251
+ release_url: nil,
252
+ compare_url: nil,
253
+ workflow_run_url: nil,
254
+ deployment_url: nil
255
+ )
256
+ payload = {
257
+ release: release || @configuration.release,
258
+ environment: environment || @configuration.environment,
259
+ repository: repository || @configuration.repository,
260
+ commit_sha: commit_sha || @configuration.commit_sha,
261
+ branch: branch || @configuration.branch,
262
+ deployed_at: deployed_at && normalize_timestamp(deployed_at),
263
+ pull_request_number: pull_request_number,
264
+ pull_request_url: pull_request_url,
265
+ release_tag: release_tag,
266
+ release_url: release_url,
267
+ compare_url: compare_url,
268
+ workflow_run_url: workflow_run_url,
269
+ deployment_url: deployment_url
270
+ }.compact
271
+
272
+ @client.publish_deployment(payload)
273
+ end
274
+
238
275
  # Store user info for the current thread so it is automatically attached to
239
276
  # every error reported during this request.
240
277
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Logister
4
- VERSION = '0.2.7'
4
+ VERSION = '0.2.8'
5
5
  end
data/lib/logister.rb CHANGED
@@ -47,6 +47,10 @@ module Logister
47
47
  reporter.report_check_in(**kwargs)
48
48
  end
49
49
 
50
+ def record_deployment(**kwargs)
51
+ reporter.record_deployment(**kwargs)
52
+ end
53
+
50
54
  def flush(timeout: 2)
51
55
  reporter.flush(timeout: timeout)
52
56
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logister-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Logister