Skip to content

Commit 2d1574d

Browse files
authored
fix(telemetry): consistent invocation ID per run and telemetry acceptance tests (#271)
* fix(telemetry): consistent invocation ID per run and add telemetry test infra - root.go: set invocation ID only when empty so all API requests in one CLI run share the same invocation_id (fixes multiple IDs when gateway PreRun calls ValidateAPIKey then connection PreRun overwrote telemetry) - pkg/cmd: add TestInvocationIDPersistsAcrossMultipleInitTelemetryCalls (fails without fix, passes with it) - test/acceptance: recording proxy (StartRecordingProxy, AssertTelemetryConsistent, RunListenWithTimeout, RunWithEnv, NewCLIRunnerWithConfigPath/NoCI), telemetry_test.go proxy-based tests, TestTelemetryInvocationIDConsistentWhenValidateAPIKeyInPreRun, TestTelemetryListenProxy in listen_test.go, README section Made-with: Cursor * docs(cli): use 'hookdeck gateway connection' in connection command examples Update Example strings in connection create, delete, get, list, and upsert so help text shows the preferred gateway-scoped form instead of the deprecated root-level 'hookdeck connection'. Made-with: Cursor * chore(docs): regenerate REFERENCE.md from Cobra metadata Run go run ./tools/generate-reference after connection example updates so REFERENCE.md reflects hookdeck gateway connection in examples. Made-with: Cursor * chore(acceptance): run telemetry tests in slice 1, remove unreproducible test - Tag telemetry_test.go with 'telemetry' (was 'connection'); run in slice 1 with request, event - CI and run_parallel.sh: add telemetry to slice 1 tags - Remove TestTelemetryThreeRequestsOneCommandPath (three-request bug not reproducible with current CLI) Made-with: Cursor * test(acceptance): move listen telemetry proxy test under telemetry tag - Add telemetry_listen_test.go (//go:build telemetry) with TestTelemetryListenProxy - Remove test from listen_test.go so matrix slices with telemetry disabled never run it - CI/run_parallel: single go test -tags=telemetry (no separate listen invocation) - README: document telemetry-tagged proxy tests Made-with: Cursor * fix(ci): force telemetry on for acceptance-telemetry job - Set HOOKDECK_CLI_TELEMETRY_DISABLED=0 so repo/org defaults cannot disable headers - AssertTelemetryConsistent: clearer fatal when all telemetry headers empty - run_parallel.sh and README match CI Made-with: Cursor * fix(acceptance): tag JSON config tests so telemetry job runs telemetry only - Add //go:build connection|destination|source to *_config_json* and connection_rules_json tests - Untagged *_test.go files were included in go test -tags=telemetry (acceptance-telemetry CI) - README + AGENTS: document that untagged tests also run in the telemetry job Made-with: Cursor * acceptance: retry CLIRunner on transient HTTP 502 with logging - Run, RunWithEnv, RunFromCwd: up to 4 attempts, 2s backoff - Detect 502 via CLI error patterns only (not 503/504) - Log each retry and final give-up with output excerpts - Document in README; add basic-tagged detection tests Made-with: Cursor
1 parent aab2ca6 commit 2d1574d

19 files changed

Lines changed: 2006 additions & 107 deletions

.github/workflows/test-acceptance.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,25 @@ jobs:
3737

3838
- name: Run Go Acceptance Tests (slice ${{ matrix.slice }})
3939
run: go test -tags="${{ matrix.tags }}" ./test/acceptance/... -v -timeout 12m
40+
41+
# Telemetry proxy tests require the real telemetry header; matrix jobs set
42+
# HOOKDECK_CLI_TELEMETRY_DISABLED=1. This job runs -tags=telemetry with
43+
# HOOKDECK_CLI_TELEMETRY_DISABLED=0 so telemetry is on even if the repo sets a global opt-out.
44+
acceptance-telemetry:
45+
runs-on: ubuntu-latest
46+
env:
47+
ACCEPTANCE_SLICE: "0"
48+
HOOKDECK_CLI_TESTING_API_KEY: ${{ secrets.HOOKDECK_CLI_TESTING_API_KEY }}
49+
# Explicitly allow telemetry: repo/org env may set HOOKDECK_CLI_TELEMETRY_DISABLED=1 globally.
50+
HOOKDECK_CLI_TELEMETRY_DISABLED: "0"
51+
steps:
52+
- name: Check out code
53+
uses: actions/checkout@v3
54+
55+
- name: Set up Go
56+
uses: actions/setup-go@v3
57+
with:
58+
go-version: "1.24.9"
59+
60+
- name: Run telemetry acceptance tests
61+
run: go test -tags=telemetry ./test/acceptance/... -v -timeout 12m

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ go run cmd/hookdeck/main.go login --help
274274
- **Always run tests** when changing code: unit tests (`go test ./pkg/...`) and, for CLI-facing changes, acceptance tests (`go test ./test/acceptance/...`). Do not skip tests to avoid failures.
275275
- When running commands (build, test, acceptance tests), if you see **TLS/certificate errors** (e.g. `x509: certificate verify failed`, `tls: failed to verify certificate`), **permission errors** (e.g. `operation not permitted` when writing to the Go module cache), or similar failures that look environment-related, the command is likely running inside a **sandbox**. **Prompt the user** and **re-run the command with elevated permissions** (e.g. `required_permissions: ["network"]` for tests that need API access, or `["all"]` to disable the sandbox) so the operation can succeed. Do not treat a build or test as passed if stderr shows these errors, even when the process exit code is 0.
276276
277+
### GitHub CLI (`gh`)
278+
- Use the **[GitHub CLI](https://cli.github.com/) (`gh`)** to read GitHub data and perform actions from the shell: **workflow runs and job logs** (e.g. `gh run list`, `gh run view <run-id> --log-failed`, `gh run view <run-id> --job <job-id> --log`), **PRs and checks** (`gh pr view`, `gh pr checks`, `gh pr diff`), **API access** (`gh api`), and creating or updating PRs, issues, and releases.
279+
- Install and authenticate `gh` where needed (e.g. `gh auth login`). If `gh` fails with TLS, network, or permission errors, re-run with **network** or **all** permissions when the agent sandbox may be blocking access.
280+
277281
## 6. Documentation Standards
278282
279283
### Command help text (Short and Long)
@@ -355,7 +359,7 @@ if apiErr, ok := err.(*hookdeck.APIError); ok {
355359
Acceptance tests require a Hookdeck API key. See [`test/acceptance/README.md`](test/acceptance/README.md) for full details. Quick setup: create `test/acceptance/.env` with `HOOKDECK_CLI_TESTING_API_KEY=<key>`. The `.env` file is git-ignored and must never be committed.
356360
357361
### Acceptance tests and feature tags
358-
Acceptance tests in `test/acceptance/` are partitioned by **feature build tags** so they can run in parallel (two slices in CI and locally). Each test file must have exactly one feature tag (e.g. `//go:build connection`, `//go:build request`). The runner (CI workflow or `run_parallel.sh`) maps features to slices and passes the corresponding `-tags="..."`; see [test/acceptance/README.md](test/acceptance/README.md) for slice mapping and setup. **Every new acceptance test file must have a feature tag**; otherwise it is included in every build and runs in both slices (duplicated). Use tags to balance and parallelize; same commands and env for local and CI.
362+
Acceptance tests in `test/acceptance/` are partitioned by **feature build tags** so they can run in parallel (matrix slices plus a separate `acceptance-telemetry` job in CI; see [test/acceptance/README.md](test/acceptance/README.md)). Each `*_test.go` file must have exactly one feature tag (e.g. `//go:build connection`, `//go:build request`, `//go:build telemetry`). **Untagged test files are included in every `-tags=...` build**, including `-tags=telemetry` only, so non-telemetry tests would run in the telemetry job—do not add untagged `*_test.go` files. Use tags to balance and parallelize; same commands and env for local and CI.
359363
360364
### Unit Testing
361365
- Test validation logic thoroughly

REFERENCE.md

Lines changed: 86 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ hookdeck login [flags]
5959
| Flag | Type | Description |
6060
|------|------|-------------|
6161
| `-i, --interactive` | `bool` | Run interactive configuration mode if you cannot open a browser |
62+
| `--local` | `bool` | Save credentials to current directory (.hookdeck/config.toml) |
6263

6364
**Examples:**
6465

6566
```bash
6667
$ hookdeck login
6768
$ hookdeck login -i # interactive mode (no browser)
69+
$ hookdeck login --local # save credentials to .hookdeck/config.toml
6870
```
6971
## Logout
7072

@@ -103,8 +105,6 @@ hookdeck whoami
103105
```bash
104106
$ hookdeck whoami
105107
```
106-
107-
Output includes the current project type (Gateway, Outpost, or Console).
108108
<!-- GENERATE_END -->
109109
## Projects
110110

@@ -114,7 +114,7 @@ Output includes the current project type (Gateway, Outpost, or Console).
114114

115115
### hookdeck project list
116116

117-
List and filter projects by organization and project name substrings. Output shows project type (Gateway, Outpost, Console). Outbound projects are excluded from the list.
117+
List and filter projects by organization and project name substrings
118118

119119
**Usage:**
120120

@@ -126,16 +126,15 @@ hookdeck project list [<organization_substring>] [<project_substring>] [flags]
126126

127127
| Flag | Type | Description |
128128
|------|------|-------------|
129-
| `--output` | `string` | Output format: `json` for machine-readable list (id, org, project, type, current) |
130-
| `--type` | `string` | Filter by project type: `gateway`, `outpost`, or `console` |
129+
| `--output` | `string` | Output format: json |
130+
| `--type` | `string` | Filter by project type: gateway, outpost, console |
131131

132132
**Examples:**
133133

134134
```bash
135135
$ hookdeck project list
136136
Acme / Ecommerce Production (current) | Gateway
137137
Acme / Ecommerce Staging | Gateway
138-
139138
$ hookdeck project list --output json
140139
$ hookdeck project list --type gateway
141140
```
@@ -161,14 +160,11 @@ hookdeck project use [<organization_name> [<project_name>]] [flags]
161160
$ hookdeck project use
162161
Use the arrow keys to navigate: ↓ ↑ → ←
163162
? Select Project:
164-
▸ [Acme] Ecommerce Production
165-
[Acme] Ecommerce Staging
166-
[Acme] Ecommerce Development
167-
168-
Selecting project [Acme] Ecommerce Staging
163+
▸ Acme / Ecommerce Production (current) | Gateway
164+
Acme / Ecommerce Staging | Gateway
169165

170166
$ hookdeck project use --local
171-
Pinning project [Acme] Ecommerce Staging to current directory
167+
Pinning project to current directory
172168
```
173169
<!-- GENERATE_END -->
174170
## Local Development
@@ -219,7 +215,6 @@ Commands for managing Event Gateway sources, destinations, connections,
219215
transformations, events, requests, metrics, and MCP server.
220216
221217
The gateway command group provides full access to all Event Gateway resources.
222-
**Gateway commands require the current project to be a Gateway project** (inbound or console). If your project type is Outpost or you have no project selected, run `hookdeck project use` to switch to a Gateway project first.
223218
224219
**Usage:**
225220
@@ -282,22 +277,22 @@ hookdeck gateway connection list [flags]
282277
283278
```bash
284279
# List all connections
285-
hookdeck connection list
280+
hookdeck gateway connection list
286281
287282
# Filter by connection name
288-
hookdeck connection list --name my-connection
283+
hookdeck gateway connection list --name my-connection
289284
290285
# Filter by source ID
291-
hookdeck connection list --source-id src_abc123
286+
hookdeck gateway connection list --source-id src_abc123
292287
293288
# Filter by destination ID
294-
hookdeck connection list --destination-id dst_def456
289+
hookdeck gateway connection list --destination-id dst_def456
295290
296291
# Include disabled connections
297-
hookdeck connection list --disabled
292+
hookdeck gateway connection list --disabled
298293
299294
# Limit results
300-
hookdeck connection list --limit 10
295+
hookdeck gateway connection list --limit 10
301296
```
302297
### hookdeck gateway connection create
303298
@@ -353,10 +348,10 @@ hookdeck gateway connection create [flags]
353348
| `--rule-deduplicate-include-fields` | `string` | Comma-separated list of fields to include for deduplication |
354349
| `--rule-deduplicate-window` | `int` | Time window in seconds for deduplication (default "0") |
355350
| `--rule-delay` | `int` | Delay in milliseconds (default "0") |
356-
| `--rule-filter-body` | `string` | JQ expression to filter on request body |
357-
| `--rule-filter-headers` | `string` | JQ expression to filter on request headers |
358-
| `--rule-filter-path` | `string` | JQ expression to filter on request path |
359-
| `--rule-filter-query` | `string` | JQ expression to filter on request query parameters |
351+
| `--rule-filter-body` | `string` | Filter on request body using Hookdeck filter syntax (JSON) |
352+
| `--rule-filter-headers` | `string` | Filter on request headers using Hookdeck filter syntax (JSON) |
353+
| `--rule-filter-path` | `string` | Filter on request path using Hookdeck filter syntax (JSON) |
354+
| `--rule-filter-query` | `string` | Filter on request query parameters using Hookdeck filter syntax (JSON) |
360355
| `--rule-retry-count` | `int` | Number of retry attempts (default "0") |
361356
| `--rule-retry-interval` | `int` | Interval between retries in milliseconds (default "0") |
362357
| `--rule-retry-response-status-codes` | `string` | Comma-separated HTTP status codes to retry on |
@@ -386,19 +381,19 @@ hookdeck gateway connection create [flags]
386381
387382
```bash
388383
# Create with inline source and destination
389-
hookdeck connection create \
384+
hookdeck gateway connection create \
390385
--name "test-webhooks-to-local" \
391386
--source-type WEBHOOK --source-name "test-webhooks" \
392387
--destination-type CLI --destination-name "local-dev"
393388
394389
# Create with existing resources
395-
hookdeck connection create \
390+
hookdeck gateway connection create \
396391
--name "github-to-api" \
397392
--source-id src_abc123 \
398393
--destination-id dst_def456
399394
400395
# Create with source configuration options
401-
hookdeck connection create \
396+
hookdeck gateway connection create \
402397
--name "api-webhooks" \
403398
--source-type WEBHOOK --source-name "api-source" \
404399
--source-allowed-http-methods "POST,PUT,PATCH" \
@@ -418,6 +413,12 @@ You can specify either a connection ID or name.
418413
hookdeck gateway connection get <connection-id-or-name> [flags]
419414
```
420415
416+
**Arguments:**
417+
418+
| Argument | Type | Description |
419+
|----------|------|-------------|
420+
| `connection-id-or-name` | `string` | **Required.** Connection ID or name |
421+
421422
**Flags:**
422423
423424
| Flag | Type | Description |
@@ -430,10 +431,10 @@ hookdeck gateway connection get <connection-id-or-name> [flags]
430431
431432
```bash
432433
# Get connection by ID
433-
hookdeck connection get conn_abc123
434+
hookdeck gateway connection get conn_abc123
434435
435436
# Get connection by name
436-
hookdeck connection get my-connection
437+
hookdeck gateway connection get my-connection
437438
```
438439
### hookdeck gateway connection update
439440
@@ -448,6 +449,12 @@ and allows changing any field including the connection name.
448449
hookdeck gateway connection update <connection-id> [flags]
449450
```
450451
452+
**Arguments:**
453+
454+
| Argument | Type | Description |
455+
|----------|------|-------------|
456+
| `connection-id` | `string` | **Required.** Connection ID |
457+
451458
**Flags:**
452459
453460
| Flag | Type | Description |
@@ -460,10 +467,10 @@ hookdeck gateway connection update <connection-id> [flags]
460467
| `--rule-deduplicate-include-fields` | `string` | Comma-separated list of fields to include for deduplication |
461468
| `--rule-deduplicate-window` | `int` | Time window in seconds for deduplication (default "0") |
462469
| `--rule-delay` | `int` | Delay in milliseconds (default "0") |
463-
| `--rule-filter-body` | `string` | JQ expression to filter on request body |
464-
| `--rule-filter-headers` | `string` | JQ expression to filter on request headers |
465-
| `--rule-filter-path` | `string` | JQ expression to filter on request path |
466-
| `--rule-filter-query` | `string` | JQ expression to filter on request query parameters |
470+
| `--rule-filter-body` | `string` | Filter on request body using Hookdeck filter syntax (JSON) |
471+
| `--rule-filter-headers` | `string` | Filter on request headers using Hookdeck filter syntax (JSON) |
472+
| `--rule-filter-path` | `string` | Filter on request path using Hookdeck filter syntax (JSON) |
473+
| `--rule-filter-query` | `string` | Filter on request query parameters using Hookdeck filter syntax (JSON) |
467474
| `--rule-retry-count` | `int` | Number of retry attempts (default "0") |
468475
| `--rule-retry-interval` | `int` | Interval between retries in milliseconds (default "0") |
469476
| `--rule-retry-response-status-codes` | `string` | Comma-separated HTTP status codes to retry on |
@@ -504,6 +511,12 @@ Delete a connection.
504511
hookdeck gateway connection delete <connection-id> [flags]
505512
```
506513
514+
**Arguments:**
515+
516+
| Argument | Type | Description |
517+
|----------|------|-------------|
518+
| `connection-id` | `string` | **Required.** Connection ID |
519+
507520
**Flags:**
508521
509522
| Flag | Type | Description |
@@ -514,10 +527,10 @@ hookdeck gateway connection delete <connection-id> [flags]
514527
515528
```bash
516529
# Delete a connection (with confirmation)
517-
hookdeck connection delete conn_abc123
530+
hookdeck gateway connection delete conn_abc123
518531
519532
# Force delete without confirmation
520-
hookdeck connection delete conn_abc123 --force
533+
hookdeck gateway connection delete conn_abc123 --force
521534
```
522535
### hookdeck gateway connection upsert
523536
@@ -542,6 +555,12 @@ Create a new connection or update an existing one by name (idempotent).
542555
hookdeck gateway connection upsert <name> [flags]
543556
```
544557
558+
**Arguments:**
559+
560+
| Argument | Type | Description |
561+
|----------|------|-------------|
562+
| `name` | `string` | **Required.** Connection name (create or update by name) |
563+
545564
**Flags:**
546565
547566
| Flag | Type | Description |
@@ -584,10 +603,10 @@ hookdeck gateway connection upsert <name> [flags]
584603
| `--rule-deduplicate-include-fields` | `string` | Comma-separated list of fields to include for deduplication |
585604
| `--rule-deduplicate-window` | `int` | Time window in seconds for deduplication (default "0") |
586605
| `--rule-delay` | `int` | Delay in milliseconds (default "0") |
587-
| `--rule-filter-body` | `string` | JQ expression to filter on request body |
588-
| `--rule-filter-headers` | `string` | JQ expression to filter on request headers |
589-
| `--rule-filter-path` | `string` | JQ expression to filter on request path |
590-
| `--rule-filter-query` | `string` | JQ expression to filter on request query parameters |
606+
| `--rule-filter-body` | `string` | Filter on request body using Hookdeck filter syntax (JSON) |
607+
| `--rule-filter-headers` | `string` | Filter on request headers using Hookdeck filter syntax (JSON) |
608+
| `--rule-filter-path` | `string` | Filter on request path using Hookdeck filter syntax (JSON) |
609+
| `--rule-filter-query` | `string` | Filter on request query parameters using Hookdeck filter syntax (JSON) |
591610
| `--rule-retry-count` | `int` | Number of retry attempts (default "0") |
592611
| `--rule-retry-interval` | `int` | Interval between retries in milliseconds (default "0") |
593612
| `--rule-retry-response-status-codes` | `string` | Comma-separated HTTP status codes to retry on |
@@ -617,22 +636,22 @@ hookdeck gateway connection upsert <name> [flags]
617636
618637
```bash
619638
# Create or update a connection with inline source and destination
620-
hookdeck connection upsert "my-connection" \
639+
hookdeck gateway connection upsert "my-connection" \
621640
--source-name "stripe-prod" --source-type STRIPE \
622641
--destination-name "my-api" --destination-type HTTP --destination-url https://api.example.com
623642
624643
# Update just the rate limit on an existing connection
625-
hookdeck connection upsert my-connection \
644+
hookdeck gateway connection upsert my-connection \
626645
--destination-rate-limit 100 --destination-rate-limit-period minute
627646
628647
# Update source configuration options
629-
hookdeck connection upsert my-connection \
648+
hookdeck gateway connection upsert my-connection \
630649
--source-allowed-http-methods "POST,PUT,DELETE" \
631650
--source-custom-response-content-type "json" \
632651
--source-custom-response-body '{"status":"received"}'
633652
634653
# Preview changes without applying them
635-
hookdeck connection upsert my-connection \
654+
hookdeck gateway connection upsert my-connection \
636655
--destination-rate-limit 200 --destination-rate-limit-period hour \
637656
--dry-run
638657
```
@@ -645,6 +664,12 @@ Enable a disabled connection.
645664
```bash
646665
hookdeck gateway connection enable <connection-id>
647666
```
667+
668+
**Arguments:**
669+
670+
| Argument | Type | Description |
671+
|----------|------|-------------|
672+
| `connection-id` | `string` | **Required.** Connection ID |
648673
### hookdeck gateway connection disable
649674
650675
Disable an active connection. It will stop receiving new events until re-enabled.
@@ -654,6 +679,12 @@ Disable an active connection. It will stop receiving new events until re-enabled
654679
```bash
655680
hookdeck gateway connection disable <connection-id>
656681
```
682+
683+
**Arguments:**
684+
685+
| Argument | Type | Description |
686+
|----------|------|-------------|
687+
| `connection-id` | `string` | **Required.** Connection ID |
657688
### hookdeck gateway connection pause
658689
659690
Pause a connection temporarily.
@@ -665,6 +696,12 @@ The connection will queue incoming events until unpaused.
665696
```bash
666697
hookdeck gateway connection pause <connection-id>
667698
```
699+
700+
**Arguments:**
701+
702+
| Argument | Type | Description |
703+
|----------|------|-------------|
704+
| `connection-id` | `string` | **Required.** Connection ID |
668705
### hookdeck gateway connection unpause
669706
670707
Resume a paused connection.
@@ -676,6 +713,12 @@ The connection will start processing queued events.
676713
```bash
677714
hookdeck gateway connection unpause <connection-id>
678715
```
716+
717+
**Arguments:**
718+
719+
| Argument | Type | Description |
720+
|----------|------|-------------|
721+
| `connection-id` | `string` | **Required.** Connection ID |
679722
<!-- GENERATE_END -->
680723
## Sources
681724
@@ -1864,6 +1907,7 @@ hookdeck ci [flags]
18641907
| Flag | Type | Description |
18651908
|------|------|-------------|
18661909
| `--api-key` | `string` | Your Hookdeck Project API key. The CLI reads from HOOKDECK_API_KEY if not provided. |
1910+
| `--local` | `bool` | Save credentials to current directory (.hookdeck/config.toml) |
18671911
| `--name` | `string` | Name of the CI run (ex: GITHUB_REF) for identification in the dashboard |
18681912
18691913
**Examples:**

0 commit comments

Comments
 (0)