Skip to content
Stéphane Brunner edited this page Mar 26, 2024 · 9 revisions

Create

To create a module you should implement the interface github_app_geo_project.module.Module

Then provide it as a ghci.module entry point, if you use Poetry with something like:

[tool.poetry.plugins."ghci.module"]
changelog = "github_app_geo_project.module.changelog:Changelog"

Use

To use it, it should be adder in the application module, in the production.ini file in the key application.<application>.modules

Then some configuration should be added in the application configuration profiles or in the repositories in the configuration file, using the main key as the module entrypoint name.

Module base

from github_app_geo_project.module import Module, ProcessOutput, utils

class MyModule(Module[dict]):

    def title(self) -> str:
       return "My title"

    def description(self) -> str:
       return "My description"

    def documentation_url(self) -> str:
       return "http://example.com/documentation"

    def get_json_schema(self) -> JsonDict:
       """The schema is used to provide a combined schema for the project configuration"""

    def get_github_application_permissions(self) -> GitHubApplicationPermissions:
       """Provids the permissons end events required by the module, this is used to verify that the application has enought right"""

    def get_actions(self, context: GetActionContext) -> list[Action]:
       """This function will "convert" the webhool call and the command line events into a job to fill the queue"""
       actions = []
       old_check = module_utils.DashboardIssue(context.event_data.get("old_data", ""))
       new_check = module_utils.DashboardIssue(context.event_data.get("new_data", ""))
       if not old_check.is_checked("my-check") and new_check.is_checked("my-check"):
           actions.append(module.Action(priority=module.PRIORITY_DASHBOARD, data={"type": "ny-check")

       return actions

    def process(self, context: ProcessContext[T]) -> ProcessOutput | None:
       """This function will process the job"""
       issue_check = module_utils.DashboardIssue(context.issue_data)
       issue_check.add_check("my-check", "My description", False)

       if context.module_data["type"] == "my-check":
           ...
           issue_check.set_check("my-check", False)

       return module.ProcessOutput(dashboard=issue_check.get_output())

    def cleanup(self, context: CleanupContext) -> None:
       """Optional, called if the module is disable by configuration"""

Working with issue dashboard

The module can interact with its own part of the dashboard, for that, you should write something like:

from github_app_geo_project.module import Module, ProcessOutput, utils

class MyModule(Module[dict]):
    def required_issue_dashboard(self) -> bool:
       return True

    def get_actions(self, context: GetActionContext) -> list[Action]:
       """This function will "convert" the webhool call and the command line events into a job to fill the queue"""
       # TODO
       return [...]

    def process(self, context: ProcessContext[dict]) -> ProcessOutput | None:
       dashboard = utils.DashboardIssue(context.issue_data)
       todo = dashboard.is_checked('<name>')
       if todo:
          ...
          dashboard.set_check('<name>', False)
          return dashboard.to_string()
       return None

In this example, we use the object DashboardIssue to parse and format the issue data, but this can be done as you want.

Transversal dashboard

A module can create a transversal dashboard accessible to admin users.

Example of module:

from github_app_geo_project.module import Module, ProcessOutput, utils

class MyModule(Module[dict]):
    def process(self, context: ProcessContext[dict]) -> ProcessOutput | None:
       trasversal_status = context.trasversal_status
       trasversal_status['toto'] = 'titi'
       return ProcessOutput(trasversal_status=trasversal_status)

    def has_transversal_dashboard(self) -> bool:
        """Return True if the module has a transversal dashboard."""
        return True

    def get_transversal_dashboard(self, context: TransversalDashboardContext) -> TransversalDashboardOutput:
        """Get the transversal dashboard content."""
        return TransversalDashboardOutput(
            renderer="github_app_geo_project:module/tests/dashboard.html",
            data={
                # Content with HTML tag to see if they are escaped
                "content": context.trasversal_status,
            },)