You wish to add a new feature in the YunoHost core, but don't know how to proceed? This guide takes you through the various steps of the development and contribution process.
If you're looking for stuff to implement or fix, the bug-tracker is here!
Come say hi to us in the dev chat room!
Use ynh-dev (see the README) to setup a development environment - locally in a virtual machine, or on a VPS. This will setup a working YunoHost instance, using directly the Git repositories (with symlinks). That way, you will be able to edit files, test your changes in real time, commit stuff and push/pull directly from your development environment.
Implement and test your feature. Depending on what you want to develop, you will want to:
/ynh-dev/yunohost/
/ynh-dev/yunohost-admin/
It is a small "homemade" framework. Its major role is to allow us to build both a web API and a command-line API from the same Python code thanks to a YAML schema which we call the actionmap.
It handles other mechanisms like authentication, internationalization and small technical utilitary functions (e.g. reading/writing JSON).
Moulinette has its own documentation available here.
This piece is the very core of YunoHost. It contains:
This is the single sign-on system of YunoHost. It both contains:
SSOwat is configured through /etc/ssowat/conf.json
which is generated by YunoHost.
It is an optional dependency of YunoHost and corresponds to an interface for the web API created by YunoHost and Moulinette (c.f. the yunohost-api
service).
It essentially contains:
Work in /ynh-dev/yunohost/
.
Run cd /ynh_dev/ && ./ynh-dev use-git yunohost
.
The actionsmap file (data/actionsmap/yunohost.yml
) defines the various
categories, actions and arguments of the YunoHost CLI. Define how you want
users to use your feature, and add/edit the corresponding categories, actions
and arguments. For example in yunohost domain add some.domain.tld
, the
category is domain
, the action is add
, and some.domain.tld
is an
argument.
Moulinette will automatically map commands in the actionsmap to Python
functions (and their arguments) located in src/yunohost/
. For example, typing
yunohost domain add some.domain.tld
will call the function
domain_add(domainName)
in domain.py
, with the argument domainName
equal
to "some.domain.tld"
.
To handle exceptions, you should raise some YunohostError()
To help with internationalizing the messages, use m18n.n('some-message-id')
and put your string in locales/en.json
. You can also put arguments and use
them in the string with {{some-argument:s}}
. Don't edit other locales files,
this will be done using weblate !
YunoHost tries to follow the pep8 coding style. Tools exist to automatically check conformity.
Name of "private" functions should start with a _
Work in /ynh-dev/yunohost-admin/src/
.
Run cd /ynh-dev && ./ynh-dev use-git yunohost-admin
. It launches gulp, such as each
time you modify sources, it recompiles the code and you can use it by
refreshing (Ctrl+F5) your web administration. To stop the command, just do Ctrl+C.
The web interface uses the API to interact with YunoHost. The API
commands/requests are also defined via the actionsmap. For instance, accessing
the page https://domain.tld/yunohost/api/users
corresponds to a GET /users
requests on the YunoHost API. It is mapped to the function
user_list()
. Accessing the URL should display the JSON returned by this
function. 'GET' requests are typically meant to ask information to the server.
'POST' requests are meant to ask the server to edit/change some information,
or to execute some actions.
js/yunohost/controllers
contains the JavaScript parts,
and define which requests to make to the API when loading a specific page of
the interface, and how to process the data to generate the page, using
templates.
views
contains the various templates for the pages of the interface. In the
template, data coming from the JavaScript part can be used with the syntax
{{some-variable}}
, which will be replaced when building/accessing the page.
It is also possible to have conditions using the
handlebars.js syntax: {{#if some-variable}}<p>Some conditional HTML code here !</p>{{/if}}
For internationalized strings, use y18n.t('some-string-code')
in the
JavaScript, or {{t 'some-string-code'}}
in the HTML template, and put your
string in locales/en.json
. Don't edit other locales files,
this will be done using Weblate!
Each time you edit the actionsmap or the Python code, you should restart the YunoHost api:
systemctl restart yunohost-api
(You'll need to retype your admin and password in the web interface)
You might need to force-clear the cache of your browser sometimes to refresh
the JavaScript and/or HTML (so each time you edit something in js
or views
).
Fork the relevant repo on GitHub, and commit stuff to a new branch. We recommend to name the branch with the following convention:
enh-ISSUENUMBER-name-of-feature
fix-ISSUENUMBER-description-of-fix
ISSUENUMBER
is optional and is the id of a corresponding ticket on the bug tracker.Once you're ready, open a Pull Request (PR) on GitHub. Please include [fix]
or
[enh]
at the beginning of the title of your PR.
After reviewing, testing and validation by other contributors, your branch
should be merged in unstable
!
Found errors? Think you can improve this documentation? Simply click the Edit link at the top of the page, and then the icon on Github to suggest changes.
Powered by Grav + with by Trilby Media. • Terms of Service