python-semantic-release icon indicating copy to clipboard operation
python-semantic-release copied to clipboard

Plugin Based Releases

Open esatterwhite opened this issue 4 years ago • 6 comments

Description

The reference javascript implementation, is almost entirely plugin driven leaving the core library to be effectively a general harness that manages the execution of a plugin list and configuration passing.

Use cases

It would be nice to define a release process as a set of plugins, this also paves the way for shareable configurations and community driven functionality not directly supported by this project.

It would off load a good amount of complexity from the core library and allow people external to the project to implement new functionality and override existing behavior

Possible implementation

[tool.semantic-release]
extends = 'release-config-special'
plugins = [
  ['<plugin-name>', {
    option1 = true,
    option2 = 'a-value'
    option3 = 100
  }]
]

A plugin name is a reference to a python module.

#  plugin-name/__init__.py

def verify_conditions(*agrs, **kwargs):
  pass

def analyze_commits(*args, **kwargs):
  pass

def verify_release(*args, **kwargs):
  pass

def generate_notes(*args, **kwargs):
  pass

def prepare(*args, **kwargs):
  pass

def publish(*args, **kwargs):
  pass

def add_channel(*args, **kwargs):
  pass

def success(*args, **kwargs):
  pass

def fail(*args, **kwargs):
  pass

A plugin could also be a class or even a simple callbale, however, I think the expectation of a module that exports simple toplevel functions the easiest and most flexible thing

[tool.semantic-release]
extends = 'release-config-special'
plugins = [
  ['<plugin-name>', {
    option1 = true,
    option2 = 'a-value'
    option3 = 100
  }]
]
# plugin-name/__init__.py
from semantic_release import Plugin
__PLUGIN_NAME__ = 'PluginName'


class PluginName(Plugin):

  def __init__(*args, **kwargs):
    super().__init__(*args, **kwargs)

  def verify_conditions(*agrs, **kwargs):
    pass

  def analyze_commits(*args, **kwargs):
    pass

  def verify_release(*args, **kwargs):
    pass

  def generateNotes(*args, **kwargs):
    pass

  def prepare(*args, **kwargs):
    pass

  def publish(*args, **kwargs):
    pass

  def add_channel(*args, **kwargs):
    pass

  def success(*args, **kwargs):
    pass

  def fail(*args, **kwargs):
    pass

esatterwhite avatar Feb 11 '21 14:02 esatterwhite

I would prefer to use an abstract base class rather than exporting toplevel functions:

  • Plugins can inherit functionality from each other
  • Multiple plugins could be defined in a single module
  • __init__ could be used to load any plugin configuration before starting the release process

danth avatar Feb 11 '21 15:02 danth

I can get behind that.

esatterwhite avatar Feb 11 '21 15:02 esatterwhite

One downside of the plugin class is that means all plugins would have a hard dependency on this package. If one wanted to publish a plugin, it shouldn't need semantic_release as a dependency to be a plugin.

unless it were its own package.

esatterwhite avatar Feb 12 '21 00:02 esatterwhite

This feature request has been labelled as help wanted since there has been no activity in the last 3 weeks. It will not be closed.

github-actions[bot] avatar Mar 05 '21 00:03 github-actions[bot]

This feature request has been labelled as help wanted since there has been no activity in the last 3 weeks. It will not be closed.

github-actions[bot] avatar Nov 15 '22 01:11 github-actions[bot]

The solution could be implementation using Protocol - the plugin itself doesn't need to know about the protocol (no dependency), just need to implement its methods - this will fulfill the requirements.

https://www.pythontutorial.net/python-oop/python-protocol/

MichalVasut avatar Apr 28 '23 16:04 MichalVasut