Pmbootstrap CI

Continuous Integration (CI) scripts run whenever sending a patch into one of the source trees of postmarketOS. These run various tests, to make sure that new patches don't introduce new bugs and to do various style checks (linting) so the code looks consistent. The command  can be used to run the same CI scripts locally. If they fail, you can fix your patch and run them again - and once they pass you can be confident that they will also pass after you submitted them.

Usage
Change to the directory of the git repository of which you would like to run the CI scripts. Then run  for an interactive selection of which scripts to run.

It is also possible to directly start one or more scripts without the interactive prompt. Just add the name of the scripts you want to run at the end, for example:

See  for the full usage instructions.

Example CI script
Here is a minimal example for checking all shell scripts in the git repository with shellcheck.

Create the following file as :

Make it executable:

If the git repository is on SourceHut, put the following in :

If the git repository is on GitLab, put the following in :

CI script
The CI scripts need to have a specific format, so  can use them. They must be named  in the root of the git repository.

The scripts must follow the following template:

Metadata
The comments on the top hold some metadata:
 * this is what gets displayed in the interactive prompt
 * a list of options to configure how pmbootstrap should handle this script. Omit this if no options are used.
 * : this script should run natively instead of running it inside a pmbootstrap chroot. This makes sense when the CI script needs to run pmbootstrap itself, as pmbootstrap can't run inside pmbootstrap. Note that the block that usually installs dependencies will get skipped when running this with, so add checks for all dependencies before starting the tests and give the user a helpful message if something is missing. See   in   as example.
 * : this script takes significant time to execute. Usually there are a few linter scripts that run rather fast, and a testsuite that takes longer. pmbootstrap will run scripts with the  option at the end.
 * : link to this wiki page, and a marker so  knows that it may use this script

Installing dependencies
The block at  is for installing dependencies with apk.


 * Add  at the beginning, so the   and   commands are printed to the terminal, it's useful to know what packages are installed and when the other block is entered. The output is well readable with these two commands printed.
 * At the end of the block, execute the CI script again but as testuser. The install dependencies block will get skipped then.
 * When running on a CI server (e.g. SourceHut, GitLab), this block will run as root inside an Alpine edge container (even if the script has  set).
 * When running with, this block will run as root user inside the pmbootstrap chroot. It has an apk cache set up (as always when using pmbootstrap's chroot). When this script has the   option set,   just skips this block and runs the part below it.
 * Make sure everything that is needed to run the CI script is packaged in Alpine, consider packaging it yourself otherwise.

Running the test

 * CI scripts runs with the git repository as working dir.
 * Everything after the "Installing dependencies" block runs as testuser. "pmos" in case of pmbootstrap, or whatever the CI server uses.
 * Make sure that its output is well readable, therefore it might be better to not use  and instead   some messages about what it is doing

SourceHut config
For SourceHut, a build manifest needs to be written, typically into a  file in the root of the git repository. See the example above.

This file just calls the CI scripts inside an alpine image. It uses sudo to elevate rights to root, so we can install dependencies at the beginning of the CI scripts (and do it only there, not repeat it in the manifest).

In theory it would be nice to use doas instead of sudo, but as of writing that didn't work out of the box.

GitLab config
For GitLab, a .gitlab-ci.yml file needs to be written. See the example above.