Repo Relay keeps PR-to-message mappings in a SQLite database so embeds keep updating across workflow runs. Where you run the job determines how that state survives between runs.
Self-hosted vs GitHub-hosted
| Aspect | Self-hosted | GitHub-hosted |
|---|---|---|
| State persistence | SQLite persists in ~/.repo-relay/ | Requires actions/cache |
| Setup | Requires runner installation | Zero setup |
| Cost | Your hardware | GitHub Actions minutes |
| Speed | Fast (no cold start) | Roughly 30s cold start |
| Availability | Depends on your uptime | Always available |
| Queue blocking | Can block behind long CI jobs | Isolated from other workflows |
Guidance: use a self-hosted runner if you already have one and want persistent PR tracking with no extra steps. Use ubuntu-latest with actions/cache if you prefer zero infrastructure and isolation from long-running build jobs.
State location
| Runner type | Storage location | Persistence |
|---|---|---|
| Self-hosted (recommended) | ~/.repo-relay/{repo-name}/state.db | Permanent |
| GitHub-hosted | actions/cache | Persistent when cached |
Persisting state on GitHub-hosted runners
Add an actions/cache step before the repo-relay step to persist the state directory between runs:
- uses: actions/cache@v4
with:
path: ~/.repo-relay
key: repo-relay-state-${{ github.repository }}
- uses: blamechris/repo-relay@v1
with:
discord_bot_token: ${{ secrets.DISCORD_BOT_TOKEN }}
channel_prs: ${{ secrets.DISCORD_CHANNEL_PRS }}Notes:
- The cache evicts after 7 days of inactivity, which is fine for active repos.
- There is no security concern: the database contains only Discord message IDs and PR metadata, no secrets.
- If the cache misses, Repo Relay falls back to searching the last 100 channel messages to recover the existing PR message.
Related
- State storage — what is in the database.
- Troubleshooting — queue blocking and other runner issues.