forked from lix-project/hydra
c737bed42f
Bring the manual in line with the configuration documentation
406 lines
15 KiB
Markdown
406 lines
15 KiB
Markdown
Creating and Managing Projects
|
||
==============================
|
||
|
||
Once Hydra is installed and running, the next step is to add projects to
|
||
the build farm. We follow the example of the [Patchelf
|
||
project](http://nixos.org/patchelf.html), a software tool written in C
|
||
and using the GNU Build System (GNU Autoconf and GNU Automake).
|
||
|
||
Log in to the web interface of your Hydra installation using the user
|
||
name and password you inserted in the database (by default, Hydra\'s web
|
||
server listens on [`localhost:3000`](http://localhost:3000/)). Then
|
||
follow the \"Create Project\" link to create a new project.
|
||
|
||
Project Information
|
||
-------------------
|
||
|
||
A project definition consists of some general information and a set of
|
||
job sets. The general information identifies a project, its owner, and
|
||
current state of activity. Here\'s what we fill in for the patchelf
|
||
project:
|
||
|
||
Identifier: patchelf
|
||
|
||
The *identifier* is the identity of the project. It is used in URLs and
|
||
in the names of build results.
|
||
|
||
The identifier should be a unique name (it is the primary database key
|
||
for the project table in the database). If you try to create a project
|
||
with an already existing identifier you\'d get an error message from the
|
||
database. So try to create the project after entering just the general
|
||
information to figure out if you have chosen a unique name. Job sets can
|
||
be added once the project has been created.
|
||
|
||
Display name: Patchelf
|
||
|
||
The *display name* is used in menus.
|
||
|
||
Description: A tool for modifying ELF binaries
|
||
|
||
The *description* is used as short documentation of the nature of the
|
||
project.
|
||
|
||
Owner: eelco
|
||
|
||
The *owner* of a project can create and edit job sets.
|
||
|
||
Enabled: Yes
|
||
|
||
Only if the project is *enabled* are builds performed.
|
||
|
||
Once created there should be an entry for the project in the sidebar. Go
|
||
to the project page for the
|
||
[Patchelf](http://localhost:3000/project/patchelf) project.
|
||
|
||
Job Sets
|
||
--------
|
||
|
||
A project can consist of multiple *job sets* (hereafter *jobsets*),
|
||
separate tasks that can be built separately, but may depend on each
|
||
other (without cyclic dependencies, of course). Go to the
|
||
[Edit](http://localhost:3000/project/patchelf/edit) page of the Patchelf
|
||
project and \"Add a new jobset\" by providing the following
|
||
\"Information\":
|
||
|
||
Identifier: trunk
|
||
Description: Trunk
|
||
Nix expression: release.nix in input patchelfSrc
|
||
|
||
This states that in order to build the `trunk` jobset, the Nix
|
||
expression in the file `release.nix`, which can be obtained from input
|
||
`patchelfSrc`, should be evaluated. (We\'ll have a look at `release.nix`
|
||
later.)
|
||
|
||
To realize a job we probably need a number of inputs, which can be
|
||
declared in the table below. As many inputs as required can be added.
|
||
For patchelf we declare the following inputs.
|
||
|
||
patchelfSrc
|
||
'Git checkout' https://github.com/NixOS/patchelf
|
||
|
||
nixpkgs 'Git checkout' https://github.com/NixOS/nixpkgs
|
||
|
||
officialRelease Boolean false
|
||
|
||
system String value "i686-linux"
|
||
|
||
Building Jobs
|
||
-------------
|
||
|
||
Build Recipes
|
||
-------------
|
||
|
||
Build jobs and *build recipes* for a jobset are specified in a text file
|
||
written in the [Nix language](http://nixos.org/nix/). The recipe is
|
||
actually called a *Nix expression* in Nix parlance. By convention this
|
||
file is often called `release.nix`.
|
||
|
||
The `release.nix` file is typically kept under version control, and the
|
||
repository that contains it one of the build inputs of the
|
||
corresponding--often called `hydraConfig` by convention. The repository
|
||
for that file and the actual file name are specified on the web
|
||
interface of Hydra under the `Setup` tab of the jobset\'s overview page,
|
||
under the `Nix
|
||
expression` heading. See, for example, the [jobset overview
|
||
page](http://hydra.nixos.org/jobset/patchelf/trunk) of the PatchELF
|
||
project, and [the corresponding Nix
|
||
file](https://github.com/NixOS/patchelf/blob/master/release.nix).
|
||
|
||
Knowledge of the Nix language is recommended, but the example below
|
||
should already give a good idea of how it works:
|
||
|
||
let
|
||
pkgs = import <nixpkgs> {}; ①
|
||
|
||
jobs = rec { ②
|
||
|
||
tarball = ③
|
||
pkgs.releaseTools.sourceTarball { ④
|
||
name = "hello-tarball";
|
||
src = <hello>; ⑤
|
||
buildInputs = (with pkgs; [ gettext texLive texinfo ]);
|
||
};
|
||
|
||
build = ⑥
|
||
{ system ? builtins.currentSystem }: ⑦
|
||
|
||
let pkgs = import <nixpkgs> { inherit system; }; in
|
||
pkgs.releaseTools.nixBuild { ⑧
|
||
name = "hello";
|
||
src = jobs.tarball;
|
||
configureFlags = [ "--disable-silent-rules" ];
|
||
};
|
||
};
|
||
in
|
||
jobs ⑨
|
||
|
||
|
||
This file shows what a `release.nix` file for
|
||
[GNU Hello](http://www.gnu.org/software/hello/) would look like.
|
||
GNU Hello is representative of many GNU and non-GNU free software
|
||
projects:
|
||
|
||
- it uses the GNU Build System, namely GNU Autoconf, and GNU Automake;
|
||
for users, it means it can be installed using the
|
||
usual
|
||
./configure && make install
|
||
procedure
|
||
;
|
||
- it uses Gettext for internationalization;
|
||
- it has a Texinfo manual, which can be rendered as PDF with TeX.
|
||
|
||
The file defines a jobset consisting of two jobs: `tarball`, and
|
||
`build`. It contains the following elements (referenced from the figure
|
||
by numbers):
|
||
|
||
1. This defines a variable `pkgs` holding the set of packages provided
|
||
by [Nixpkgs](http://nixos.org/nixpkgs/).
|
||
|
||
Since `nixpkgs` appears in angle brackets, there must be a build
|
||
input of that name in the Nix search path. In this case, the web
|
||
interface should show a `nixpkgs` build input, which is a checkout
|
||
of the Nixpkgs source code repository; Hydra then adds this and
|
||
other build inputs to the Nix search path when evaluating
|
||
`release.nix`.
|
||
|
||
2. This defines a variable holding the two Hydra jobs--an *attribute
|
||
set* in Nix.
|
||
|
||
3. This is the definition of the first job, named `tarball`. The
|
||
purpose of this job is to produce a usable source code tarball.
|
||
|
||
4. The `tarball` job calls the `sourceTarball` function, which
|
||
(roughly) runs `autoreconf && ./configure &&
|
||
make dist` on the checkout. The `buildInputs` attribute
|
||
specifies additional software dependencies for the job.
|
||
|
||
> The package names used in `buildInputs`--e.g., `texLive`--are the
|
||
> names of the *attributes* corresponding to these packages in
|
||
> Nixpkgs, specifically in the
|
||
> [`all-packages.nix`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/all-packages.nix)
|
||
> file. See the section entitled "Package Naming" in the Nixpkgs
|
||
> manual for more information.
|
||
|
||
5. The `tarball` jobs expects a `hello` build input to be available in
|
||
the Nix search path. Again, this input is passed by Hydra and is
|
||
meant to be a checkout of GNU Hello\'s source code repository.
|
||
|
||
6. This is the definition of the `build` job, whose purpose is to build
|
||
Hello from the tarball produced above.
|
||
|
||
7. The `build` function takes one parameter, `system`, which should be
|
||
a string defining the Nix system type--e.g., `"x86_64-linux"`.
|
||
Additionally, it refers to `jobs.tarball`, seen above.
|
||
|
||
Hydra inspects the formal argument list of the function (here, the
|
||
`system` argument) and passes it the corresponding parameter
|
||
specified as a build input on Hydra\'s web interface. Here, `system`
|
||
is passed by Hydra when it calls `build`. Thus, it must be defined
|
||
as a build input of type string in Hydra, which could take one of
|
||
several values.
|
||
|
||
The question mark after `system` defines the default value for this
|
||
argument, and is only useful when debugging locally.
|
||
|
||
8. The `build` job calls the `nixBuild` function, which unpacks the
|
||
tarball, then runs `./configure && make
|
||
&& make check && make install`.
|
||
|
||
9. Finally, the set of jobs is returned to Hydra, as a Nix attribute
|
||
set.
|
||
|
||
Building from the Command Line
|
||
------------------------------
|
||
|
||
It is often useful to test a build recipe, for instance before it is
|
||
actually used by Hydra, when testing changes, or when debugging a build
|
||
issue. Since build recipes for Hydra jobsets are just plain Nix
|
||
expressions, they can be evaluated using the standard Nix tools.
|
||
|
||
To evaluate the `tarball` jobset of the above example, just
|
||
run:
|
||
|
||
```console
|
||
$ nix-build release.nix -A tarball
|
||
```
|
||
|
||
However, doing this with the example as is will probably
|
||
yield an error like this:
|
||
|
||
error: user-thrown exception: file `hello' was not found in the Nix search path (add it using $NIX_PATH or -I)
|
||
|
||
The error is self-explanatory. Assuming `$HOME/src/hello` points to a
|
||
checkout of Hello, this can be fixed this way:
|
||
|
||
```console
|
||
$ nix-build -I ~/src release.nix -A tarball
|
||
```
|
||
|
||
Similarly, the `build` jobset can be evaluated:
|
||
|
||
```console
|
||
$ nix-build -I ~/src release.nix -A build
|
||
```
|
||
|
||
The `build` job reuses the result of the `tarball` job, rebuilding it
|
||
only if it needs to.
|
||
|
||
Adding More Jobs
|
||
----------------
|
||
|
||
The example illustrates how to write the most basic
|
||
jobs, `tarball` and `build`. In practice, much more can be done by using
|
||
features readily provided by Nixpkgs or by creating new jobs as
|
||
customizations of existing jobs.
|
||
|
||
For instance, test coverage report for projects compiled with GCC can be
|
||
automatically generated using the `coverageAnalysis` function provided
|
||
by Nixpkgs instead of `nixBuild`. Back to our GNU Hello example, we can
|
||
define a `coverage` job that produces an HTML code coverage report
|
||
directly readable from the corresponding Hydra build page:
|
||
|
||
coverage =
|
||
{ system ? builtins.currentSystem }:
|
||
|
||
let pkgs = import nixpkgs { inherit system; }; in
|
||
pkgs.releaseTools.coverageAnalysis {
|
||
name = "hello";
|
||
src = jobs.tarball;
|
||
configureFlags = [ "--disable-silent-rules" ];
|
||
};
|
||
|
||
As can be seen, the only difference compared to `build` is the use of
|
||
`coverageAnalysis`.
|
||
|
||
Nixpkgs provides many more build tools, including the ability to run
|
||
build in virtual machines, which can themselves run another GNU/Linux
|
||
distribution, which allows for the creation of packages for these
|
||
distributions. Please see [the `pkgs/build-support/release`
|
||
directory](https://github.com/NixOS/nixpkgs/tree/master/pkgs/build-support/release)
|
||
of Nixpkgs for more. The NixOS manual also contains information about
|
||
whole-system testing in virtual machine.
|
||
|
||
Now, assume we want to build Hello with an old version of GCC, and with
|
||
different `configure` flags. A new `build_exotic` job can be written
|
||
that simply *overrides* the relevant arguments passed to `nixBuild`:
|
||
|
||
build_exotic =
|
||
{ system ? builtins.currentSystem }:
|
||
|
||
let
|
||
pkgs = import nixpkgs { inherit system; };
|
||
build = jobs.build { inherit system; };
|
||
in
|
||
pkgs.lib.overrideDerivation build (attrs: {
|
||
buildInputs = [ pkgs.gcc33 ];
|
||
preConfigure = "gcc --version";
|
||
configureFlags =
|
||
attrs.configureFlags ++ [ "--disable-nls" ];
|
||
});
|
||
|
||
The `build_exotic` job reuses `build` and overrides some of its
|
||
arguments: it adds a dependency on GCC 3.3, a pre-configure phase that
|
||
runs `gcc --version`, and adds the `--disable-nls` configure flags.
|
||
|
||
This customization mechanism is very powerful. For instance, it can be
|
||
used to change the way Hello and *all* its dependencies--including the C
|
||
library and compiler used to build it--are built. See the Nixpkgs manual
|
||
for more.
|
||
|
||
Declarative Projects
|
||
--------------------
|
||
|
||
see this [chapter](./plugins/declarative-projects.md)
|
||
|
||
Email Notifications
|
||
-------------------
|
||
|
||
Hydra can send email notifications when the status of a build changes.
|
||
This provides immediate feedback to maintainers or committers when a
|
||
change causes build failures.
|
||
|
||
The feature can be turned on by adding the following line to `hydra.conf`
|
||
|
||
``` conf
|
||
email_notification = 1
|
||
```
|
||
|
||
By default, Hydra only sends email notifications if a previously successful
|
||
build starts to fail. In order to force Hydra to send an email for each build
|
||
(including e.g. successful or cancelled ones), the environment variable
|
||
`HYDRA_FORCE_SEND_MAIL` can be declared:
|
||
|
||
``` nix
|
||
services.hydra-dev.extraEnv.HYDRA_FORCE_SEND_MAIL = "1";
|
||
```
|
||
|
||
SASL Authentication for the email address that's used to send notifications
|
||
can be configured like this:
|
||
|
||
``` conf
|
||
EMAIL_SENDER_TRANSPORT_sasl_username=hydra@example.org
|
||
EMAIL_SENDER_TRANSPORT_sasl_password=verysecret
|
||
EMAIL_SENDER_TRANSPORT_port=587
|
||
EMAIL_SENDER_TRANSPORT_ssl=starttls
|
||
```
|
||
|
||
Further information about these environment variables can be found at the
|
||
[MetaCPAN documentation of `Email::Sender::Manual::QuickStart`](https://metacpan.org/pod/Email::Sender::Manual::QuickStart#specifying-transport-in-the-environment).
|
||
|
||
It's recommended to not put this in `services.hydra-dev.extraEnv` as this would
|
||
leak the secrets into the Nix store. Instead, it should be written into an
|
||
environment file and configured like this:
|
||
|
||
``` nix
|
||
{ systemd.services.hydra-notify = {
|
||
serviceConfig.EnvironmentFile = "/etc/secrets/hydra-mail-cfg";
|
||
};
|
||
}
|
||
```
|
||
|
||
The simplest approach to enable Email Notifications is to use the ssmtp
|
||
package, which simply hands off the emails to another SMTP server. For
|
||
details on how to configure ssmtp, see the documentation for the
|
||
`networking.defaultMailServer` option. To use ssmtp for the Hydra email
|
||
notifications, add it to the path option of the Hydra services in your
|
||
`/etc/nixos/configuration.nix` file:
|
||
|
||
systemd.services.hydra-queue-runner.path = [ pkgs.ssmtp ];
|
||
systemd.services.hydra-server.path = [ pkgs.ssmtp ];
|
||
|
||
Gitea Integration
|
||
-----------------
|
||
|
||
Hydra can notify Git servers (such as [GitLab](https://gitlab.com/), [GitHub](https://github.com)
|
||
or [Gitea](https://gitea.io/en-us/)) about the result of a build from a Git checkout.
|
||
|
||
This section describes how it can be implemented for `gitea`, but the approach for `gitlab` is
|
||
analogous:
|
||
|
||
* [Obtain an API token for your user](https://docs.gitea.io/en-us/api-usage/#authentication)
|
||
* Add it to a file which only users in the hydra group can read like this: see [including files](configuration.md#including-files) for more information
|
||
```
|
||
<gitea_authorization>
|
||
your_username=your_token
|
||
</gitea_authorization>
|
||
```
|
||
|
||
* Include the file in your `hydra.conf` like this:
|
||
``` nix
|
||
{
|
||
services.hydra-dev.extraConfig = ''
|
||
Include /path/to/secret/file
|
||
'';
|
||
}
|
||
```
|
||
|
||
* For a jobset with a `Git`-input which points to a `gitea`-instance, add the following
|
||
additional inputs:
|
||
|
||
| Type | Name | Value |
|
||
| -------------- | ------------------- | ---------------------------------- |
|
||
| `String value` | `gitea_repo_name` | *Name of the repository to build* |
|
||
| `String value` | `gitea_repo_owner` | *Owner of the repository* |
|
||
| `String value` | `gitea_status_repo` | *Name of the `Git checkout` input* |
|
||
| `String value` | `gitea_http_url` | *Public URL of `gitea`*, optional |
|
||
|