Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!--
PR title: conventional commit style (e.g., "feat: add webhook retry logic", "fix: handle null repo owner"). Do NOT include the ticket/issue ID in the title.

Choose the prefix deliberately based on whether this change should appear in the user-facing changelog. See `release-please-config.json`:
- Visible (appear in CHANGELOG.md): feat, fix, perf, deps, revert
- Hidden (excluded from CHANGELOG.md): docs, chore, style, refactor, test, build, ci

If the change is internal-only — e.g., an agent prompt tweak, a CI fix, a refactor with no user-visible behavior — use a hidden prefix (typically `chore:`) so it does not pollute the release notes. `fix:` is for bugs users could have hit; an internal-only fix is a `chore:`.
-->

## Summary

<!-- 2-3 sentences explaining what changed and why. Write for a human reviewer, not a changelog parser. Include any related issue references here (e.g., "Closes #123", "ENG-456") — not in the title, not in a separate section. -->

## Review focus

<!-- One or two things you genuinely want a reviewer to think hard about — a risky decision, a trade-off, an API choice that could have gone another way. NOT a list of every file touched. If nothing is unusual, write "Nothing unusual" or delete this section entirely. -->

## Commits

<!--
Before opening a PR, rebase the commits on your local branch to make them easy for a human to review commit-by-commit in a PR. Commits like "wip", "fix fmt" etc should be squashed into a clean, logical commit.

When organizing commits, stage changes at the file rather than the hunk level to make things easy on yourself.

Then list them with clickable links (e.g., - [`abc1234`](url) — did the thing).
-->
13 changes: 13 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ jobs:
with:
role-to-assume: ${{ secrets.RELEASE_ROLE_ARN }}

- name: Validate telemetry build config
shell: bash
run: |
set -euo pipefail
for name in __PW_SENTRY_DSN__ __PW_POSTHOG_KEY__ __PW_POSTHOG_HOST__; do
value="${!name:-}"
if [ -z "$value" ]; then
echo "::error::$name is required for release builds" >&2
exit 1
fi
echo "::add-mask::$value"
done

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1
with:
Expand Down
9 changes: 9 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ builds:
- bun-linux-x64
flags:
- --compile
# Telemetry credentials, injected at build time from SSM via
# fetch-release-secrets. buildInfo.ts reads these and falls back to empty
# (disabling telemetry) when they're absent, e.g. local builds.
- --define
- '__PW_SENTRY_DSN__="{{ .Env.__PW_SENTRY_DSN__ }}"'
- --define
- '__PW_POSTHOG_KEY__="{{ .Env.__PW_POSTHOG_KEY__ }}"'
- --define
- '__PW_POSTHOG_HOST__="{{ .Env.__PW_POSTHOG_HOST__ }}"'

# Version-less archive names keep the GitHub `releases/latest/download/<asset>`
# URLs stable across releases, which is what scripts/analyze.sh fetches.
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,23 +97,27 @@ Nothing in the report or bundle leaves your machine unless you choose to share i

## What it does not do

- It does not upload the report or any GitHub data unless you choose to share the generated artifacts. It reads from `api.github.com`. Filesystem writes are limited to the `patchwave-report.html` / `patchwave-report.zip` pair in a temporary directory and a one-time anonymous-id file (see Telemetry).
- It does not upload the report or any GitHub data unless you choose to share the generated artifacts. It reads from `api.github.com`. Filesystem writes are limited to the `patchwave-report.html` / `patchwave-report.zip` pair in a temporary directory and a one-time anonymous-id file (see Telemetry & privacy).
- It does not keep a Markdown compatibility report.
- It does not auto-update.

## Telemetry
## Telemetry & privacy

The CLI sends anonymous product analytics (PostHog) to help us understand how it's used. A random UUID is stored at `$XDG_CONFIG_HOME/contextbridge/anonymous_id` or `~/.config/contextbridge/anonymous_id` and shared across contextbridge tools. **Org names, repo names, tokens, and report contents are never sent** — only event counts and timings.
The CLI reports anonymous usage analytics and crash diagnostics so we can improve it. Both share a random UUID stored at `$XDG_CONFIG_HOME/contextbridge/anonymous_id` (or `~/.config/contextbridge/anonymous_id`) and used across contextbridge tools. **Org names, repo names, tokens, report contents, and your machine's hostname are never sent.**

We capture coarse usage events when a run starts, finishes, or fails, and the choices you make at the share and open promptsalong with aggregate counts (such as repos, PRs, and warnings), durations, and error kinds.
**Product analytics (PostHog)** — coarse usage events only: when a run starts, finishes, or fails, and the choices you make at the share and open prompts, along with aggregate counts (repos, PRs, warnings), durations, and error kinds.

Opt out by setting any of:
**Error reporting (Sentry)** — only when the CLI hits an _unexpected_ crash. It sends the error and stack trace, the release version, the anonymous id, and generic environment context (OS, CPU architecture, runtime version, locale/timezone). To keep the guarantee above, breadcrumbs and request data are dropped and the hostname is stripped before anything is sent. Expected problems — bad arguments, missing GitHub auth, GitHub API errors, or failed writes — are shown to you in the prompt and recorded as anonymous analytics, but are **not** sent to Sentry.

Telemetry keys are baked only into official released binaries, so builds you make yourself from source send nothing.

Both are disabled together by setting any of:

- `DO_NOT_TRACK=1`
- `CONTEXTBRIDGE_TELEMETRY_DISABLED=1`
- `CI=1`

When disabled, no anonymous-id file is created and no events are sent.
When disabled, no anonymous-id file is created, no analytics events are sent, and Sentry is never initialized.

## License

Expand Down
Loading
Loading