Skip to main content

What this guide does

Use this guide when you want to wire SelfTune Cloud to GitHub so a repository can publish into the registry through the GitHub App flow. This guide covers:
  1. Creating the GitHub App
  2. Wiring SelfTune environment variables
  3. Applying the required migration
  4. Binding an installation in the dashboard
  5. Verifying manual sync and webhook publishing
SelfTune can publish from GitHub by default. If you also grant Checks and Commit statuses permissions, it can post publish results back to GitHub as check-runs and commit statuses. It still does not open pull requests, create releases, or push commits back to your repo.

Prerequisites

  • A deployed SelfTune API reachable from GitHub webhooks
  • A deployed SelfTune dashboard reachable by users after GitHub App installation
  • A Pro-or-higher SelfTune org
  • A GitHub account or GitHub organization where you can install apps
  • A registry entry you want to publish into, or permission to create one
You also need the GitHub migration applied:
drizzle/0017_github_registry_foundation.sql
drizzle/0018_github_write_back.sql

Architecture

GitHub App install -> dashboard callback -> bind installation to org
GitHub push/tag webhook -> SelfTune API -> package repo -> push registry version
Dashboard/manual sync -> SelfTune API -> fetch repo -> push registry version

Step 1: Register the GitHub App

Create a GitHub App in GitHub settings and use these values.
SettingValue
App nameYour production app name, for example SelfTune Cloud
Homepage URLYour dashboard base URL, for example https://selftune.dev
Setup URLhttps://selftune.dev/settings/github
Webhook URLhttps://api.selftune.dev/api/v1/github/webhook
Webhook secretGenerate a random secret and store it as GITHUB_WEBHOOK_SECRET
Adjust the hostnames to match your actual deployment domains.

Repository permissions

Use the current minimum permission set:
PermissionAccess
ContentsRead-only
MetadataRead-only

Optional write-back permissions

If you want SelfTune to post publish results back to GitHub, also grant:
PermissionAccessWhy
ChecksRead & writeCreate and update GitHub check-runs for publish attempts
Commit statusesRead & writePost commit status fallback for the same publish attempts

Subscribe to events

Enable these webhook events:
EventWhy SelfTune needs it
pushPublish commit-based versions from the configured default branch
createPublish release versions from matching Git tags
installationTrack install, suspend, unsuspend, and delete lifecycle
installation_repositoriesDetect repo access changes on an installation
Keep the app unlisted until you have verified the full flow in a staging or internal environment.

Step 2: Configure SelfTune environment variables

API service

Set these variables for the API process:
GITHUB_APP_ID=1234567
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"
GITHUB_WEBHOOK_SECRET="replace-with-random-secret"
These are read in packages/api/src/config.ts.

Dashboard

Set the GitHub install URL for the dashboard process:
NEXT_PUBLIC_GITHUB_APP_INSTALL_URL="https://github.com/apps/YOUR-APP-SLUG/installations/new"
This enables the one-click install button in the dashboard GitHub settings page at src/app/settings/github/page.tsx.

Step 3: Apply the database migration

Apply the GitHub registry foundation migration before using the dashboard flow:
bunx drizzle-kit migrate
That migration creates:
  • github_installations
  • github_connections
  • github_publish_attempts
  • registry visibility and GitHub source metadata fields
  • org-level and connection-level write-back settings

Step 4: Restart the services

After setting env vars and applying the migration, restart:
  • the API service
  • the dashboard service
The API must come back with the GitHub credentials loaded, or repo listing and webhook handling will fail.

Step 5: Install and bind the GitHub App

1

Open the dashboard GitHub settings page

Go to /settings/github in the dashboard.
2

Install the GitHub App

Click Connect GitHub App, or go directly to the install URL you set in NEXT_PUBLIC_GITHUB_APP_INSTALL_URL.
3

Choose the GitHub account and repositories

