Skip to content

test: cover Linear webhook delivery dedupe#827

Open
ColeMurray wants to merge 1 commit into
mainfrom
test/linear-webhook-delivery-dedupe
Open

test: cover Linear webhook delivery dedupe#827
ColeMurray wants to merge 1 commit into
mainfrom
test/linear-webhook-delivery-dedupe

Conversation

@ColeMurray

@ColeMurray ColeMurray commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add route-level Linear webhook tests for the recently changed Linear-Delivery dedupe contract.
  • Cover missing delivery header rejection, duplicate delivery suppression, distinct deliveries sharing the same webhookId, and malformed AgentSession payload rejection.

Why

These paths decide whether external Linear webhook deliveries enqueue agent work, so regressions can silently drop or duplicate sessions.

Testing

  • npm test -w @open-inspect/linear-bot

Created with Open-Inspect

Summary by CodeRabbit

  • Tests
    • Added coverage for webhook request handling, including missing headers, duplicate deliveries, distinct delivery IDs, and invalid payloads.
    • Improved confidence in duplicate protection and request validation for more reliable webhook processing.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new Vitest test file (packages/linear-bot/src/index.test.ts) with 197 lines covering four POST /webhook behaviors: missing Linear-Delivery header rejection, KV-backed deduplication of repeated deliveries, pass-through for distinct delivery IDs, and malformed payload rejection.

Changes

POST /webhook Vitest Test Suite

Layer / File(s) Summary
Test scaffolding, mocks, and request helpers
packages/linear-bot/src/index.test.ts
Sets up Vitest imports, a hoisted handleAgentSessionEvent mock, a module mock for ./webhook-handler, a PutCall type, a sign() HMAC-SHA256 helper using crypto.subtle, a Map-backed createFakeKV() stub, makeEnv()/makeCtx() environment factories, makeAgentSessionPayload(), and makeWebhookRequest().
Behavioral test cases
packages/linear-bot/src/index.test.ts
Four tests: (1) missing Linear-Delivery returns 400 with no KV/handler calls; (2) repeated Linear-Delivery deduplicates via KV put with TTL and handler runs once; (3) distinct Linear-Delivery values each succeed and produce separate KV keys; (4) malformed AgentSessionEvent shape returns 400 with no KV/handler calls.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • ColeMurray/background-agents#627: Introduced the /webhook endpoint behavior (missing Linear-Delivery rejection, KV deduplication, invalid payload handling) that this test suite directly exercises.

Poem

🐇 A webhook arrives, will it pass or get blocked?
The KV says "seen it!" — duplicate's docked.
Missing a header? That's four hundred, friend.
Bad payload shape? Same swift 400 end.
With HMAC signatures and mocks in a row,
This rabbit ensures all the edge cases show! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding tests for Linear webhook delivery deduplication.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/linear-webhook-delivery-dedupe

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: one or more packages not found in the registry.


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.

@github-actions

Copy link
Copy Markdown

Terraform Validation Results

Step Status
Format
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@open-inspect open-inspect Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Summary

PR #827 (test: cover Linear webhook delivery dedupe) by @ColeMurray adds route-level Linear webhook tests for delivery-header-based deduplication and malformed payload rejection. The coverage is focused and aligns with the current webhook behavior.

Files changed: 1 file, +197/-0.

Critical Issues

None found.

Suggestions

None.

Nitpicks

None.

Positive Feedback

  • Covers the key regression risk that webhookId is a stable config identifier and should not be used as the dedupe key.
  • Verifies validation ordering by asserting malformed/missing-delivery cases do not touch KV or enqueue work.
  • Uses a mocked handler at the route boundary, keeping these tests focused on request validation, dedupe, and dispatch behavior.

Questions

None.

Verdict

Approve.

Testing: npm test -w @open-inspect/linear-bot passed with 8 test files and 109 tests.

@open-inspect open-inspect Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Deep maintainability review complete. I left one inline comment focused on test harness structure.

.join("");
}

function createFakeKV(initial: Record<string, string> = {}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[deep review] This adds a second bespoke fake KV implementation, plus another local env/context harness below, rather than creating one canonical Linear worker test harness. For a route-level test file this is exactly where the test infrastructure will keep growing: every future webhook route case will need signed requests, a fake KV with call inspection, a full Env, and an ExecutionContext. Can we extract the reusable pieces now, for example a small test-helpers module with createFakeKV, makeLinearBotEnv, makeExecutionContext, and signLinearWebhookRequest, and have both this file and kv-store.test.ts use it where applicable? That deletes duplicated scaffolding instead of normalizing another local copy with casts and hand-rolled behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/linear-bot/src/index.test.ts (1)

178-196: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert handler non-invocation explicitly in malformed-payload test.

Add an explicit assertion that the mocked handler is never called on malformed payloads to lock the contract more tightly.

Suggested patch
   expect(res.status).toBe(400);
   expect(await res.json()).toEqual({ error: "Invalid payload" });
   expect(kv.get).not.toHaveBeenCalled();
   expect(kv.put).not.toHaveBeenCalled();
   expect(ctx.waitUntil).not.toHaveBeenCalled();
+  expect(mocks.handleAgentSessionEvent).not.toHaveBeenCalled();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/linear-bot/src/index.test.ts` around lines 178 - 196, In the
malformed AgentSessionEvent test in index.test.ts, explicitly assert that the
webhook handler is never invoked when validation fails, not just that KV and
waitUntil are skipped. Add a clear non-invocation expectation against the mocked
handler used by app.fetch for this payload, alongside the existing Invalid
payload and 400 assertions, to lock the contract in the malformed-payload path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/linear-bot/src/index.test.ts`:
- Around line 178-196: In the malformed AgentSessionEvent test in index.test.ts,
explicitly assert that the webhook handler is never invoked when validation
fails, not just that KV and waitUntil are skipped. Add a clear non-invocation
expectation against the mocked handler used by app.fetch for this payload,
alongside the existing Invalid payload and 400 assertions, to lock the contract
in the malformed-payload path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1c51fc6c-1ba1-4458-b425-de99fcd29531

📥 Commits

Reviewing files that changed from the base of the PR and between a537ba3 and 36a045b.

📒 Files selected for processing (1)
  • packages/linear-bot/src/index.test.ts

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