Skip to content

feat(trogon-sink-github): add webhook receiver that sinks events to NATS JetStream#79

Merged
yordis merged 1 commit intomainfrom
github
Apr 2, 2026
Merged

feat(trogon-sink-github): add webhook receiver that sinks events to NATS JetStream#79
yordis merged 1 commit intomainfrom
github

Conversation

@yordis
Copy link
Copy Markdown
Member

@yordis yordis commented Apr 1, 2026

Summary

  • Add trogon-sink-github crate: an axum webhook receiver that validates GitHub signatures, maps events to NATS subjects (github.<event>), and publishes to JetStream with deduplication via Nats-Msg-Id header (X-GitHub-Delivery UUID)
  • router and serve are generic over JetStreamPublisher / JetStreamContext traits — concrete NatsJetStreamClient wired only in main, enabling full test coverage without #[cfg(not(coverage))] gates on library code
  • Box JetStreamPublisher::publish_with_headers return type (PublishFuture<'a, T>) to satisfy axum's Handler Send bounds with generic handlers
  • Production-grade Dockerfile with cargo-chef layer caching, stripped binary, pinned base images, non-root user, STOPSIGNAL SIGTERM, and health check
  • Add smee.io webhook proxy to Docker Compose (dev profile) with how-to guide for local GitHub App webhook development
  • Use bytesize::ByteSize for max_body_size config instead of raw usize
  • Use SDK's async_nats::header::NATS_MESSAGE_ID instead of custom constant
  • SignatureError properly implements Error::source() for InvalidHex variant

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 1, 2026

PR Summary

Medium Risk
Introduces a new internet-facing webhook receiver with signature verification and JetStream publishing, plus Docker Compose wiring; errors or misconfig could drop/duplicate events or expose an unauthenticated endpoint if misused.

Overview
Adds a new trogon-sink-github Rust service that receives POST /webhook, verifies X-Hub-Signature-256, and publishes the raw payload to NATS JetStream under {prefix}.{event} with delivery/event headers and Nats-Msg-Id set from X-GitHub-Delivery (plus /health, body-size limiting, stream auto-provisioning, and ack timeout handling).

Updates trogon-nats JetStream traits/mocks to better support generic publishers (Send-safe ack futures and exposing full published messages), and registers the new binary in acp-telemetry service names.

Extends local Docker Compose to run JetStream-enabled NATS, build/run trogon-sink-github, and optionally proxy GitHub webhooks via smee-client (dev profile), alongside new .dockerignore, Dockerfile, and local webhook setup docs.

Written by Cursor Bugbot for commit 5c33189. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new trogon-sink-github crate and binary (GitHub webhook receiver), NATS JetStream provisioning/publish flow, HMAC-SHA256 signature verification, configuration/constants, Dockerfile and compose entries, a .dockerignore, tests, telemetry enum variant, and a mock publisher accessor.

Changes

Cohort / File(s) Summary
Docker & Compose
rsworkspace/.dockerignore, devops/docker/compose/compose.yml, rsworkspace/crates/trogon-sink-github/Dockerfile
Add .dockerignore; enable NATS HTTP port and healthcheck in compose; add trogon-sink-github service with healthcheck and restart policy; add multi-stage Dockerfile with non-root runtime and container healthcheck.
New Crate: trogon-sink-github
rsworkspace/crates/trogon-sink-github/Cargo.toml, .../src/lib.rs, .../src/main.rs, .../src/constants.rs, .../src/config.rs, .../src/server.rs, .../src/signature.rs
Introduce crate and binary: env-driven GithubConfig and defaults, HMAC-SHA256 signature verification, Axum HTTP server (/webhook, /health), JetStream provisioning/publish/ack handling, request size limiting, extensive unit tests, and crate re-exports.
Telemetry & Test Mocks
rsworkspace/crates/acp-telemetry/src/service_name.rs, rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
Add ServiceName::TrogonSinkGithub and MockJetStreamPublisher::published_messages() accessor for test inspection.

Sequence Diagram(s)

sequenceDiagram
    participant GH as GitHub
    participant S as trogon-sink-github<br/>HTTP Server
    participant JS as NATS<br/>JetStream
    participant Sub as Downstream<br/>Subscriber

    GH->>S: POST /webhook (headers, body)
    S->>S: Verify x-hub-signature-256 (HMAC-SHA256)
    alt invalid signature
        S-->>GH: 401 Unauthorized
    else valid signature
        S->>JS: Publish to subject {prefix}.{event} with headers & payload
        JS->>JS: Accept/store message and ACK
        alt ACK success
            S-->>GH: 200 OK
            JS->>Sub: Deliver message
        else ACK timeout/failure
            S-->>GH: 500 Internal Server Error
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

rust:coverage-baseline-reset

Poem

🐰 I hopped a webhook through the night,
HMAC checked with moonbeam light,
JetStream stored each crunchy bite,
NATS hummed on, the routing right,
Rabbits cheer — the system's tight.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change—adding a new webhook receiver crate that sinks GitHub events to NATS JetStream.
Description check ✅ Passed The description directly relates to the changeset, covering the new crate's core functionality, composable API, and test coverage.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch github

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@yordis yordis force-pushed the github branch 6 times, most recently from b1c9669 to 2155563 Compare April 1, 2026 22:55
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
rsworkspace/crates/trogon-github/Dockerfile (1)

9-9: Use --locked for reproducible image builds.

Line 9 should enforce Cargo.lock usage to prevent drift during container builds.

Proposed change
-RUN cargo build --release -p trogon-github
+RUN cargo build --locked --release -p trogon-github
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-github/Dockerfile` at line 9, The Dockerfile's
build step uses "RUN cargo build --release -p trogon-github" without locking
dependencies, which can cause non-reproducible builds; update that RUN
invocation to include the --locked flag (i.e., run cargo build --release
--locked -p trogon-github) so Cargo uses Cargo.lock during image builds and
prevents dependency drift.
rsworkspace/crates/trogon-github/tests/webhook_e2e.rs (2)

43-47: Consider using port 0 for dynamic allocation in test helpers.

The static PORT_COUNTER starting at 28000 could theoretically collide with other services. While unlikely in CI, using port 0 with TcpListener::bind("127.0.0.1:0") and retrieving the assigned port would be more robust. However, since the server binds internally and wait_for_port polls, this approach works and is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-github/tests/webhook_e2e.rs` around lines 43 - 47,
Replace the manual static port counter (PORT_COUNTER and next_port) with dynamic
allocation via the OS: create a TcpListener bound to "127.0.0.1:0" to obtain the
assigned port and use that port for starting the test server (or return it from
the helper that previously called next_port); remove or stop using PORT_COUNTER
and next_port and update any callers (and wait_for_port usage) to accept the
listener-assigned port so tests no longer risk port collisions.

954-985: Consider adding #[cfg(unix)] to signal tests for consistency with workspace patterns.

The kill -TERM and kill -INT commands at lines 963-966 and 1008-1011 are Unix-specific. While no Windows CI is currently configured in the repository, the codebase uses #[cfg(unix)] guards elsewhere (e.g., rsworkspace/crates/acp-telemetry/src/signal.rs). Adding similar guards here improves consistency and prevents accidental test failures if platform support changes in the future.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-github/tests/webhook_e2e.rs` around lines 954 -
985, The test that sends Unix signals uses std::process::Command::new("kill")
and is Unix-specific; add #[cfg(unix)] above the async test functions that
invoke kill (e.g., server_exits_cleanly_on_sigterm and the sibling test that
sends SIGINT) so they only run on Unix platforms, leaving the tokio::test
attribute and the body (pid = child.id(), Command::new("kill") calls, and
child.wait() logic) unchanged.
rsworkspace/crates/trogon-github/src/config.rs (1)

22-31: Consider domain-specific value objects for subject_prefix and stream_name.

Per coding guidelines, domain-specific value objects are preferred over primitives. NATS subjects and JetStream stream names have validity constraints (e.g., no spaces, specific character sets). Wrapping these in validated types like SubjectPrefix and StreamName would catch invalid configurations at startup rather than at runtime when NATS rejects them.

This can be deferred since NATS provides runtime validation, but it would improve the fail-fast behavior. As per coding guidelines: "Prefer domain-specific value objects over primitives (e.g., AcpPrefix not String), with each type's factory guaranteeing correctness at construction."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-github/src/config.rs` around lines 22 - 31, The
fields subject_prefix and stream_name on GithubConfig are raw Strings but should
be domain-specific validated types to fail fast; introduce value objects (e.g.,
SubjectPrefix and StreamName) with constructors/TryFrom/FromStr and serde
deserialization that enforce NATS/JetStream name rules (no spaces, allowed
chars, length limits), replace GithubConfig::subject_prefix: String and
::stream_name: String with these new types, update any code that constructs or
reads GithubConfig (parsing from env/files) to validate at startup and convert
strings into SubjectPrefix/StreamName, and adjust usages of those fields to call
the new types' accessors or AsRef<str> so NATS clients get already-validated
values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rsworkspace/crates/trogon-github/src/main.rs`:
- Around line 18-31: After constructing the config with
GithubConfig::from_env(&SystemEnv), add a startup guard that ensures the GitHub
webhook secret is present and non-empty (check the config field that holds the
secret, e.g., config.github_webhook_secret or by reading
std::env::var("GITHUB_WEBHOOK_SECRET") if the config does not expose it); if the
secret is missing/empty, log an error (using error! with context) and return
ExitCode::FAILURE immediately before calling serve(config, nats). This ensures
the process fails fast rather than starting with webhook auth unenforced.

---

Nitpick comments:
In `@rsworkspace/crates/trogon-github/Dockerfile`:
- Line 9: The Dockerfile's build step uses "RUN cargo build --release -p
trogon-github" without locking dependencies, which can cause non-reproducible
builds; update that RUN invocation to include the --locked flag (i.e., run cargo
build --release --locked -p trogon-github) so Cargo uses Cargo.lock during image
builds and prevents dependency drift.

In `@rsworkspace/crates/trogon-github/src/config.rs`:
- Around line 22-31: The fields subject_prefix and stream_name on GithubConfig
are raw Strings but should be domain-specific validated types to fail fast;
introduce value objects (e.g., SubjectPrefix and StreamName) with
constructors/TryFrom/FromStr and serde deserialization that enforce
NATS/JetStream name rules (no spaces, allowed chars, length limits), replace
GithubConfig::subject_prefix: String and ::stream_name: String with these new
types, update any code that constructs or reads GithubConfig (parsing from
env/files) to validate at startup and convert strings into
SubjectPrefix/StreamName, and adjust usages of those fields to call the new
types' accessors or AsRef<str> so NATS clients get already-validated values.

In `@rsworkspace/crates/trogon-github/tests/webhook_e2e.rs`:
- Around line 43-47: Replace the manual static port counter (PORT_COUNTER and
next_port) with dynamic allocation via the OS: create a TcpListener bound to
"127.0.0.1:0" to obtain the assigned port and use that port for starting the
test server (or return it from the helper that previously called next_port);
remove or stop using PORT_COUNTER and next_port and update any callers (and
wait_for_port usage) to accept the listener-assigned port so tests no longer
risk port collisions.
- Around line 954-985: The test that sends Unix signals uses
std::process::Command::new("kill") and is Unix-specific; add #[cfg(unix)] above
the async test functions that invoke kill (e.g., server_exits_cleanly_on_sigterm
and the sibling test that sends SIGINT) so they only run on Unix platforms,
leaving the tokio::test attribute and the body (pid = child.id(),
Command::new("kill") calls, and child.wait() logic) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 378d9a8e-ccde-4c92-92d2-6556170c5f53

📥 Commits

Reviewing files that changed from the base of the PR and between c70081c and 1a013ee.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • rsworkspace/.dockerignore
  • rsworkspace/crates/trogon-github/Cargo.toml
  • rsworkspace/crates/trogon-github/Dockerfile
  • rsworkspace/crates/trogon-github/docker-compose.yml
  • rsworkspace/crates/trogon-github/src/config.rs
  • rsworkspace/crates/trogon-github/src/constants.rs
  • rsworkspace/crates/trogon-github/src/lib.rs
  • rsworkspace/crates/trogon-github/src/main.rs
  • rsworkspace/crates/trogon-github/src/server.rs
  • rsworkspace/crates/trogon-github/src/signature.rs
  • rsworkspace/crates/trogon-github/tests/webhook_e2e.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs

@yordis yordis force-pushed the github branch 2 times, most recently from fe5c27f to 2422a39 Compare April 1, 2026 23:03
@yordis yordis changed the title feat(trogon-github): GitHub webhook receiver → NATS JetStream feat(trogon-sink-github): GitHub webhook receiver → NATS JetStream Apr 1, 2026
@yordis yordis force-pushed the github branch 2 times, most recently from a012ba4 to 490aa4e Compare April 1, 2026 23:10
@yordis yordis changed the title feat(trogon-sink-github): GitHub webhook receiver → NATS JetStream feat(trogon-sink-github): add webhook receiver that sinks events to NATS JetStream Apr 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

badge

Code Coverage Summary

Details
Filename                                                                      Stmts    Miss  Cover    Missing
--------------------------------------------------------------------------  -------  ------  -------  ---------------------------------------------------------------------------------------------
crates/acp-nats/src/telemetry/metrics.rs                                         65       0  100.00%
crates/trogon-nats/src/connect.rs                                                96      16  83.33%   22-24, 37, 49, 68-151
crates/trogon-nats/src/messaging.rs                                             528       2  99.62%   132, 142
crates/trogon-nats/src/nats_token.rs                                            161       0  100.00%
crates/trogon-nats/src/token.rs                                                   8       0  100.00%
crates/trogon-nats/src/client.rs                                                 25      25  0.00%    50-89
crates/trogon-nats/src/mocks.rs                                                 304       0  100.00%
crates/trogon-nats/src/auth.rs                                                  114       3  97.37%   45-47
crates/acp-nats/src/nats/subjects/subscriptions/global_all.rs                    11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_session.rs                   11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_client.rs                    11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_agent.rs                     11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_session.rs                   18       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_agent.rs                     18       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_client.rs                    18       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_agent_ext.rs                 11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/prompt_wildcard.rs               11       0  100.00%
crates/acp-nats/src/client/ext_session_prompt_response.rs                       157       0  100.00%
crates/acp-nats/src/client/mod.rs                                              2987       0  100.00%
crates/acp-nats/src/client/terminal_kill.rs                                     309       0  100.00%
crates/acp-nats/src/client/request_permission.rs                                338       0  100.00%
crates/acp-nats/src/client/terminal_release.rs                                  357       0  100.00%
crates/acp-nats/src/client/ext.rs                                               365       8  97.81%   193-204, 229-240
crates/acp-nats/src/client/fs_write_text_file.rs                                451       0  100.00%
crates/acp-nats/src/client/rpc_reply.rs                                          71       0  100.00%
crates/acp-nats/src/client/session_update.rs                                     55       0  100.00%
crates/acp-nats/src/client/terminal_create.rs                                   294       0  100.00%
crates/acp-nats/src/client/terminal_output.rs                                   223       0  100.00%
crates/acp-nats/src/client/terminal_wait_for_exit.rs                            396       0  100.00%
crates/acp-nats/src/client/fs_read_text_file.rs                                 384       0  100.00%
crates/acp-nats/src/jetstream/streams.rs                                        194       4  97.94%   254-256, 266
crates/acp-nats/src/jetstream/consumers.rs                                       99       0  100.00%
crates/acp-nats/src/jetstream/ext_policy.rs                                      26       0  100.00%
crates/acp-nats/src/jetstream/provision.rs                                       61       0  100.00%
crates/acp-nats/src/agent/list_sessions.rs                                       50       0  100.00%
crates/acp-nats/src/agent/ext_notification.rs                                    88       0  100.00%
crates/acp-nats/src/agent/fork_session.rs                                       106       0  100.00%
crates/acp-nats/src/agent/authenticate.rs                                        52       0  100.00%
crates/acp-nats/src/agent/mod.rs                                                 65       0  100.00%
crates/acp-nats/src/agent/test_support.rs                                       299       0  100.00%
crates/acp-nats/src/agent/close_session.rs                                       67       0  100.00%
crates/acp-nats/src/agent/load_session.rs                                       101       0  100.00%
crates/acp-nats/src/agent/prompt.rs                                             633       0  100.00%
crates/acp-nats/src/agent/resume_session.rs                                     102       0  100.00%
crates/acp-nats/src/agent/new_session.rs                                         91       0  100.00%
crates/acp-nats/src/agent/set_session_mode.rs                                    71       0  100.00%
crates/acp-nats/src/agent/set_session_model.rs                                   71       0  100.00%
crates/acp-nats/src/agent/js_request.rs                                         304       0  100.00%
crates/acp-nats/src/agent/bridge.rs                                             123       4  96.75%   109-112
crates/acp-nats/src/agent/ext_method.rs                                          92       0  100.00%
crates/acp-nats/src/agent/logout.rs                                              49       0  100.00%
crates/acp-nats/src/agent/set_session_config_option.rs                           71       0  100.00%
crates/acp-nats/src/agent/initialize.rs                                          83       0  100.00%
crates/acp-nats/src/agent/cancel.rs                                             105       0  100.00%
crates/acp-nats/src/nats/mod.rs                                                  23       0  100.00%
crates/acp-nats/src/nats/extensions.rs                                            3       0  100.00%
crates/acp-nats/src/nats/parsing.rs                                             285       1  99.65%   153
crates/acp-telemetry/src/log.rs                                                  70       2  97.14%   39-40
crates/acp-telemetry/src/trace.rs                                                32       4  87.50%   23-24, 31-32
crates/acp-telemetry/src/lib.rs                                                 153      22  85.62%   39-46, 81, 86, 91, 105-120
crates/acp-telemetry/src/service_name.rs                                         20       0  100.00%
crates/acp-telemetry/src/metric.rs                                               35       4  88.57%   30-31, 38-39
crates/acp-telemetry/src/signal.rs                                                3       3  0.00%    4-43
crates/trogon-std/src/env/in_memory.rs                                           81       0  100.00%
crates/trogon-std/src/env/system.rs                                              17       0  100.00%
crates/acp-nats-ws/src/main.rs                                                  187      18  90.37%   87, 204-225, 303
crates/acp-nats-ws/src/upgrade.rs                                                57       2  96.49%   59, 90
crates/acp-nats-ws/src/config.rs                                                 83       0  100.00%
crates/acp-nats-ws/src/connection.rs                                            166      35  78.92%   75-82, 87-98, 114, 116-117, 122, 133-135, 142, 146, 150, 153-161, 172, 176, 179, 182-186, 220
crates/acp-nats/src/nats/subjects/responses/response.rs                          20       0  100.00%
crates/acp-nats/src/nats/subjects/responses/cancelled.rs                         18       0  100.00%
crates/acp-nats/src/nats/subjects/responses/ext_ready.rs                         15       0  100.00%
crates/acp-nats/src/nats/subjects/responses/update.rs                            27       0  100.00%
crates/acp-nats/src/nats/subjects/responses/prompt_response.rs                   27       0  100.00%
crates/trogon-std/src/args.rs                                                    10       0  100.00%
crates/trogon-std/src/json.rs                                                    30       0  100.00%
crates/trogon-sink-github/src/config.rs                                         104       0  100.00%
crates/trogon-sink-github/src/main.rs                                             4       0  100.00%
crates/trogon-sink-github/src/server.rs                                         390       0  100.00%
crates/trogon-sink-github/src/signature.rs                                       64       0  100.00%
crates/trogon-std/src/time/system.rs                                             24       0  100.00%
crates/trogon-std/src/time/mock.rs                                              123       0  100.00%
crates/acp-nats-stdio/src/main.rs                                               141      27  80.85%   62, 114-121, 127-129, 146, 177-198
crates/acp-nats-stdio/src/config.rs                                              72       0  100.00%
crates/acp-nats/src/nats/subjects/global/initialize.rs                            8       0  100.00%
crates/acp-nats/src/nats/subjects/global/authenticate.rs                          8       0  100.00%
crates/acp-nats/src/nats/subjects/global/logout.rs                                8       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext.rs                                  12       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext_notify.rs                           12       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_list.rs                          8       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_new.rs                           8       0  100.00%
crates/acp-nats-agent/src/connection.rs                                        1434       1  99.93%   686
crates/acp-nats/src/nats/subjects/commands/set_mode.rs                           18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/close.rs                              18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/prompt.rs                             18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/cancel.rs                             18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/fork.rs                               18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/resume.rs                             18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_model.rs                          18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/load.rs                               18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_config_option.rs                  18       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/session_request_permission.rs       15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_create.rs                  15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_kill.rs                    15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_wait_for_exit.rs           15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/fs_write_text_file.rs               15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/fs_read_text_file.rs                15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/session_update.rs                   15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_release.rs                 15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_output.rs                  15       0  100.00%
crates/acp-nats/src/nats/subjects/mod.rs                                        380       0  100.00%
crates/acp-nats/src/nats/subjects/stream.rs                                      58       0  100.00%
crates/trogon-std/src/fs/system.rs                                               29      12  58.62%   17-19, 31-45
crates/trogon-std/src/fs/mem.rs                                                 220      10  95.45%   61-63, 77-79, 133-135, 158
crates/trogon-nats/src/jetstream/mocks.rs                                       474       0  100.00%
crates/trogon-std/src/dirs/system.rs                                             98      11  88.78%   57, 65, 67, 75, 77, 85, 87, 96, 98, 109, 154
crates/trogon-std/src/dirs/fixed.rs                                              84       0  100.00%
crates/acp-nats/src/client_proxy.rs                                             200       0  100.00%
crates/acp-nats/src/req_id.rs                                                    39       0  100.00%
crates/acp-nats/src/acp_prefix.rs                                                51       0  100.00%
crates/acp-nats/src/jsonrpc.rs                                                    6       0  100.00%
crates/acp-nats/src/in_flight_slot_guard.rs                                      32       0  100.00%
crates/acp-nats/src/config.rs                                                   204       0  100.00%
crates/acp-nats/src/lib.rs                                                       73       0  100.00%
crates/acp-nats/src/pending_prompt_waiters.rs                                   141       0  100.00%
crates/acp-nats/src/ext_method_name.rs                                           70       0  100.00%
crates/acp-nats/src/error.rs                                                     84       0  100.00%
crates/acp-nats/src/session_id.rs                                                72       0  100.00%
TOTAL                                                                         17205     214  98.76%

Diff against main

Filename                                      Stmts    Miss  Cover
------------------------------------------  -------  ------  --------
crates/acp-telemetry/src/service_name.rs         +4       0  +100.00%
crates/trogon-sink-github/src/config.rs        +104       0  +100.00%
crates/trogon-sink-github/src/main.rs            +4       0  +100.00%
crates/trogon-sink-github/src/server.rs        +390       0  +100.00%
crates/trogon-sink-github/src/signature.rs      +64       0  +100.00%
crates/trogon-nats/src/jetstream/mocks.rs        +3       0  +100.00%
TOTAL                                          +569       0  +0.04%

Results for commit: 5c33189

Minimum allowed coverage is 95%

♻️ This comment has been updated with latest results

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
rsworkspace/crates/trogon-sink-github/src/config.rs (1)

37-41: Silent fallback on parse errors may hide configuration mistakes.

When GITHUB_WEBHOOK_PORT contains an invalid value like "abc", the code silently falls back to the default without logging. This could make deployment debugging harder.

Consider logging a warning when a configured value fails to parse:

💡 Optional: Add warning for invalid config values
+use tracing::warn;
+
 impl GithubConfig {
     pub fn from_env<E: ReadEnv>(env: &E) -> Self {
         Self {
             webhook_secret: env.var("GITHUB_WEBHOOK_SECRET").ok(),
-            port: env
-                .var("GITHUB_WEBHOOK_PORT")
-                .ok()
-                .and_then(|p| p.parse().ok())
-                .unwrap_or(DEFAULT_PORT),
+            port: env
+                .var("GITHUB_WEBHOOK_PORT")
+                .ok()
+                .and_then(|p| p.parse().ok().or_else(|| {
+                    warn!("Invalid GITHUB_WEBHOOK_PORT, using default {DEFAULT_PORT}");
+                    None
+                }))
+                .unwrap_or(DEFAULT_PORT),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-sink-github/src/config.rs` around lines 37 - 41,
The GITHUB_WEBHOOK_PORT parsing currently swallows parse errors and silently
uses DEFAULT_PORT; change the logic where port is set (the block calling
env.var("GITHUB_WEBHOOK_PORT").ok().and_then(|p|
p.parse().ok()).unwrap_or(DEFAULT_PORT)) to explicitly handle the parse result:
if env.var returns a value attempt p.parse::<u16>() and on Err call log::warn!
(including the raw value and the parse error) before falling back to
DEFAULT_PORT, and keep using DEFAULT_PORT when the env var is absent; reference
the port assignment and DEFAULT_PORT in config.rs to locate where to add the
match/if-let and logging.
rsworkspace/crates/acp-telemetry/src/service_name.rs (1)

31-41: Consider adding test coverage for the new TrogonSinkGithub variant.

The existing tests verify AcpNatsStdio and AcpNatsWs but don't cover the newly added TrogonSinkGithub variant:

💡 Suggested test additions
     #[test]
     fn as_str_returns_expected_values() {
         assert_eq!(ServiceName::AcpNatsStdio.as_str(), "acp-nats-stdio");
         assert_eq!(ServiceName::AcpNatsWs.as_str(), "acp-nats-ws");
+        assert_eq!(ServiceName::TrogonSinkGithub.as_str(), "trogon-sink-github");
     }

     #[test]
     fn display_delegates_to_as_str() {
         assert_eq!(format!("{}", ServiceName::AcpNatsStdio), "acp-nats-stdio");
         assert_eq!(format!("{}", ServiceName::AcpNatsWs), "acp-nats-ws");
+        assert_eq!(format!("{}", ServiceName::TrogonSinkGithub), "trogon-sink-github");
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/acp-telemetry/src/service_name.rs` around lines 31 - 41,
Add assertions covering the new ServiceName::TrogonSinkGithub variant in the
existing tests: update as_str_returns_expected_values to assert
ServiceName::TrogonSinkGithub.as_str() == "trogon-sink-github" and update
display_delegates_to_as_str to assert format!("{}",
ServiceName::TrogonSinkGithub) == "trogon-sink-github"; this ensures both
as_str() and Display behavior are tested for the new enum variant.
devops/docker/compose/compose.yml (1)

5-5: Consider pinning the NATS image version for reproducibility.

Using nats:latest can lead to unexpected behavior when the upstream image is updated. Pin to a specific version for reproducible builds.

💡 Suggested fix
-    image: nats:latest
+    image: nats:2.10
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@devops/docker/compose/compose.yml` at line 5, Replace the floating image
reference "image: nats:latest" with a pinned value to ensure reproducible
builds; update the compose service entry that currently uses image: nats:latest
to either a specific tagged release (e.g., nats:<stable-version>) or an
immutable digest (nats@sha256:...), and commit that change so the docker-compose
YAML always pulls a known, tested NATS image.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@devops/docker/compose/compose.yml`:
- Line 5: Replace the floating image reference "image: nats:latest" with a
pinned value to ensure reproducible builds; update the compose service entry
that currently uses image: nats:latest to either a specific tagged release
(e.g., nats:<stable-version>) or an immutable digest (nats@sha256:...), and
commit that change so the docker-compose YAML always pulls a known, tested NATS
image.

In `@rsworkspace/crates/acp-telemetry/src/service_name.rs`:
- Around line 31-41: Add assertions covering the new
ServiceName::TrogonSinkGithub variant in the existing tests: update
as_str_returns_expected_values to assert ServiceName::TrogonSinkGithub.as_str()
== "trogon-sink-github" and update display_delegates_to_as_str to assert
format!("{}", ServiceName::TrogonSinkGithub) == "trogon-sink-github"; this
ensures both as_str() and Display behavior are tested for the new enum variant.

In `@rsworkspace/crates/trogon-sink-github/src/config.rs`:
- Around line 37-41: The GITHUB_WEBHOOK_PORT parsing currently swallows parse
errors and silently uses DEFAULT_PORT; change the logic where port is set (the
block calling env.var("GITHUB_WEBHOOK_PORT").ok().and_then(|p|
p.parse().ok()).unwrap_or(DEFAULT_PORT)) to explicitly handle the parse result:
if env.var returns a value attempt p.parse::<u16>() and on Err call log::warn!
(including the raw value and the parse error) before falling back to
DEFAULT_PORT, and keep using DEFAULT_PORT when the env var is absent; reference
the port assignment and DEFAULT_PORT in config.rs to locate where to add the
match/if-let and logging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8edc023f-8ba8-4703-b10b-a75f32607278

📥 Commits

Reviewing files that changed from the base of the PR and between 1a013ee and f7b3ea6.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • devops/docker/compose/compose.yml
  • rsworkspace/.dockerignore
  • rsworkspace/crates/acp-telemetry/src/service_name.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/Dockerfile
  • rsworkspace/crates/trogon-sink-github/src/config.rs
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
  • rsworkspace/crates/trogon-sink-github/src/lib.rs
  • rsworkspace/crates/trogon-sink-github/src/main.rs
  • rsworkspace/crates/trogon-sink-github/src/server.rs
  • rsworkspace/crates/trogon-sink-github/src/signature.rs
✅ Files skipped from review due to trivial changes (4)
  • rsworkspace/.dockerignore
  • rsworkspace/crates/trogon-sink-github/Dockerfile
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/src/constants.rs

@yordis yordis force-pushed the github branch 5 times, most recently from 849989f to 483ff31 Compare April 1, 2026 23:37
@yordis yordis force-pushed the github branch 2 times, most recently from ff8bf0f to 6786547 Compare April 2, 2026 00:12
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
rsworkspace/crates/trogon-sink-github/src/signature.rs (1)

30-36: Prefer typed webhook inputs over raw primitives in verify() API.

Line 30 currently accepts raw &str/&[u8]; consider value objects (e.g., GithubWebhookSecret, GithubSignatureHeader) so invalid header forms are unrepresentable before verification.

As per coding guidelines, “Prefer domain-specific value objects over primitives … invalid instances should be unrepresentable.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-sink-github/src/signature.rs` around lines 30 - 36,
The verify() API currently accepts raw primitives (secret: &str, body: &[u8],
signature_header: &str); refactor to use domain value objects so invalid forms
are unrepresentable: introduce types like GithubWebhookSecret (wrapping the
secret bytes/string) and GithubSignatureHeader (constructed via a fallible
try_from/parse that enforces "sha256=" prefix and validates/decodes hex,
returning SignatureError variants such as MissingPrefix/InvalidHex), then change
pub fn verify to accept GithubWebhookSecret and GithubSignatureHeader (and body:
&[u8] can remain or be wrapped if desired) and move the prefix-strip/hex-decode
logic out of verify into GithubSignatureHeader::try_from/parse so verify only
compares signatures using the already-validated values.
rsworkspace/crates/trogon-sink-github/src/config.rs (1)

22-31: Consider domain-specific value objects for configuration fields.

The struct uses primitive types (String, u16) for fields like subject_prefix and stream_name. Per coding guidelines, domain-specific value objects are preferred over primitives, where each type's factory guarantees correctness at construction. For example, a SubjectPrefix or StreamName type could validate format constraints (e.g., no invalid NATS subject characters).

This is a low-priority suggestion that can be deferred. As per coding guidelines: "Prefer domain-specific value objects over primitives (e.g., AcpPrefix not String), with each type's factory guaranteeing correctness at construction."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-sink-github/src/config.rs` around lines 22 - 31,
Replace primitive config fields with domain-specific value objects: introduce
SubjectPrefix and StreamName types with constructors/factories that validate
allowed characters/format (e.g., NATS subject rules) and convert/parse from
String; then change GithubConfig's subject_prefix: String and stream_name:
String to subject_prefix: SubjectPrefix and stream_name: StreamName, and update
any code that constructs GithubConfig to use the new factories (validate at
creation time so rest of code can rely on correct values).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@devops/docker/compose/compose.yml`:
- Around line 17-22: The healthcheck uses wget which is not present in the
nats:latest (Alpine) image so it will always fail; update the healthcheck block
(the healthcheck: test: entry) to use a shell-based check that works in Alpine,
e.g. replace the exec form with a shell form that uses /bin/sh -c and either a
TCP probe (/dev/tcp/localhost/8222) or curl if you add it to the image;
specifically modify the healthcheck test in the healthcheck section so it runs
something like /bin/sh -c 'echo > /dev/tcp/localhost/8222 >/dev/null 2>&1 ||
exit 1' or use /bin/sh -c 'curl -sSf http://localhost:8222/healthz || exit 1' to
ensure the container can perform the check without wget.

---

Nitpick comments:
In `@rsworkspace/crates/trogon-sink-github/src/config.rs`:
- Around line 22-31: Replace primitive config fields with domain-specific value
objects: introduce SubjectPrefix and StreamName types with
constructors/factories that validate allowed characters/format (e.g., NATS
subject rules) and convert/parse from String; then change GithubConfig's
subject_prefix: String and stream_name: String to subject_prefix: SubjectPrefix
and stream_name: StreamName, and update any code that constructs GithubConfig to
use the new factories (validate at creation time so rest of code can rely on
correct values).

In `@rsworkspace/crates/trogon-sink-github/src/signature.rs`:
- Around line 30-36: The verify() API currently accepts raw primitives (secret:
&str, body: &[u8], signature_header: &str); refactor to use domain value objects
so invalid forms are unrepresentable: introduce types like GithubWebhookSecret
(wrapping the secret bytes/string) and GithubSignatureHeader (constructed via a
fallible try_from/parse that enforces "sha256=" prefix and validates/decodes
hex, returning SignatureError variants such as MissingPrefix/InvalidHex), then
change pub fn verify to accept GithubWebhookSecret and GithubSignatureHeader
(and body: &[u8] can remain or be wrapped if desired) and move the
prefix-strip/hex-decode logic out of verify into
GithubSignatureHeader::try_from/parse so verify only compares signatures using
the already-validated values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8d3a8f17-c4db-40d7-8a01-068eff98990c

📥 Commits

Reviewing files that changed from the base of the PR and between f7b3ea6 and 0428752.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • devops/docker/compose/compose.yml
  • rsworkspace/.dockerignore
  • rsworkspace/crates/acp-telemetry/src/service_name.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/Dockerfile
  • rsworkspace/crates/trogon-sink-github/src/config.rs
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
  • rsworkspace/crates/trogon-sink-github/src/lib.rs
  • rsworkspace/crates/trogon-sink-github/src/main.rs
  • rsworkspace/crates/trogon-sink-github/src/server.rs
  • rsworkspace/crates/trogon-sink-github/src/signature.rs
✅ Files skipped from review due to trivial changes (4)
  • rsworkspace/crates/acp-telemetry/src/service_name.rs
  • rsworkspace/.dockerignore
  • rsworkspace/crates/trogon-sink-github/src/lib.rs
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (3)
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
  • rsworkspace/crates/trogon-sink-github/src/server.rs

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
rsworkspace/crates/acp-telemetry/src/service_name.rs (1)

27-41: Add test coverage for the new TrogonSinkGithub variant.

The existing tests cover AcpNatsStdio and AcpNatsWs but not the newly added TrogonSinkGithub variant.

Proposed fix to add test coverage
     #[test]
     fn as_str_returns_expected_values() {
         assert_eq!(ServiceName::AcpNatsStdio.as_str(), "acp-nats-stdio");
         assert_eq!(ServiceName::AcpNatsWs.as_str(), "acp-nats-ws");
+        assert_eq!(ServiceName::TrogonSinkGithub.as_str(), "trogon-sink-github");
     }
 
     #[test]
     fn display_delegates_to_as_str() {
         assert_eq!(format!("{}", ServiceName::AcpNatsStdio), "acp-nats-stdio");
         assert_eq!(format!("{}", ServiceName::AcpNatsWs), "acp-nats-ws");
+        assert_eq!(format!("{}", ServiceName::TrogonSinkGithub), "trogon-sink-github");
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/acp-telemetry/src/service_name.rs` around lines 27 - 41,
Tests for ServiceName currently assert only AcpNatsStdio and AcpNatsWs; add
assertions for the new ServiceName::TrogonSinkGithub variant in both tests:
update as_str_returns_expected_values to assert
ServiceName::TrogonSinkGithub.as_str() returns the expected string (e.g.,
"trogon-sink-github") and update display_delegates_to_as_str to assert
format!("{}", ServiceName::TrogonSinkGithub) equals the same expected string,
ensuring you reference the ServiceName::TrogonSinkGithub symbol and the
as_str()/Display behavior.
rsworkspace/crates/trogon-sink-github/src/server.rs (1)

142-160: Minor: JetStream context created twice in serve().

Line 144 creates a NatsJetStreamClient for provisioning, and then router() (line 149) creates another one internally (line 126). Consider passing the provisioned client to router() to avoid recreating it.

Proposed refactor
 #[cfg(not(coverage))]
-pub fn router(config: &GithubConfig, nats: async_nats::Client) -> Router {
-    let js = NatsJetStreamClient::new(async_nats::jetstream::new(nats));
+pub fn router(config: &GithubConfig, js: NatsJetStreamClient) -> Router {
     let state = AppState {
         js,
         ...
     };
     ...
 }

 #[cfg(not(coverage))]
 pub async fn serve(config: GithubConfig, nats: async_nats::Client) -> Result<(), ServeError> {
     let js = NatsJetStreamClient::new(async_nats::jetstream::new(nats.clone()));
     provision(&js, &config)
         .await
         .map_err(ServeError::Provision)?;

-    let app = router(&config, nats);
+    let app = router(&config, js);
     ...
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-sink-github/src/server.rs` around lines 142 - 160,
The serve() function currently constructs a NatsJetStreamClient for provisioning
and then router() recreates another JetStream context; modify serve() to pass
the already-created NatsJetStreamClient into router() instead of letting
router() create its own. Update router()'s signature (and any call-sites) to
accept the provisioned NatsJetStreamClient (or a reference) alongside
GithubConfig and async_nats::Client, remove the internal
NatsJetStreamClient::new(...) call inside router(), and use the passed client
for any JetStream operations and for calling provision() you already invoked in
serve().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@rsworkspace/crates/acp-telemetry/src/service_name.rs`:
- Around line 27-41: Tests for ServiceName currently assert only AcpNatsStdio
and AcpNatsWs; add assertions for the new ServiceName::TrogonSinkGithub variant
in both tests: update as_str_returns_expected_values to assert
ServiceName::TrogonSinkGithub.as_str() returns the expected string (e.g.,
"trogon-sink-github") and update display_delegates_to_as_str to assert
format!("{}", ServiceName::TrogonSinkGithub) equals the same expected string,
ensuring you reference the ServiceName::TrogonSinkGithub symbol and the
as_str()/Display behavior.

In `@rsworkspace/crates/trogon-sink-github/src/server.rs`:
- Around line 142-160: The serve() function currently constructs a
NatsJetStreamClient for provisioning and then router() recreates another
JetStream context; modify serve() to pass the already-created
NatsJetStreamClient into router() instead of letting router() create its own.
Update router()'s signature (and any call-sites) to accept the provisioned
NatsJetStreamClient (or a reference) alongside GithubConfig and
async_nats::Client, remove the internal NatsJetStreamClient::new(...) call
inside router(), and use the passed client for any JetStream operations and for
calling provision() you already invoked in serve().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3d4dab46-5b1c-46fa-bb38-265311a17b53

📥 Commits

Reviewing files that changed from the base of the PR and between 0428752 and 4119243.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • devops/docker/compose/compose.yml
  • rsworkspace/.dockerignore
  • rsworkspace/crates/acp-telemetry/src/service_name.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/Dockerfile
  • rsworkspace/crates/trogon-sink-github/src/config.rs
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
  • rsworkspace/crates/trogon-sink-github/src/lib.rs
  • rsworkspace/crates/trogon-sink-github/src/main.rs
  • rsworkspace/crates/trogon-sink-github/src/server.rs
  • rsworkspace/crates/trogon-sink-github/src/signature.rs
✅ Files skipped from review due to trivial changes (3)
  • rsworkspace/.dockerignore
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
  • rsworkspace/crates/trogon-sink-github/src/signature.rs
  • rsworkspace/crates/trogon-sink-github/src/lib.rs

@yordis yordis force-pushed the github branch 3 times, most recently from 29da556 to aabb40b Compare April 2, 2026 14:27
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
rsworkspace/crates/trogon-sink-github/src/config.rs (1)

40-67: Consider logging warnings when invalid environment variable values fall back to defaults.

Invalid numeric values for GITHUB_WEBHOOK_PORT, GITHUB_STREAM_MAX_AGE_SECS, GITHUB_NATS_ACK_TIMEOUT_SECS, and GITHUB_MAX_BODY_SIZE silently fall back to defaults. This can make misconfiguration hard to diagnose in production.

Example: Add tracing warnings on parse failures
port: env
    .var("GITHUB_WEBHOOK_PORT")
    .ok()
    .and_then(|p| p.parse().map_err(|e| {
        tracing::warn!(value = %p, "Invalid GITHUB_WEBHOOK_PORT, using default");
        e
    }).ok())
    .unwrap_or(DEFAULT_PORT),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-sink-github/src/config.rs` around lines 40 - 67,
The code silently falls back to defaults when parsing env vars for port,
stream_max_age, nats_ack_timeout, and max_body_size; update the parsing chains
for the fields named port, stream_max_age, nats_ack_timeout, and max_body_size
in config.rs to log a warning (e.g., tracing::warn!) when env::var exists but
parse() fails before falling back to the DEFAULT_* values, capturing the raw
value and context in the log message so misconfigurations are visible in
production.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rsworkspace/crates/trogon-sink-github/src/server.rs`:
- Around line 260-271: The test fixture in test_config() assigns a String to
GithubConfig.webhook_secret which is declared as Option<String>; update
test_config() to supply an Option (e.g., wrap the value with
Some(TEST_SECRET.to_string()) or use None as appropriate) and ensure any related
AppState changes that expect an Option<String> for webhook_secret are applied
consistently (search for test_config, GithubConfig, and AppState to locate
usages to update).

---

Nitpick comments:
In `@rsworkspace/crates/trogon-sink-github/src/config.rs`:
- Around line 40-67: The code silently falls back to defaults when parsing env
vars for port, stream_max_age, nats_ack_timeout, and max_body_size; update the
parsing chains for the fields named port, stream_max_age, nats_ack_timeout, and
max_body_size in config.rs to log a warning (e.g., tracing::warn!) when env::var
exists but parse() fails before falling back to the DEFAULT_* values, capturing
the raw value and context in the log message so misconfigurations are visible in
production.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e1af64d5-5b36-4f0b-bd4d-fb45e6d48336

📥 Commits

Reviewing files that changed from the base of the PR and between 4119243 and 29da556.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • devops/docker/compose/compose.yml
  • rsworkspace/.dockerignore
  • rsworkspace/crates/acp-telemetry/src/service_name.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/mocks.rs
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/Dockerfile
  • rsworkspace/crates/trogon-sink-github/src/config.rs
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
  • rsworkspace/crates/trogon-sink-github/src/lib.rs
  • rsworkspace/crates/trogon-sink-github/src/main.rs
  • rsworkspace/crates/trogon-sink-github/src/server.rs
  • rsworkspace/crates/trogon-sink-github/src/signature.rs
✅ Files skipped from review due to trivial changes (6)
  • rsworkspace/.dockerignore
  • rsworkspace/crates/trogon-sink-github/Dockerfile
  • rsworkspace/crates/trogon-sink-github/Cargo.toml
  • rsworkspace/crates/trogon-sink-github/src/signature.rs
  • rsworkspace/crates/trogon-sink-github/src/lib.rs
  • rsworkspace/crates/trogon-sink-github/src/constants.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • rsworkspace/crates/acp-telemetry/src/service_name.rs
  • rsworkspace/crates/trogon-sink-github/src/main.rs

@yordis yordis force-pushed the github branch 2 times, most recently from 8a6b4fa to a8ee6e5 Compare April 2, 2026 18:20
@yordis yordis force-pushed the github branch 4 times, most recently from f4ac558 to 277626c Compare April 2, 2026 22:24
…ATS JetStream

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis yordis merged commit dabe16e into main Apr 2, 2026
7 checks passed
@yordis yordis deleted the github branch April 2, 2026 22:30
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:${GITHUB_WEBHOOK_PORT:-8080}/health"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Healthcheck uses curl which is not installed in image

High Severity

The trogon-sink-github healthcheck uses curl, but the Dockerfile's runtime stage (debian:bookworm-slim) only installs ca-certificatescurl is not included in slim images. The healthcheck will always fail, so the container never reaches "healthy" status. Since the smee service depends on condition: service_healthy for trogon-sink-github, the entire dev-profile workflow described in the docs is broken. The same issue was recognized and fixed for the NATS container (switched to nats:alpine for wget), but wasn't addressed here.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant