Skip to content

Plugin Mechanism #20126

Open
Open
@delvh

Description

@delvh

What should it be?

  • it should allow adding additional functionality to Gitea without bloating the main binary or being responsible for maintaining it
  • it should not allow to modify the core functionality of Gitea

Architecture

  • Plugins are called using Gos plugin package. (see discussion below, was generally disliked)
  • Plugins are called over RCP using the go-plugin package.
  • Reasons:
    • active community to maintain the package
    • works on every platform and even across languages
    • minimalistic and understandable -> no technical debt to have to consider
    • OS is responsible for setting plugin resource limits, not Gitea
    • Protocol versioning built-in
  • Reasons against that architecture:
    • requests over RCP make everything slow
    • extra dependency
    • vendor lock-in for plugins to go-plugin

Communication: Gitea ➡️ plugin ➡️ Gitea

  • common data structures and methods needed
  • recommendation: an extra package that both Gitea and the plugins use
    • during application startup, Gitea should use the package from the receiver side and the plugins from the sender side
    • while dispatching calls to the plugins, the roles should be switched around so that Gitea becomes the sender and the plugins the receivers
  • things that plugins, as well as Gitea, should have access to (at best only as a wrapper that is set once at runtime because the underlying implementation can change quite often):
    • especially things located in modules/:
    • logger
    • context
    • i18n
  • again, to avoid vendor lock-in, this package cannot depend on anything that it doesn't define on its own, or is provided by Go itself
  • to reduce the chance of plugins breaking with a new Gitea release, this extra package should be developed to be "all-inclusive" from the beginning meaning that it entails everything a plugin might wish to configure
    • it is recommended that the extra package uses easily extendable data structures, i.e. map[string]?, where possible to avoid breaking changes

Communication: plugin ➡️ Gitea ➡️ plugin

  • Let Plugins use the Gitea API when requesting additional information from Gitea. Reasons:
    • easy to implement (literally NO work at all 😃 )
    • easy to maintain (again, because there is literally NO code to maintain 😃 )
    • safe to use for the plugins because the API guarantees stability
    • API gets used more, hence more people want to see it well-maintained and there is an actual incentive to add an API for a feature that at that moment only exists for the web UI
  • Reasons against this approach:
    • slow, because it will always require HTTP requests
    • plugins need to parse the answer instead of simply being able to use a predefined method/ datatype

Plugin Lifecycle (What the plugins can set/ "use")

  • Plugin Initialization
  • Application is completely initialized and running - Hook
  • Plugin Dependencies (to Gitea (versions), to other plugins?)
  • Setting Plugin-wide settings as well while parsing the server-wide settings (requires (a) section(s) reserved for plugins)
  • Custom translation keys to allow for localized new features
  • Adding custom tabs to different units:
    • most basic:
    • user
    • org
    • user+org
    • all repos
    • public repo
    • private repo
    • additionally possible:
    • issue
    • PR
    • projects
    • packages
    • ...
    • to make parsing this easier, it would probably be good to use an approach that allows setting a list of tags where this tab will be shown. Problem: How to handle OR/ AND relations (depending on the chosen algorithm)?
  • Adding consistency checks
  • Cron Job Hooks?
  • Shutdown Hook

What data is needed by every/ some plugin(s)?

  • unique plugin name (i.e. by following reverse naming such as io.gitea.example_plugin)
  • human printable plugin name (i.e. Example Plugin V1)
  • plugin version in semver form
  • list of core units affected by this plugin (rather as a code of honor the plugin intends to keep than a security feature)
  • dependencies to other plugins
  • custom translations/ translation files
  • custom settings/ setting files
  • custom web routes
  • custom API routes (problem: how to update the swagger file with the new operations?)
  • provided hooks
  • minimum Gitea version the plugin needs

Why this long text rambling?

  1. Everyone should know without a doubt how it should look like in the end
  2. To make the work for the (eventual) reviewers easier by simply letting them cross-check the actual functionality with its intention
  3. Most of the text I wrote here can be copy-pasted into the docs, making it easier for me to write the docs
  4. To allow for discussion if I missed something while planning this feature
  5. To see if the scope others expect from this feature differs from what I imagine from it

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/featureCompletely new functionality. Can only be merged if feature freeze is not active.type/proposalThe new feature has not been accepted yet but needs to be discussed first.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions