Skip to content

feat(github): add GitHub App integration#19641

Draft
amCap1712 wants to merge 3 commits into
WeblateOrg:mainfrom
amCap1712:github-integration
Draft

feat(github): add GitHub App integration#19641
amCap1712 wants to merge 3 commits into
WeblateOrg:mainfrom
amCap1712:github-integration

Conversation

@amCap1712
Copy link
Copy Markdown
Contributor

@amCap1712 amCap1712 commented May 18, 2026

Implement GitHub App based authentication as an alternative to personal access tokens for GitHub-backed repositories. The integration stores the app configuration and installation metadata, exchanges app credentials for installation access tokens, and uses those tokens when Weblate performs GitHub repository operations.

Screenshot From 2026-05-18 15-30-20 Example of a PR opened by the app: https://github.com/amCap1712/weblate-test/pull/2

@amCap1712
Copy link
Copy Markdown
Contributor Author

I am working on more testing to ensure that adding the github integration doesn't break existing github pull request or other git integrations.

@nijel
Copy link
Copy Markdown
Member

nijel commented May 18, 2026

Does it work for organization-scoped repos as well? (I will look in more detail later, I'm just curious)

@amCap1712
Copy link
Copy Markdown
Contributor Author

Yes it should but I have not had the opportunity to test it because of lack of organization access to install it in.

Comment thread weblate/vcs/github.py
on_delete=models.SET_NULL,
null=True,
blank=True,
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether scoping this to the user is the right approach. The user indeed has to initiate this, but shouldn't the connection be bound to a project? Or workspace once #19535 lands?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, good point. I will rework this to project for now and yes workspace seems to make more sense once available.

kwargs["existing_form"] = kwargs["form"]
installations = GitHubInstallation.objects.filter(enabled=True).order_by(
"target_login", "hostname"
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should do some scope filtering, in this way, it exposes all site GitHub installations to all users.

@nijel
Copy link
Copy Markdown
Member

nijel commented May 23, 2026

This is Codex review of the changes:

  • [P1] Validate GitHub remote URLs before probing — /home/nijel/weblate/weblate/weblate/vcs/git.py:2097-2100
    This override dropped the validate_remote_url() call that the base Git implementation performs before git ls-remote. When a user selects the GitHub VCS driver with a URL resolving to a private or otherwise disallowed host, Weblate now runs ls-remote before the outbound/private-
    network checks can reject it, bypassing the existing VCS_RESTRICT_PRIVATE protection; validate repo before _popen.
  • [P2] Do not require app signatures for legacy GitHub webhooks — /home/nijel/weblate/weblate/weblate/trans/views/hooks.py:562-563
    This fallback assigns the single configured GitHub App host even to ordinary push webhooks that have no installation payload. _authenticate_github_app_webhook() then enforces the app webhook secret, so existing repository webhooks start returning 403 unless they were also
    configured with the App secret; only app deliveries, or deliveries whose signature actually identifies a host, should be forced through that check.
  • [P2] Use the GitHub Enterprise app install path — /home/nijel/weblate/weblate/weblate/vcs/github.py:109-110
    For hosts other than github.com, GitHub Enterprise Server exposes GitHub App installation pages under /github-apps//..., not /apps//.... With the current URL, the documented Enterprise host flow sends users to a non-existent install page, so the prefix needs to be
    conditional on the configured hostname.

@nijel nijel self-assigned this May 23, 2026
@nijel
Copy link
Copy Markdown
Member

nijel commented May 25, 2026

Thinking more about this, I don't think the app should use the same webhook endpoint as generic GitHub hooks. The app hooks should always require signing and should do no fuzzy matching on the repositories, as the repository URL is configured via the app.

@amCap1712
Copy link
Copy Markdown
Contributor Author

Makes sense, will update.

Have you been able to test this manually yet? I can deploy a version locally and expose it online for you to access and test if not.

@nijel
Copy link
Copy Markdown
Member

nijel commented May 25, 2026

I will get to it soon. First, I want to land basic workspaces code to main.

@nijel
Copy link
Copy Markdown
Member

nijel commented May 26, 2026

Just tried this:

  • The app creation is non-obvious (what should be Callback URL, is there some expected Setup URL, what permissions and event subscriptions are needed), so the documentation really needs to cover this
  • Because of not setting the some of the URLs (probably) the workflow is not smooth - you choose repositories to access and end up on the GitHub app settings page rather than going back to Weblate to continue with the import
  • The "Import" button doesn't preserve the project passed to the create page
  • Should we allow editing of the repository URLs when configured via GitHub app? That could potentially leak the credentials to other services and will most likely break the integration. Perhaps using separate VCS backend which will restrict these changes would be better.
  • It worked just fine for organization scoped repo (Translations update from Weblate github-app-testing#1)

@nijel nijel added this to the 2026.7 milestone May 26, 2026
@amCap1712
Copy link
Copy Markdown
Contributor Author

  1. I documented some things but yeah it seems I forgot to add that. Will fix.
  2. Not sure what you mean by this one, can you share a screen recording maybe where it breaks?
  3. Will fix.
  4. A separate backend would definitely simplify things, will do.
  5. I see workspaces is now merged so I'll rework this to connect to that instead of project.

@nijel
Copy link
Copy Markdown
Member

nijel commented May 26, 2026

2 is IMHO caused by not setting callback/setup URLs on GitHub. After selecting where to install the GitHub app, I ended up on https://github.com/settings/installations/135697804 rather than in Weblate where I would choose which repo to import.

Yes, the basics of workspaces are now there, but I have several follow-up pull requests prepared so that it doesn't all land in one massive change (#19729 is the current next step).

@nijel
Copy link
Copy Markdown
Member

nijel commented May 26, 2026

While working on the workspaces, I this we can make the GitHub app work only with workspaces and do not support project-scoped installs at all. This will simplify the code and the limitation should not be that constraining, it just needs to be documented.

amCap1712 added 2 commits May 29, 2026 12:28
Implement GitHub App based authentication as an alternative to personal access
tokens for GitHub-backed repositories. The integration stores the app
configuration and installation metadata, exchanges app credentials for
installation access tokens, and uses those tokens when Weblate performs GitHub
repository operations.
Add one-click registration from Manage → Weblate GitHub Apps. The
form POSTs a GitHub App manifest containing the required permissions,
events, and webhook URL; GitHub returns the App ID, slug, private
key, and webhook secret, which Weblate stores in a new
GitHubAppCredentials table.

Also, move the github app creation from project level to workspace level.
@amCap1712 amCap1712 force-pushed the github-integration branch from f10dfa3 to 7845c2a Compare May 29, 2026 17:17
@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

@amCap1712
Copy link
Copy Markdown
Contributor Author

I have added an option to register an application automatically. Currently the downside is that the credentials are stored in the database but we can change it to showing the credentials to the user on the website and having them manually update settings.py. What do you think?

image

I was trying to generate some tests with codex but I don't think they are upto the mark yet so I will iterate on them manually. Let me know if you think any other major changes are needed for the integration before I proceed with that.

@nijel
Copy link
Copy Markdown
Member

nijel commented Jun 1, 2026

The registration looks nice and makes it harder to mess up the setup. Storing the credentials in the database is IMHO okay.

I'm still unsure about the hooks code, I don't think we should do that much of guessing there. How about exposing hook per integration (let's say /hooks/integrations/<ID>/) and that would be configured in the GitHub app and verify only it's secret. Eventually we want to phase out unauthenticated hooks and this would eventually allow us to use authentication even for manual hooks (given they will get the integration).

Overall while this PR is GitHub specific, it should be prepared for a generalization later.

For integration/webhooks, we would like to support other code sites such as GitLab or Forgejo. So the model should be prepared for that. Enabling authenticated webhooks (via the integration) should disable unauthenticated hooks on that component.

For VCS integration:

  • the site admin would configure the integrations.
  • the workspace admin can connect it to the code hosting organization (or individual account)
  • the component creation would then default to selection of repos exposed by the integration

This is not the scope we need to cover in this pull request, but the GitHub integration should go in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants