mirror of
https://github.com/go-gitea/gitea.git
synced 2026-03-10 22:06:34 -05:00
Plugin Mechanism #9126
Open
opened 2025-11-02 08:30:09 -06:00 by GiteaMirror
·
41 comments
No Branch/Tag Specified
main
release/v1.25
release/v1.24
release/v1.23
release/v1.22
release/v1.21
release/v1.20
release/v1.19
release/v1.18
release/v1.17
release/v1.16
release/v1.15
release/v1.14
release/v1.13
release/v1.12
release/v1.11
release/v1.10
release/v1.9
release/v1.8
v1.25.3
v1.25.2
v1.25.1
v1.25.0
v1.24.7
v1.25.0-rc0
v1.26.0-dev
v1.24.6
v1.24.5
v1.24.4
v1.24.3
v1.24.2
v1.24.1
v1.24.0
v1.23.8
v1.24.0-rc0
v1.25.0-dev
v1.23.7
v1.23.6
v1.23.5
v1.23.4
v1.23.3
v1.23.2
v1.23.1
v1.23.0
v1.23.0-rc0
v1.24.0-dev
v1.22.6
v1.22.5
v1.22.4
v1.22.3
v1.22.2
v1.22.1
v1.22.0
v1.23.0-dev
v1.22.0-rc1
v1.21.11
v1.22.0-rc0
v1.21.10
v1.21.9
v1.21.8
v1.21.7
v1.21.6
v1.21.5
v1.21.4
v1.21.3
v1.21.2
v1.20.6
v1.21.1
v1.21.0
v1.21.0-rc2
v1.21.0-rc1
v1.20.5
v1.22.0-dev
v1.21.0-rc0
v1.20.4
v1.20.3
v1.20.2
v1.20.1
v1.20.0
v1.19.4
v1.21.0-dev
v1.20.0-rc2
v1.20.0-rc1
v1.20.0-rc0
v1.19.3
v1.19.2
v1.19.1
v1.19.0
v1.19.0-rc1
v1.20.0-dev
v1.19.0-rc0
v1.18.5
v1.18.4
v1.18.3
v1.18.2
v1.18.1
v1.18.0
v1.17.4
v1.18.0-rc1
v1.19.0-dev
v1.18.0-rc0
v1.17.3
v1.17.2
v1.17.1
v1.17.0
v1.17.0-rc2
v1.16.9
v1.17.0-rc1
v1.18.0-dev
v1.16.8
v1.16.7
v1.16.6
v1.16.5
v1.16.4
v1.16.3
v1.16.2
v1.16.1
v1.16.0
v1.15.11
v1.17.0-dev
v1.16.0-rc1
v1.15.10
v1.15.9
v1.15.8
v1.15.7
v1.15.6
v1.15.5
v1.15.4
v1.15.3
v1.15.2
v1.15.1
v1.14.7
v1.15.0
v1.15.0-rc3
v1.14.6
v1.15.0-rc2
v1.14.5
v1.16.0-dev
v1.15.0-rc1
v1.14.4
v1.14.3
v1.14.2
v1.14.1
v1.14.0
v1.13.7
v1.14.0-rc2
v1.13.6
v1.13.5
v1.14.0-rc1
v1.15.0-dev
v1.13.4
v1.13.3
v1.13.2
v1.13.1
v1.13.0
v1.12.6
v1.13.0-rc2
v1.14.0-dev
v1.13.0-rc1
v1.12.5
v1.12.4
v1.12.3
v1.12.2
v1.12.1
v1.11.8
v1.12.0
v1.11.7
v1.12.0-rc2
v1.11.6
v1.12.0-rc1
v1.13.0-dev
v1.11.5
v1.11.4
v1.11.3
v1.10.6
v1.12.0-dev
v1.11.2
v1.10.5
v1.11.1
v1.10.4
v1.11.0
v1.11.0-rc2
v1.10.3
v1.11.0-rc1
v1.10.2
v1.10.1
v1.10.0
v1.9.6
v1.9.5
v1.10.0-rc2
v1.11.0-dev
v1.10.0-rc1
v1.9.4
v1.9.3
v1.9.2
v1.9.1
v1.9.0
v1.9.0-rc2
v1.10.0-dev
v1.9.0-rc1
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.8.0-rc3
v1.7.6
v1.8.0-rc2
v1.7.5
v1.8.0-rc1
v1.9.0-dev
v1.7.4
v1.7.3
v1.7.2
v1.7.1
v1.7.0
v1.7.0-rc3
v1.6.4
v1.7.0-rc2
v1.6.3
v1.7.0-rc1
v1.7.0-dev
v1.6.2
v1.6.1
v1.6.0
v1.6.0-rc2
v1.5.3
v1.6.0-rc1
v1.6.0-dev
v1.5.2
v1.5.1
v1.5.0
v1.5.0-rc2
v1.5.0-rc1
v1.5.0-dev
v1.4.3
v1.4.2
v1.4.1
v1.4.0
v1.4.0-rc3
v1.4.0-rc2
v1.3.3
v1.4.0-rc1
v1.3.2
v1.3.1
v1.3.0
v1.3.0-rc2
v1.3.0-rc1
v1.2.3
v1.2.2
v1.2.1
v1.2.0
v1.2.0-rc3
v1.2.0-rc2
v1.1.4
v1.2.0-rc1
v1.1.3
v1.1.2
v1.1.1
v1.1.0
v1.0.2
v1.0.1
v1.0.0
v0.9.99
Labels
Clear labels
$20
$250
$50
$500
backport/done
💎 Bounty
docs-update-needed
good first issue
hacktoberfest
issue/bounty
issue/confirmed
issue/critical
issue/duplicate
issue/needs-feedback
issue/not-a-bug
issue/regression
issue/stale
issue/workaround
lgtm/need 2
modifies/api
modifies/translation
outdated/backport/v1.18
outdated/theme/markdown
outdated/theme/timetracker
performance/bigrepo
performance/cpu
performance/memory
performance/speed
pr/breaking
proposal/accepted
proposal/rejected
pr/wip
pull-request
reviewed/wontfix
💰 Rewarded
skip-changelog
status/blocked
topic/accessibility
topic/api
topic/authentication
topic/build
topic/code-linting
topic/commit-signing
topic/content-rendering
topic/deployment
topic/distribution
topic/federation
topic/gitea-actions
topic/issues
topic/lfs
topic/mobile
topic/moderation
topic/packages
topic/pr
topic/projects
topic/repo
topic/repo-migration
topic/security
topic/theme
topic/ui
topic/ui-interaction
topic/ux
topic/webhooks
topic/wiki
type/bug
type/deprecation
type/docs
type/enhancement
type/feature
type/miscellaneous
type/proposal
type/question
type/refactoring
type/summary
type/testing
type/upstream
Mirrored from GitHub Pull Request
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/gitea#9126
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @delvh on GitHub (Jun 24, 2022).
What should it be?
Architecture
Plugins are called using(see discussion below, was generally disliked)Gospluginpackage.go-pluginCommunication: Gitea ➡️ plugin ➡️ Gitea
modules/:map[string]?, where possible to avoid breaking changesCommunication: plugin ➡️ Gitea ➡️ plugin
Plugin Lifecycle (What the plugins can set/ "use")
Application is completely initialized and running- HookOR/ANDrelations (depending on the chosen algorithm)?What data is needed by every/ some plugin(s)?
io.gitea.example_plugin)Example Plugin V1)Why this long text rambling?
@42wim commented on GitHub (Jun 24, 2022):
I think https://github.com/hashicorp/go-plugin should also be taking in consideration, afaik the "normal" plugin system has a lot of shortcomings (eg crashing the whole process because of issues with the plugin), that the Hashicorp one does not suffer from.
See also:
@delvh commented on GitHub (Jun 24, 2022):
Yeah, I've also seen their implementation when looking for a plugin system.
However, to me, it appears as if they don't support executing dynamic functions as I think I read the sentence
sending functions is not possibleanywhere, and then I stopped reading and didn't investigate further as that is something we most likely need.After having read through their docs for a little, it seems I was a bit too fast with that.
Regarding the unexpected crashes: I intended to call every plugin by using something like
and thus mitigating the potential for those errors.
So, the question is now, should we use the RPC version which might offer a few benefits and higher latency, or do we stay with the Go native approach that we can completely customize to our liking?
@Gusted commented on GitHub (Jun 24, 2022):
Do you want to compile/execute Go code on-the-fly?
@delvh commented on GitHub (Jun 24, 2022):
Not really, but we certainly need to handle the custom routes which can best be achieved dynamically, and making this interface-based might be possible, but (a little bit) more work.
@Gusted commented on GitHub (Jun 24, 2022):
Wish you many luck with this advanced logic.
@lunny commented on GitHub (Jun 25, 2022):
I prefer the plugin system based on javascript or nodejs because that will allow it include frontend code.
Possbile library be used. https://github.com/dop251/goja, there is also a plugin support nodejs .
@delvh commented on GitHub (Jun 25, 2022):
Interesting how many different views there are regarding this feature.
Now we have three completely different options and no agreement on what to use...
@lunny commented on GitHub (Jun 25, 2022):
Use javascript based plugin system, we can implement a plugin market and one click installation. That's impossible for Go based plugin system.
@delvh commented on GitHub (Jun 25, 2022):
The problem I can see is: We do not even have the same definition of what we want in the end:
What you want seems to be a per-user plugin mechanism, what I thought of was a per-instance plugin mechanism...
@lunny commented on GitHub (Jun 25, 2022):
I don't think so. I think I'm also talking about per-instance plugin. If I made you confusing, I'm sorry.
@jolheiser commented on GitHub (Jun 25, 2022):
-1 for the go
pluginpackage.It can't be removed per compatibility promise, but it is absolutely not stable, and there are far too many caveats to get it working properly.
@lunny commented on GitHub (Jun 25, 2022):
I think we can begin from a theme-kind plugin, which is simple and useful. A plugin could be a zip/tar file with a
main.jsorindex.jsand other files liketheme.sass,theme.cssandimagesand etc.@wxiaoguang commented on GitHub (Jun 25, 2022):
I do not think the Go's
pluginpackage is the future. Is there any success story of using it?Most large Go projects uses gPRC for inter-process commutation, including plugins, but it's also heavy.
@delvh commented on GitHub (Jun 25, 2022):
Ok, seems as if the
pluginpackage is generally disliked, so I'll exclude it from the possible options.I'm still not a fan of a purely frontend-based plugin mechanism as that will have many shortcomings of its own, and I don't know if
should be the deciding factor for how to implement the plugin system...
Server admins should be sure of what they want for their instance, and not install it with a simple misplaced click.
Also, even with the Go-based approach, a plugin "market" would be possible as a third-party tool that simply stores the executables and perhaps some other information about the plugin...
So, as I can see that now, the two possible options are
go-plugin)@luwol03 commented on GitHub (Jun 25, 2022):
Isn't this library lunny suggested meant for a backend-based plugin mechanism? But instead of writing go you can write js? Or would that be to difficult to build a bridge between the Gitea go code and js code?
@lunny commented on GitHub (Jun 25, 2022):
Yes, it could expose structs, methods to frontend. i.e. If we expose getdb method, then we can operate database with javascript.
@lafriks commented on GitHub (Jun 25, 2022):
I think the best way to go would be using grpc so that plugins could be implemented using any language. Plugin could return asset files on init (JavaScript etc) that would need to be injected/used in specific places
@jolheiser commented on GitHub (Jun 27, 2022):
I would also like to throw yaegi into the mix.
I think gRPC is probably the only way to go (unfortunately), but figured yaegi is worth considering as well.
@Mai-Lapyst commented on GitHub (Jun 27, 2022):
Honestly, I would like to see the native go plugin implementation.
Yes it has drawbacks, but it would be fast and admins had full controll over what to use.
But since thats off the table for now, I would rather go with the gRPC approach, since its more open (i.e. you can choose more languages) and imo more secure then javascript.
The problems I see with js plugins is, that it lead to a huge security risk, since js can be so minified or encrypted that you not even need any letters (only parentheses) to write correct js. We then would need an very strict system so no js can accidentally just execute "DROP ALL TABLES;" (or similar) on startup.
Also an interpreter (of any kind) in gitea would bring back the risk of one plugin crashing the whole instance, or to eat up so much performance that gitea stops responding (i.e. a infinite loop in a script somewhere). To mitigate this we then would need to sandbox the plugins into own processes, which would nearly the same as the gRPC approach but with less freedom.
@delvh commented on GitHub (Jun 27, 2022):
To be fair, you can also
DROP ALL TABLES;in Go or consume all available memory.But yeah, I can see your point.
@luwol03 commented on GitHub (Jun 27, 2022):
Then you have to think twice about an official plug-in market like lunny suggested. Official also indicates that they are save for usage and have no malicious intentions. An easy one click install could potentially break servers from not experienced users who don't understand what the plugin is doing and just pressing install.
To prevent this, this would at least requires some reviewing and analysis of newly published plugins, which is time expensive.
@lafriks commented on GitHub (Jun 27, 2022):
We could probably get some ideas on how mattermost have implemented their plugin system.
@jolheiser commented on GitHub (Jun 28, 2022):
For posterity:
mattermost plugin package
It looks like they use go-plugin
@mscherer commented on GitHub (Aug 1, 2022):
Another inspiration could be woodpecker proposal around extensions https://github.com/woodpecker-ci/woodpecker/pull/915
@Trendyne commented on GitHub (Aug 7, 2022):
Since nobody has mentioned it yet, projects like Adobe Lightroom, MPV, or Wireshark use Lua for this. You'd read and run Lua files from a directory where they would register events with callbacks or maybe return properties and functions. It's very light. simple, and fast but would make it very easy to make plugins and shouldn't be any harder to implement
Made up possible example:
@KN4CK3R commented on GitHub (Sep 26, 2022):
The Lua integration could be plugin too which forwards callbacks to Lua.
@Lord-Leonard commented on GitHub (Apr 24, 2024):
Are there any updates on this one? ^^
@lunny commented on GitHub (Apr 25, 2024):
For most backend tasks, Gitea Actions can be considered as somewhat plugins.
@Lord-Leonard commented on GitHub (Apr 25, 2024):
Yeah for my usecase the webhooks are sufficient. I will just have to host another small webserver alongside Gitea.
But it would have been nice to just write a plugin and call it a day :)
@Sharaf5 commented on GitHub (Aug 27, 2024):
Then there are 4 point of views could be considered for plugins
and I will add the 5th
@lunny commented on GitHub (Mar 12, 2025):
Looks like Typescript 7 will be migrated to Go. So that maybe we can use typescript as the plugin language. https://github.com/microsoft/typescript-go
@wxiaoguang commented on GitHub (Mar 12, 2025):
typescript-gois just a TypeScript compiler implemented in Go with a LSP. Where do you see that "use typescript as the plugin"?To be frank:
For the "plugin" proposal, I do not see anyone is really working on it, or whether it is feasible at current stage (my answer is "no": either gPRC or js/wasm/lua would involves a lot of work to design the structs and interfaces, no manpower).
Mission Impossible
So I would suggest to mark the proposal as "close as not planned" since it doesn't seem able to get real progress (reopen at any time when there is a feasible design and manpower)
For some existing requirements:
@wxiaoguang commented on GitHub (Apr 4, 2025):
Quote above: So I would suggest to mark the proposal as "close as not planned" since it doesn't seem able to get real progress (reopen at any time when there is a feasible design and manpower)
Golang eco-system is naturely not easy with plugins .... unfortunately.
@hiifong commented on GitHub (Apr 4, 2025):
Maybe we can learn from git's plugin model, where commands that start with git- can be called freely by git, e.g. I have a git-bug plugin, and I can call my git-bug plugin by calling git bug.
@Sharaf5 commented on GitHub (Apr 5, 2025):
most top named Go/C/C++ projects support plugins including
.sothere were many success stories and a cost effective announce using plugins opening the way to be integrated into other projects
Really, closing it disappointed me, but hope this is in mind for future at least
I wished this project could grow beyond it's limit
hope you best luck
@wxiaoguang commented on GitHub (Apr 5, 2025):
These examples you shown, are either desktop/traffic-server or C++ applications (Golang plugin doesn't work on Windows, but Gitea still needs to support), or the plugin doesn't need to heavily depend on the host application (traffic server: CoreDNS, Traefik). And either they have a large company & team, or a lot of active contributors to maintain.
For Gitea's plugin: Gitea itself is a heavy web application (but not a traffic server), there are more business logic than others, the proposed "Plugin Lifecycle" is already more complex than the traffic server examples. And Gitea community is not that large as others (that's what I meant "my answer is no: either gPRC or js/wasm/lua would involves a lot of work to design the structs and interfaces, no manpower").
Actually it doesn't need a general plugin system, but you see that the webhook related PRs are still stale for long time (WIP: Custom Webhooks #19307). As simple as this one doesn't get success, how would a general plugin proposal succeed?
I don't want to disappoint anyone, but I think we need to face reality.
And see my comment above: reopen at any time when there is a feasible design and manpower
@wxiaoguang commented on GitHub (Apr 5, 2025):
Let's keep it open and don't disappoint anyone. Let's hope there would be some real progresses.
@hiifong commented on GitHub (Apr 5, 2025):
A successful case of a go project: github cli, But this plugin mode only supports command line calls
@wxiaoguang commented on GitHub (Apr 5, 2025):
You need to find some "rich web application" to learn.
@Sharaf5 commented on GitHub (Apr 5, 2025):
I'm mainly a biology teacher and server admin, while I'm tring to learn Go I go slowly so my kwnolage is under just entry level or below ( gpt aided ), so I understand your point here, unfortunatly for now I can only help with ideas but we cant stop building next roadmap steps that it's just somehow far ( you may consider good suggestion for juat undetermined version )
you are right, I previously raised an issue here to enhance Frontend ( https://github.com/go-gitea/gitea/issues/31125 ) and separate it from backend so the backend just work independantly and could be integrated in any frontend - this may make the application focus more on functionality especially if PWA / SPA is considered for frontend as it will reduce SSR ( server side rendering ) and minimize validation to AuthN, AuthZ
yes but may introduce many panels to go for git workflow based deployments ( https://chatgpt.com/share/67f13ee5-3334-8005-82e8-7d087c1cb51b ) integrating gitea and making more developer wanting to contribute and develop more ( separate plugins )
you are thinking well,
I just expressed what in mind "when I said disappointed", as I realy love this project and feal it's mostly the future of git servers
@ProIcons commented on GitHub (Aug 5, 2025):
There are several implementations / architectures of "Plugins".
The most common one (not necessarily in golang) is dynamic library loading, in which, a plugin is compiled against an ABI, and it gets loaded dynamically on runtime from a predefined folder/structure. For that architecture to even exist, it requires a good isolation layer and abstraction layer. Plugins while being able to interact with the main Application, should do so from the exposed APIs to the Plugin, based also on the permissions/scope each plugin can get. It shouldn't be able to modify the database of the core application directly, or any of the behavior of the application directly without accessing this shared controlled layer. This obviously creates complexity. However, with this approach a plugin can do more on the Application, such as declaring its own http api endpoints on the same server, injecting new UI Elements, having its own database entities/state and have a tighter integration with the platform in general.
The one suggested above (as in the first message of the post), resembles more an "Integration" layer, rather than a "Plugin" layer. In this approach there are limitations, which, some of them, can be addressed with "creative workarounds" while some others can't. One of them would probably be, injecting new functionality in the UI, and having API Endpoints to handle the new functionality on the backend. (It could be solved by a third party server, but this would lead to a CORS mess, and this doesn't feel like a plugin system anymore)
An example for a plugin would be "Gitea Pages". What would it require?
While Gitea could serve pages, it doesn't have to. Since we're talking about a plugin after all, the whole project, besides the plugin, can have other executable services, which the plugin can interact with, in the same way Gitea interacts with Action Runners. Some executable services such as
Pages Serverswhich could serve content from a Distributed Storage such as S3, and the plugin to directly store these artifacts (hugo/jekyll compilation units) directly to S3.For this example, which involves many systems and injection points, the dynamic library loading seems a more appropriate solution.
Having said all that, I'm aware of the Complexity of this idea/architecture, since I have already engineered something similar in an Enterprise Product, and it is not something that can be hacked together in a week.
There are a lot, which are written in different languages, which handle dynamic library loading significantly different. I have exposure to mechanisms like these mostly for Languages such as Java and C#.
For C#
These are both Library isolation layers, which can be loaded and unloaded on runtime. There are several .NET Applications that are utilizing them such as
For Java
You can unload a ClassLoader on runtime, which a ServiceLoader is using. There are also libraries that are utilizing these mechanisms such as
Jetbrains' IDEs are all using a Plugin System you can find all their plugins in their repository https://github.com/JetBrains/intellij-plugins
In java there are many closed-source applications that are utilizing a plugin system, which there aren't source examples for them, however they tend to use directly the Language's APIs instead of relying on a 3rd party library such as the aforementioned PF4j library.
For C++
The only exposure I have with dynamic library loading, is modding frameworks for HLDS and SRCDS Servers. The frameworks are AmxmodX and SourceMod. HLDS and SRCDS (Valve's Dedicated Servers for GoldSrc (CS1.6, HL,...) and Source games (CS:S, CS:GO, TF2,...) respectively) are dynamically loading Amxmodx and Sourcemod on startup, and these provide an "Easier" to use abstraction layer of the intrinsics of the Dedicated Servers by loading other plugins either in their own pre-compiled intermediate language, or directly with C++. There are projects on top of them which allows Python and C# to be used for plugins.
Edit:
While researching I found the following go package: https://pkg.go.dev/plugin