langfuse-ruby 0.2.0 → 0.2.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 +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +44 -0
- data/CLAUDE.md +40 -14
- data/Gemfile.lock +1 -1
- data/Makefile +1 -4
- data/README.md +216 -99
- data/Rakefile +0 -6
- data/docs/FINAL_SUMMARY.md +12 -185
- data/docs/PUBLISH_GUIDE.md +36 -272
- data/docs/README.md +12 -22
- data/docs/RELEASE_CHECKLIST.md +20 -145
- data/docs/V4.md +159 -0
- data/examples/basic_tracing.rb +11 -10
- data/examples/simplified_usage.rb +7 -6
- data/examples/v4_otel_tracing.rb +70 -0
- data/lib/langfuse/client.rb +457 -247
- data/lib/langfuse/event.rb +1 -17
- data/lib/langfuse/generation.rb +35 -120
- data/lib/langfuse/null_objects.rb +4 -0
- data/lib/langfuse/otel_exporter.rb +101 -11
- data/lib/langfuse/partial_updates.rb +30 -0
- data/lib/langfuse/prompt.rb +9 -83
- data/lib/langfuse/prompt_cache.rb +65 -0
- data/lib/langfuse/span.rb +28 -153
- data/lib/langfuse/span_wrappers.rb +32 -0
- data/lib/langfuse/template_compiler.rb +56 -0
- data/lib/langfuse/trace.rb +26 -162
- data/lib/langfuse/utils.rb +28 -26
- data/lib/langfuse/version.rb +1 -1
- data/lib/langfuse.rb +49 -52
- data/scripts/release.sh +12 -12
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 45de0f0dc3915b41c725f9099843bd6fd1e29d9a532a11a13bb65ca744a753fa
|
|
4
|
+
data.tar.gz: d04b31ebc438237d2462fec8e3c5e407f27548eb40c25164a7dc939d39942183
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7677e27533af07f139e14dc6d189d16c3d00a75a625d5058e332221b89d107e76206fadc9d1fd4175346eaab43cd11322f724aca87d61acffc1f267ec651d301
|
|
7
|
+
data.tar.gz: 2bb6e47d16ff17e62200f2da93e539549edaf329419bb352f6081d7983e813c30d03cf61b775f98f643fc7b199921def0e0944b8aaf717daa80a18de8bb8067e
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.1] - 2026-09-17
|
|
11
|
+
|
|
12
|
+
### Documentation
|
|
13
|
+
- README and examples now lead with **Langfuse v4** (`ingestion_mode: :otel`): OTLP ingestion, observations-first tracing, `usage_details` / `cost_details`, typed observations, and the Cloud cutoff of non-score `/api/public/ingestion` traffic on 16 November 2026
|
|
14
|
+
- Added [docs/V4.md](docs/V4.md) (attribute mapping, scores, cutover checklist) and `examples/v4_otel_tracing.rb`
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- **`Langfuse.trace` executed the block twice**: an exception raised inside the block was caught by the method-level `rescue` and the block was re-run with a `NullTrace` — duplicating LLM calls and their cost. Only trace creation degrades to `NullTrace` now; exceptions from the block propagate untouched
|
|
18
|
+
- **Typed API errors collapsed into `APIError`**: `AuthenticationError` / `RateLimitError` / `ValidationError` raised by `handle_response` were re-wrapped by the generic `rescue` in `#request`, so callers could not rescue them selectively
|
|
19
|
+
- **`Langfuse.configure` values for `timeout` / `retries` were ignored**: the `Client#initialize` defaults (30 / 3) shadowed the configured values
|
|
20
|
+
- **OTel mode dropped token usage**: only `promptTokens` / `completionTokens` were mapped. All legacy shapes (`promptTokens`, `inputTokens`, `input`) now map to `gen_ai.usage.*` and are normalized into `langfuse.observation.usage_details`, which is what Langfuse v4 uses for cost. Usage carrying a non-token `unit` is skipped instead of being reported as tokens
|
|
21
|
+
- **OTel mode produced duplicate observations**: the `*-create` and `*-update` events of one observation were exported as two spans sharing a span id, which the append-only v4 data model stores twice. They are collapsed into one span carrying the final state
|
|
22
|
+
- **OTel mode stringified structured attributes**: hashes and arrays (for example `model_parameters[:tools]`) were sent through Ruby's `inspect`; they are JSON-encoded now
|
|
23
|
+
- **OTel export leaked raw Faraday errors**: failures on the OTLP connection now surface as `TimeoutError` / `NetworkError` / `APIError`, matching the ingestion API path
|
|
24
|
+
- **`shutdown` killed the flush thread mid-send**: events already drained from the queue were lost. The thread is now signalled to stop and joined (5 s grace period, kill only as a fallback)
|
|
25
|
+
- **Flush thread was not fork-safe**: after `fork` (e.g. Puma workers) the child inherited a dead thread and the parent's queued events. Each process now recreates its own flush thread and drops inherited events instead of sending them twice
|
|
26
|
+
- **Permanently failing batches were re-queued forever**: a 4xx (validation/auth) failure re-queued the same events on every flush, blocking the queue. They are now dropped with a warning; transient failures (5xx, network) are still re-queued
|
|
27
|
+
- **Event queue races**: enqueue, the `trace-update` → `trace-create` merge, and the flush drain ran without a shared lock, so a concurrent flush could interleave with a merge. They are serialized by a queue mutex now
|
|
28
|
+
- **Prompt compilation re-expanded placeholders coming from variable values**: variables were substituted one after another, so a value containing `{{other_var}}` was expanded by a later round (user input could inject template syntax, and the result depended on hash order). All variables are now substituted in a single pass, and a value containing a placeholder stays literal
|
|
29
|
+
- **`Span#generation` and `Generation#generation` dropped `usage_details`, `cost_details` and `prompt`**: the parameters were missing from both signatures, so a generation created under a span or another generation silently lost its v4 cost data and prompt link (only `Trace#generation` forwarded them)
|
|
30
|
+
- **Retries hit non-retryable failures**: `#request` retried every error, so a 401 or a 422 was sent four times before failing. Only timeouts, network errors, 429 and 5xx are retried now
|
|
31
|
+
- **Retries ignored `Retry-After`**: a rate-limited request was retried on a fixed 1 s / 2 s / 3 s schedule regardless of the server's instruction, and all clients retried in lockstep because the delay carried no jitter
|
|
32
|
+
- **`Langfuse.get_prompt` retried twice over**: its own retry loop wrapped the HTTP layer's retries, so one call could issue up to nine requests (and a missing prompt was fetched three times before returning `nil`). Retries now happen in one place
|
|
33
|
+
- **An unknown `ingestion_mode` silently behaved like `:legacy`**: a typo such as `LANGFUSE_INGESTION_MODE=otlp` looked like a working v4 setup. The value is now normalized (`"OTEL"` → `:otel`) and validated, with a warning when it is not recognized
|
|
34
|
+
- **A flushed `trace-update` sent unprocessed `to_dict` output**: when the matching `trace-create` was already gone from the queue, the reconstructed body used symbol/snake_case keys and skipped environment injection and the `mask` callable, so the API could reject the event and PII could leave unredacted. The reconstruction now re-runs the same prepare/env/mask path as every other enqueue
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
- OTLP payloads are chunked to the 3.5 MB batch limit (previously only the ingestion API path was chunked)
|
|
38
|
+
- OTLP `partialSuccess` responses (HTTP 200 with rejected spans) are logged as warnings instead of silently losing data
|
|
39
|
+
- `max_queue_size` config (constructor / `Langfuse.configure` / `LANGFUSE_MAX_QUEUE_SIZE`, default 10,000): the event queue is bounded; when full, the oldest events are dropped with a rate-limited warning instead of growing memory without bound
|
|
40
|
+
- `get_prompt` resilience: when a refetch fails, the expired cache entry is served with a warning instead of raising (a Langfuse outage no longer breaks prompt resolution for previously fetched prompts). The prompt cache is now bounded (200 entries) and measures TTLs on the monotonic clock, so wall-clock jumps cannot extend or shorten entry lifetimes
|
|
41
|
+
- `Client#inspect` redacts the secret key, keeping it out of logs and console output
|
|
42
|
+
- `http_adapter` config (constructor / `Langfuse.configure`): selects the Faraday adapter, so a connection-pooling adapter such as `:net_http_persistent` can be used to keep the TLS connection alive between flushes. Defaults to Faraday's default adapter; an adapter whose gem is missing logs a warning and falls back instead of raising
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
- Retries are now applied only to transient failures (`TimeoutError`, `NetworkError`, `RateLimitError`, 5xx `APIError`), honor `Retry-After` (seconds or HTTP date, capped at 10 s), and otherwise back off exponentially from 0.5 s with ±50% jitter, capped at 10 s. `retries:` can be overridden per request
|
|
46
|
+
- Ingestion batches are serialized to JSON once and posted as a pre-encoded body; the per-event chunking path only runs when the batch exceeds the 3.5 MB limit (previously every batch was measured event by event and then re-encoded by Faraday)
|
|
47
|
+
- `*-update` events send only the fields that actually changed, plus the identifying ones, instead of the observation's full body. Ending a long generation no longer re-uploads its input and model parameters
|
|
48
|
+
- Enhanced observation wrappers (`agent`, `tool`, `chain`, `retriever`, `evaluator`, `guardrail`) are generated once in the new `Langfuse::SpanWrappers` module and shared by `Client`, `Trace`, `Span` and `Generation`, replacing 24 hand-written copies (~400 lines); an explicit `as_type:` passed by the caller no longer overrides the wrapper's type
|
|
49
|
+
- `Client#evaluator` is available as an alias of `Client#evaluator_obs`, so the helper has the same name as `Trace#evaluator` / `Span#evaluator` / `Generation#evaluator` (both names keep working)
|
|
50
|
+
- Placeholder compilation and variable extraction moved into the new `Langfuse::TemplateCompiler`, shared by `Prompt`, `PromptTemplate` and `ChatPromptTemplate` (previously four copies of the substitution loop and three of the variable scanner)
|
|
51
|
+
- `Trace`, `Span` and `Event` now serialize through `to_dict` when enqueuing `*-create` / `*-update` events instead of rebuilding the same hash in each method, so a field can no longer be added to one path and forgotten in the others
|
|
52
|
+
- `Utils.deep_stringify_keys` is now an alias of `Utils.deep_camelize_keys`: the two implementations were identical, and both camelize keys rather than only stringifying them
|
|
53
|
+
|
|
10
54
|
## [0.2.0] - 2026-07-18
|
|
11
55
|
|
|
12
56
|
### Added
|
data/CLAUDE.md
CHANGED
|
@@ -36,8 +36,8 @@ bundle exec rubocop
|
|
|
36
36
|
# Build the gem
|
|
37
37
|
bundle exec rake build
|
|
38
38
|
|
|
39
|
-
# Release
|
|
40
|
-
|
|
39
|
+
# Release: bump version + CHANGELOG, then `make tag VERSION=x.y.z`
|
|
40
|
+
# (pushes v* tag; GitHub Actions publishes to RubyGems)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
## Architecture
|
|
@@ -50,18 +50,28 @@ bundle exec rake release_gem
|
|
|
50
50
|
- **`Langfuse::Span`** ([lib/langfuse/span.rb](lib/langfuse/span.rb)) - Timed operation with enhanced type support.
|
|
51
51
|
- **`Langfuse::Generation`** ([lib/langfuse/generation.rb](lib/langfuse/generation.rb)) - LLM call tracking (supports `usage_details`/`cost_details` and prompt linking).
|
|
52
52
|
- **`Langfuse::Event`** ([lib/langfuse/event.rb](lib/langfuse/event.rb)) - Point-in-time events.
|
|
53
|
-
- **`Langfuse::
|
|
53
|
+
- **`Langfuse::SpanWrappers`** ([lib/langfuse/span_wrappers.rb](lib/langfuse/span_wrappers.rb)) - Generates the enhanced observation helpers (`agent`, `tool`, `chain`, `retriever`, `evaluator`, `guardrail`) for Client/Trace/Span/Generation as `#span` calls with a fixed `as_type`.
|
|
54
|
+
- **`Langfuse::Prompt`** ([lib/langfuse/prompt.rb](lib/langfuse/prompt.rb)) - Prompt templates.
|
|
55
|
+
- **`Langfuse::TemplateCompiler`** ([lib/langfuse/template_compiler.rb](lib/langfuse/template_compiler.rb)) - `{{var}}` / `{var}` substitution and variable extraction shared by `Prompt`, `PromptTemplate` and `ChatPromptTemplate`.
|
|
56
|
+
- **`Langfuse::PromptCache`** ([lib/langfuse/prompt_cache.rb](lib/langfuse/prompt_cache.rb)) - Bounded, thread-safe prompt cache used by `Client#get_prompt`: monotonic-clock TTLs, oldest-first eviction, stale reads for outage fallback.
|
|
57
|
+
- **`Langfuse::PartialUpdates`** ([lib/langfuse/partial_updates.rb](lib/langfuse/partial_updates.rb)) - Dirty tracking for `Trace`/`Span`/`Generation`: `update`/`end` record which fields the caller passed, and `update_body` slices `to_dict` down to those plus the identifying fields (`id`, `trace_id`, `type`).
|
|
54
58
|
- **`Langfuse::OtelExporter`** ([lib/langfuse/otel_exporter.rb](lib/langfuse/otel_exporter.rb)) - Maps Langfuse events to OTLP/HTTP JSON when `ingestion_mode: :otel`.
|
|
55
59
|
- **`Langfuse::NullTrace/NullGeneration/NullSpan`** ([lib/langfuse/null_objects.rb](lib/langfuse/null_objects.rb)) - Null objects for graceful degradation.
|
|
56
60
|
|
|
61
|
+
New projects should set `ingestion_mode: :otel` (Langfuse v4 / OTLP). The
|
|
62
|
+
default remains `:legacy` for compatibility; Cloud stops accepting non-score
|
|
63
|
+
`/api/public/ingestion` traffic on 16 November 2026. See [docs/V4.md](docs/V4.md).
|
|
64
|
+
|
|
57
65
|
### Simplified API (Recommended)
|
|
58
66
|
|
|
59
67
|
```ruby
|
|
68
|
+
Langfuse.configure { |c| c.ingestion_mode = :otel } # Langfuse v4
|
|
69
|
+
|
|
60
70
|
# Block-based tracing with automatic flush
|
|
61
71
|
Langfuse.trace("my-trace", user_id: "user-1") do |trace|
|
|
62
72
|
gen = trace.generation(name: "openai", model: "gpt-4", input: messages)
|
|
63
73
|
response = call_llm(...)
|
|
64
|
-
gen.end(output: response,
|
|
74
|
+
gen.end(output: response, usage_details: { input: 10, output: 20, total: 30 })
|
|
65
75
|
end # Auto flush!
|
|
66
76
|
|
|
67
77
|
# Get prompt with variables and retry
|
|
@@ -72,12 +82,15 @@ Langfuse.get_prompt("my-prompt", variables: { name: "Alice" }, retries: 3)
|
|
|
72
82
|
|
|
73
83
|
1. Observations (traces, spans, generations, events, scores) are created via Client methods
|
|
74
84
|
2. Bodies are prepared via `Utils.prepare_event_body` (top-level camelCase; user data under `input`/`output`/`metadata`/etc. is left verbatim), then environment injection, masking, and sampling are applied
|
|
75
|
-
3. Events are queued in `@event_queue` (thread-safe `Concurrent::Array`)
|
|
76
|
-
4. Background flush thread wakes on `flush_interval` **or** when the queue reaches `flush_at`
|
|
77
|
-
5.
|
|
78
|
-
|
|
79
|
-
- `:
|
|
80
|
-
|
|
85
|
+
3. Events are queued in `@event_queue` (thread-safe `Concurrent::Array`, guarded by `@queue_mutex`). The queue is bounded by `max_queue_size` (default 10,000); when full, the oldest events are dropped with a rate-limited warning. `trace-update` events merge into the queued `trace-create` under the same lock; if the create has already flushed, the update is converted to a create from `trace_ref.to_dict` and re-run through the same camelCase / environment / mask path
|
|
86
|
+
4. Background flush thread wakes on `flush_interval` **or** when the queue reaches `flush_at`. It is recreated after `fork` (events inherited from the parent are dropped; the parent still flushes them) and stopped gracefully on `shutdown` (signalled, joined with a 5 s grace period, killed only as a fallback)
|
|
87
|
+
5. `*-update` events carry only the changed fields (see `PartialUpdates`), so a long generation's input is not re-sent when it ends
|
|
88
|
+
6. Flush path depends on `ingestion_mode` (both paths chunk to 3.5 MB):
|
|
89
|
+
- `:legacy` → batched POST to `/api/public/ingestion`
|
|
90
|
+
- `:otel` → non-score events via OTLP `/api/public/otel/v1/traces`, after collapsing each observation's `*-create`/`*-update` events into one span (v4 is append-only, so exporting both would duplicate the observation); **scores always go through the ingestion API**, with IDs normalized to OTel hex so they attach correctly. On OTEL transport failure, the not-yet-sent chunks and the batch's score events are re-queued; `partialSuccess` responses are logged as warnings
|
|
91
|
+
- On failure both paths re-queue only for transient errors; permanent failures (4xx validation/auth) drop the batch with a warning so it cannot block the queue forever
|
|
92
|
+
- The legacy batch is serialized to JSON once and posted as a String; the per-event chunking path only runs when that payload exceeds 3.5 MB
|
|
93
|
+
7. Manual flush via `client.flush`; idempotent shutdown via `client.shutdown` (plus optional `at_exit` hook)
|
|
81
94
|
|
|
82
95
|
### Observation Types
|
|
83
96
|
|
|
@@ -92,21 +105,34 @@ Enhanced types are implemented as spans with `as_type` metadata sent to the API.
|
|
|
92
105
|
Client accepts config via:
|
|
93
106
|
1. Constructor parameters
|
|
94
107
|
2. `Langfuse.configure` block
|
|
95
|
-
3. Environment variables: `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_HOST` / `LANGFUSE_BASE_URL`, `LANGFUSE_FLUSH_INTERVAL`, `LANGFUSE_FLUSH_AT`, `LANGFUSE_AUTO_FLUSH`, `LANGFUSE_TRACING_ENVIRONMENT`, `LANGFUSE_SAMPLE_RATE`, `LANGFUSE_DEBUG`, `LANGFUSE_INGESTION_MODE`
|
|
108
|
+
3. Environment variables: `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_HOST` / `LANGFUSE_BASE_URL`, `LANGFUSE_FLUSH_INTERVAL`, `LANGFUSE_FLUSH_AT`, `LANGFUSE_MAX_QUEUE_SIZE`, `LANGFUSE_AUTO_FLUSH`, `LANGFUSE_TRACING_ENVIRONMENT`, `LANGFUSE_SAMPLE_RATE`, `LANGFUSE_DEBUG`, `LANGFUSE_INGESTION_MODE` (`otel` for v4, `legacy` for pre-v4)
|
|
109
|
+
|
|
110
|
+
Default host is `https://us.cloud.langfuse.com`. Default `ingestion_mode` is `:legacy`; use `:otel` for Langfuse v4.
|
|
111
|
+
|
|
112
|
+
`http_adapter` is constructor/`configure`-only (no env var), since the adapter has to be in the app's `Gemfile` anyway.
|
|
96
113
|
|
|
97
114
|
### Error Handling
|
|
98
115
|
|
|
99
116
|
Custom exceptions in [lib/langfuse/errors.rb](lib/langfuse/errors.rb):
|
|
100
117
|
- `AuthenticationError`, `APIError`, `NetworkError`, `ValidationError`, `RateLimitError`, `TimeoutError`
|
|
101
118
|
|
|
102
|
-
Graceful degradation: When
|
|
119
|
+
Graceful degradation: When trace creation fails, `Langfuse.trace` yields a `NullTrace` that silently no-ops all operations. Only creation is rescued — an exception raised by the block propagates and the block is never re-run (re-running it would duplicate LLM calls).
|
|
120
|
+
|
|
121
|
+
Retries live in `Client#request` only: `TimeoutError`, `NetworkError`, `RateLimitError` and 5xx `APIError` are retried up to `retries` times (per-call override via `retries:`), honoring `Retry-After` (seconds or HTTP date, capped at `MAX_RETRY_DELAY_SECONDS`) and otherwise backing off exponentially from `RETRY_BASE_DELAY_SECONDS` with ±50% jitter. `Langfuse.get_prompt` passes `retries:` down instead of running its own loop (the two used to multiply).
|
|
103
122
|
|
|
104
123
|
## Key Implementation Details
|
|
105
124
|
|
|
106
|
-
- Uses Faraday for HTTP with Basic Auth (public_key:secret_key)
|
|
125
|
+
- Uses Faraday for HTTP with Basic Auth (public_key:secret_key); `http_adapter` selects the adapter (e.g. `:net_http_persistent` for keep-alive) and falls back to `Faraday.default_adapter` with a warning when the adapter's gem is missing
|
|
107
126
|
- Prompt names with special characters are auto-URL-encoded via `Utils.url_encode`
|
|
108
|
-
- `trace-update` events merge into
|
|
127
|
+
- `trace-update` events merge into the queued `trace-create` under `@queue_mutex` (deduplication without flush races). A reconstruction from `trace_ref` (create already flushed) goes through `prepare_queued_body` so keys stay camelCase, the default environment is injected, and the mask still applies
|
|
128
|
+
- `get_prompt` caches via `PromptCache`: on refetch failure the stale entry is served with a warning rather than raising
|
|
129
|
+
- `Client#inspect` redacts the secret key
|
|
130
|
+
- The enhanced observation wrappers are generated by `SpanWrappers#define_span_wrappers` (Client names the evaluator helper `evaluator_obs` and aliases `evaluator` to it); `embedding` stays hand-written in each class because it folds model/usage into metadata
|
|
131
|
+
- `Trace`/`Span`/`Event` enqueue `to_dict`, so `to_dict` is the single place a body field is defined (`Generation` already worked this way)
|
|
132
|
+
- `TemplateCompiler.compile` substitutes all variables in one pass over the template, so a variable value containing `{{...}}` is never expanded again; unknown placeholders are left untouched
|
|
109
133
|
- Event bodies use `Utils.prepare_event_body` (top-level camelCase only; nested user data is not mangled)
|
|
110
134
|
- Process-wide singleton client via `Langfuse::CLIENT_MUTEX` (not thread-local); use `Langfuse.new` for isolated clients in tests
|
|
111
135
|
- In OTel mode, IDs are W3C hex (`generate_trace_id` / `generate_observation_id`); scores normalize refs via `OtelExporter.to_otel_trace_id` / `to_otel_span_id`
|
|
136
|
+
- In OTel mode, a legacy `usage` object is normalized into `langfuse.observation.usage_details` (v4's cost model) unless `usage_details` was set explicitly; non-token `unit`s are skipped
|
|
137
|
+
- Typed errors from `handle_response` keep their class through `#request`; only unexpected errors are wrapped in `APIError`
|
|
112
138
|
- `get_prompt` supports configurable retries with exponential backoff
|
data/Gemfile.lock
CHANGED
data/Makefile
CHANGED
|
@@ -30,9 +30,6 @@ lint-fix: ## Run RuboCop with auto-correct
|
|
|
30
30
|
build: ## Build the gem
|
|
31
31
|
bundle exec rake build
|
|
32
32
|
|
|
33
|
-
release: tag ## Release: tag + build + push to RubyGems
|
|
34
|
-
bundle exec rake release_gem
|
|
35
|
-
|
|
36
33
|
clean: ## Remove built gem files
|
|
37
34
|
rm -f langfuse-ruby-*.gem
|
|
38
35
|
rm -rf pkg/
|
|
@@ -40,7 +37,7 @@ clean: ## Remove built gem files
|
|
|
40
37
|
console: ## Start an IRB console with the gem loaded
|
|
41
38
|
bundle exec irb -r langfuse
|
|
42
39
|
|
|
43
|
-
tag: ## Create and push a version tag. Usage: make tag
|
|
40
|
+
tag: ## Create and push a version tag. Usage: make tag VERSION=x.y.z
|
|
44
41
|
@git fetch --tags; \
|
|
45
42
|
if [ -z "$(VERSION)" ]; then \
|
|
46
43
|
LATEST=$$(git tag -l 'v[0-9]*' --sort=-v:refname | head -n1); \
|