This guide explains how to test and debug the GitHub development tracking flow in Vector.
Use it when you need to verify:
- GitHub App or token fallback setup
- repo sync and repo selection
- manual linking from an issue
- automatic linking from regex matches
- webhook-driven PR and GitHub issue state updates
- commit linking and child-issue commit rollups
- unlink and suppression behavior
If you just want the shortest possible path, do this:
-
Create a GitHub App in
GitHub -> Settings -> Developer settings -> GitHub Apps. -
Copy these values from GitHub:
App ID-> use asGITHUB_APP_ID- generated
.pemprivate key -> use asGITHUB_APP_PRIVATE_KEY
-
Generate an encryption key locally:
openssl rand -base64 32
Use that as
GITHUB_TOKEN_ENCRYPTION_KEY. -
Set those 3 values in your Convex environment.
-
Install the GitHub App on the repo owner you want to test.
-
Copy the installation details:
- installation ID from the GitHub installation URL
- account login from the installed user/org name
- account type as
UserorOrganization
-
Open Vector at
/{orgSlug}/settings. -
In the
GitHubsection:- paste installation ID
- paste account login
- paste account type
- click
Save
-
Click
Generate webhook secretand copy the generated value into the GitHub App webhook settings. -
Click
Sync repos. -
Select at least one repo.
-
Open an issue and paste a GitHub PR, issue, or commit URL into
Development. -
If that works, move on to webhook and auto-link testing.
Run the app locally:
pnpm run convex:dev
pnpm run devSet these environment variables before testing GitHub automation:
GITHUB_APP_IDGITHUB_APP_PRIVATE_KEYGITHUB_TOKEN_ENCRYPTION_KEY
These values are used by the Convex backend, so set them in your Convex environment for the local deployment you are testing.
Notes:
GITHUB_TOKEN_ENCRYPTION_KEYis required to store admin-pasted token fallbacks securely.- GitHub webhook secrets are generated per workspace in Vector settings and stored in Convex data, not in a Convex env var.
- If you do not want to wire the GitHub App yet, you can still test most flows with the token fallback from the org settings UI.
- The webhook endpoint is
POST /webhooks/github.
If you are new to GitHub Apps, do this in order.
In GitHub:
- Open
GitHub -> Settings -> Developer settings -> GitHub Apps. - Click
New GitHub App. - Fill in the form as described below.
- Under repository permissions, give the app at least:
Contents:Read-onlyPull requests:Read-onlyIssues:Read-onlyMetadata: GitHub Apps always have metadata access; GitHub docs note metadata is always available at least read-only
- Under webhook subscriptions, enable:
Pull requestIssuesPushInstallationInstallation repositories
- Create the app.
This maps to the fields in your screenshot.
What to enter:
- use a unique name such as
vector-local-syed
Tips:
- GitHub App names must be unique enough not to collide with existing apps and users
- do not use just
vectorunless GitHub accepts it - if you are testing locally, include your name or team name
What to enter:
- something simple like
GitHub sync for Vector local testing
This is only descriptive. It does not affect the integration.
What to enter:
- use a safe public URL such as your repo URL
- example:
https://github.com/xrehpicx/vector
Recommended:
- use a public repo/docs URL, not
http://localhost:3000
Reason:
- GitHub’s docs warn not to put sensitive internal URLs into app registration fields
- this field is only informational for users
What to do:
- leave it blank
- if GitHub auto-added an empty callback row, remove it if the UI allows
Reason:
- Vector does not currently use GitHub’s user OAuth flow during installation
- callback URLs are only needed if you enable user authorization during install
What to do:
- leave the default alone
Reason:
- Vector is not using user authorization tokens for this setup
- this setting is not important for the current integration
What to do:
- keep this unchecked
Reason:
- Vector authenticates as the app installation, not as each GitHub user
- if you enable this, GitHub expects a callback URL and a user auth flow that Vector does not currently implement
What to do:
- keep this unchecked
Reason:
- Vector is not a CLI device-auth app in this flow
Scroll to the webhook section of the form and set:
- turn this on
What to enter:
- your public tunnel URL plus
/webhooks/github
Example:
https://your-ngrok-or-cloudflared-url/webhooks/github
If you put just the site URL without /webhooks/github, GitHub will happily send events to the wrong place and then act shocked when nothing works.
What to enter:
- if GitHub requires a value during app creation, use any temporary random string
Example:
openssl rand -base64 32Before testing webhook deliveries, copy the generated secret from Vector's org settings into the GitHub App webhook secret field. Vector verifies signatures against the per-workspace secret stored with the integration, not an env var.
In the repository permissions section, set:
Contents->Read-onlyIssues->Read-onlyPull requests->Read-only
You do not need write permissions for Vector’s current GitHub tracking flow because it only reads PRs, issues, commits, and repo metadata.
In the webhook event subscriptions section, enable:
Pull requestIssuesPushInstallationInstallation repositories
These are the events Vector’s backend currently processes.
If GitHub shows a Setup URL section:
- leave
Setup URLblank - leave
Redirect on updateoff
Reason:
- Vector’s current settings flow is manual in the org settings page
- it does not yet implement a post-install redirect flow
For local testing, prefer a private app:
Only on this accountif the repos live under the same personal account or org that owns the app
Important:
- if your test repos are in a GitHub organization, the easiest setup is to create the app under that same organization
- GitHub’s docs say a private app can only be installed on the account that owns it
- if you create it under your personal account and want to install it elsewhere, you may need broader visibility
Where to get it:
- Open your GitHub App.
- On the app overview page, look for
App ID.
That number is the value for GITHUB_APP_ID.
Where to get it:
- Open your GitHub App.
- Go to
Private keys. - Click
Generate a private key. - GitHub downloads a
.pemfile.
That .pem file content is the value for GITHUB_APP_PRIVATE_KEY.
Important:
- keep the full file content
- include the
-----BEGIN ...-----and-----END ...-----lines - when storing it in Convex env, use escaped
\nline breaks
Where to get it:
- generate your own random secret locally
Example:
openssl rand -base64 32Use the generated value as GITHUB_TOKEN_ENCRYPTION_KEY.
The easiest approach is the Convex dashboard for your local deployment, but the CLI works too.
- Open your Convex deployment dashboard.
- Go to environment variables.
- Add:
GITHUB_APP_IDGITHUB_APP_PRIVATE_KEYGITHUB_TOKEN_ENCRYPTION_KEY
For GITHUB_APP_PRIVATE_KEY:
- open the downloaded
.pemfile - convert the line breaks to literal
\n - paste that single escaped value into Convex
Example commands:
pnpm convex env set GITHUB_APP_ID 123456
pnpm convex env set GITHUB_TOKEN_ENCRYPTION_KEY "$(openssl rand -base64 32)"
pnpm convex env set GITHUB_APP_PRIVATE_KEY "$(perl -0pe 's/\n/\\n/g' ~/Downloads/your-github-app.private-key.pem)"The private key command reads the .pem file and converts real line breaks into escaped \n, which is what the backend expects.
In GitHub:
- Open your GitHub App.
- Click
Install App. - Choose the GitHub user or organization that owns the repos you want to test.
- Choose either:
All repositories- or
Only select repositories
- Install the app.
Vector settings currently ask for:
- installation ID
- installation account login
- installation account type
Here is how to get each one.
Where to get it:
- Open the installed app in GitHub.
- Look at the browser URL.
Example:
https://github.com/settings/installations/12345678
In that URL, 12345678 is the installation ID.
Where to get it:
- this is the GitHub username or organization name where the app was installed
Examples:
acmeyour-user-name
Use one of:
OrganizationUser
If you installed the app on a GitHub organization, use Organization.
If you installed it on your personal GitHub account, use User.
In Vector:
- Open
/{orgSlug}/settings. - In the
GitHubsection:- paste the installation ID
- paste the account login
- paste the account type
- Click
Save. - Click
Sync repos. - Select at least one repo.
Expected result:
- selected repos become available for linking
- the app connection badge shows as connected
- repo sync health starts showing real values
If you want the simplest possible test setup, use a GitHub token fallback.
Create a fine-grained personal access token in GitHub with access to the repos you want to test and at least:
- metadata read
- contents read
- pull requests read
- issues read
Then:
- open
/{orgSlug}/settings - paste the token into
Token Fallback - click
Save - click
Sync repos - select the repos you want Vector to scan
Open:
/{orgSlug}/settings
In the GitHub section:
- Save GitHub App installation metadata.
- Or paste a GitHub token fallback.
- Click
Sync repos. - Select at least one repository.
Expected result:
- the repo appears in the selected list
- app/token status badges appear
- webhook/reconcile health fields stop looking empty and sad
Automation expects these workflow state types to exist in the org:
todoin_progressdonecanceled
If one of those types is missing, GitHub automation cannot move issues correctly.
- Open an issue detail page.
- In
Development, paste one of:- a GitHub PR URL
- a GitHub issue URL
- a GitHub commit URL
- Click
Link.
Expected result:
- the artifact appears in the
Developmentsection - the artifact shows repo, status, and last sync time
- manual links show a
manualbadge
If it fails:
- make sure the repo is selected in org settings
- make sure the URL points to a selected repo
- make sure GitHub auth is configured
- Create a Vector issue like
ENG-123. - Create a GitHub PR in a selected repo.
- Put
ENG-123in one of:- PR title
- PR body
- head branch name
- Deliver the webhook or wait for reconciliation.
Expected result:
- the PR appears automatically in the issue
Developmentsection - it shows an
autobadge
Matching rules:
- matching is case-insensitive
- the issue key must be a standalone token
- comments are not scanned in v1
With an auto-linked or manually linked PR:
- Mark it draft.
- Open it.
- Close it without merging.
- Reopen it.
- Merge it.
Expected issue workflow changes:
draft->in_progressopen->in_progressclosedand not merged ->canceledreopened->in_progressmerged->done
Check these surfaces:
- issue detail header state selector
- issues table
- issues kanban
- project issue views
- team issue views
This only matters when no linked PR is currently controlling the issue.
- Create a GitHub issue in a selected repo.
- Put the Vector issue key in the GitHub issue title or body.
- Open, close, and reopen the GitHub issue.
Expected issue workflow changes:
open->todoreopened->todoclosed->done
- Create a parent issue, for example
ENG-200. - Create a child issue under it, for example
ENG-201. - Push a commit whose message contains
ENG-201. - Deliver the push webhook or wait for reconciliation.
Expected result:
- the commit links directly to
ENG-201 ENG-201shows the commit in itsDevelopmentsectionENG-200shows the commit inChild Issue Commits- the parent does not get a direct commit link unless its own key is referenced
- Let an artifact auto-link to an issue.
- In the issue
Developmentsection, clickSuppress. - Re-deliver the webhook or wait for reconciliation.
- Manually link another artifact, click
Unlink, and re-deliver its webhook. - Link one artifact to two Work items, unlink it from only one, and re-deliver its webhook.
Expected result:
- both artifacts stay unlinked
- neither comes back or creates unmatched Work/Requests on the next sync
- manually linking either artifact again reverses its durable unlink decision
- a partially unlinked artifact remains
linkedwhile its other attachment is active, and the suppression applies only to the Work/Task scope that was removed
- Link a PR.
- Let the cached data become old, or just change the PR in GitHub.
- Open the issue page.
- Click
Refreshif needed.
Expected result:
- stale artifacts are marked
Stale - opening the page triggers a refresh when the cache is old
- manual refresh updates the displayed status
The webhook endpoint is:
/webhooks/github
Events handled in v1:
pull_requestissuespushinstallationinstallation_repositories
Recommended local test loop:
- expose your local app with a tunnel
- point the GitHub App webhook to your tunnel URL
- use GitHub webhook delivery logs to redeliver events after code changes
If webhook delivery is failing:
- verify the webhook secret in the GitHub App matches the secret currently generated in Vector
- verify the webhook points to the correct environment
- verify the repo is selected in Vector
- verify the GitHub App or token has access to that repo
The reconcile job runs every 10 minutes.
Use it to test:
- missed webhook recovery
- newly discoverable links in recent PRs/issues/commits
- repo access changes
Expected behavior:
- recent artifacts from the last 14 days are refreshed
- linked artifacts are refreshed even if webhooks were missed
Check:
- the repo exists in org settings
- the repo is selected
- the URL matches the repo exactly
Check:
- the issue key is in PR title/body/branch, commit message, or GitHub issue title/body
- the repo is selected
- the webhook event actually arrived
- the artifact is recent enough for reconcile
Check:
- the org has
todo,in_progress,done, andcanceledworkflow state types - the artifact link is active
- a linked PR is not overriding the GitHub issue state
Check:
- the artifact was not explicitly linked again after the unlink or suppression
- the Development inbox record is still
dismissed - the webhook and reconciliation paths are using the latest deployment
Check:
- the
Refreshbutton on the issue page - the org settings sync health
- webhook delivery logs
When debugging, start here:
convex/github/actions.tsconvex/github/mutations.tsconvex/github/queries.tsconvex/github/shared.tssrc/components/issues/issue-development-section.tsxsrc/components/organization/github-integration-settings.tsx
If you only want a fast sanity pass:
- configure GitHub in org settings
- sync repos and select one repo
- manually link one PR URL
- auto-link one PR with an issue key in the title
- close, reopen, and merge that PR
- push one commit for a child issue
- suppress one auto-linked artifact and confirm it stays gone