Install the app on the GitHub user or organization that owns the skill repository. Limit the install to the repos you want SelfTune to read.
4

Return to SelfTune

GitHub redirects back to /settings/github?installation_id=....
5

Verify the installation was bound

The dashboard should show the installation under the bound-installations list and display the connected state.

Step 6: Connect a repository to a registry entry

From the same GitHub settings page:
  1. Select the bound installation
  2. Pick the target registry entry
  3. Pick the GitHub repo
  4. Confirm default_branch
  5. Confirm or choose skill_path
  6. Set the tag pattern, usually v*
  7. Save the connection
If the repo is a monorepo, the dashboard should discover SKILL.md paths and let you choose the correct subpath.

Step 7: Verify publishing

Run the verification in this order.

Manual sync

Use the dashboard Sync now control first. Expected result:
  • a GitHub-backed version is created in the registry
  • the version source is github
  • the version source_ref is the commit SHA

Default-branch push

Push a commit to the connected default branch. Expected result:
  • the webhook reaches /api/v1/github/webhook
  • SelfTune packages the skill path
  • a new prerelease-style version is published, such as 0.0.0-github.abcdef1

Tag publish

Push a matching tag such as v1.2.0. Expected result:
  • the webhook create event is accepted
  • the connection’s tag_pattern matches
  • a registry version is published using the tag-derived version number

Optional write-back verification

If you enabled the optional GitHub permissions:
  1. In the dashboard, set org write-back mode to checks
  2. Enable write-back on one repo connection
  3. Run Sync now
Expected result:
  • the commit receives a selftune/publish/... status context
  • the commit or pull request shows a Selftune publish check-run
  • success, skip, and failure outcomes match the registry publish result

Smoke-test checklist

Use this after initial setup:
  • GET /api/v1/github/installations returns the bound installation
  • GET /api/v1/github/repos?installation_id=... returns the expected repos
  • the dashboard can discover SKILL.md paths for the repo
  • manual sync publishes successfully
  • a push to the default branch auto-publishes
  • a matching tag auto-publishes
  • disconnecting the connection leaves already-published registry versions intact
  • deleting the GitHub installation removes the bound installation row
  • optional write-back posts a commit status and check-run when enabled

Troubleshooting

The dashboard says GitHub install is unavailable

Check:
  • NEXT_PUBLIC_GITHUB_APP_INSTALL_URL is set on the dashboard
  • the dashboard was restarted after setting it

Repo listing fails

Check:
  • GITHUB_APP_ID
  • GITHUB_APP_PRIVATE_KEY
  • the GitHub App is installed on the selected account
  • the selected repo is included in the installation scope

Webhook publishing does not fire

Check:
  • the GitHub App webhook URL points to /api/v1/github/webhook
  • GITHUB_WEBHOOK_SECRET matches the GitHub App webhook secret
  • the push and create events are subscribed
  • the repo connection exists and auto_publish is enabled

Manual sync says No SKILL.md found

Check:
  • skill_path points at the actual skill root
  • the repo contains SKILL.md at that path
  • monorepo discovery returned the expected path

Current limitation: no PR or branch mutation write-back

SelfTune now supports Tier A write-back: commit statuses and check-runs. It still does not support:
  • remediation pull request creation
  • direct branch or tag mutation
  • release creation
Keep those as a separate future permission tier. That lets teams adopt repo-to-registry publishing and publish-result visibility without granting source mutation access to the GitHub App. If you want to plan the next tier, use this permission model:
CapabilitySuggested permission changeWhy
Check-runs and commit statusesChecks: Read & write, Commit statuses: Read & writeShow publish and validation results on commits and PRs without mutating repo contents
Remediation pull requestsPull requests: Read & write, Contents: Read & writeLet SelfTune open fix PRs for cases like missing metadata or packaging issues
Direct branch/tag mutationNot recommended for v1Highest-risk mode; avoid until checks and PR flows are proven