<section xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xml:id="sec-declarative-projects">

<title>Declarative projects</title>

<para>
  Hydra supports declaratively configuring a project's jobsets. This
  configuration can be done statically, or generated by a build job.
</para>

<note><para>
  Hydra will treat the project's declarative input as a static definition
  if and only if the spec file contains a dictionary of dictionaries.
  If the value of any key in the spec is not a dictionary, it will
  treat the spec as a generated declarative spec.
</para></note>

<section xml:id="sec-static-declarative-projects">

  <title>Static, Declarative Projects</title>
  <para>
    Hydra supports declarative projects, where jobsets are configured
    from a static JSON document in a repository.
  </para>

  <para>
    To configure a static declarative project, take the following steps:
  </para>
  <orderedlist numeration="arabic" spacing="compact">
    <listitem>
      <para>
        Create a Hydra-fetchable source like a Git repository or local path.
      </para>
    </listitem>
    <listitem>
      <para>
        In that source, create a file called <filename>spec.json</filename>,
        and add the specification for all of the jobsets. Each key is jobset
        and each value is a jobset's specification. For example:

        <programlisting language="json">
{
  "nixpkgs": {
    "enabled": 1,
    "hidden": false,
    "description": "Nixpkgs",
    "nixexprinput": "nixpkgs",
    "nixexprpath": "pkgs/top-level/release.nix",
    "checkinterval": 300,
    "schedulingshares": 100,
    "enableemail": false,
    "emailoverride": "",
    "keepnr": 3,
    "inputs": {
      "nixpkgs": {
          "type": "git",
          "value": "git://github.com/NixOS/nixpkgs.git master",
          "emailresponsible": false
      }
    }
  },
  "nixos": {
    "enabled": 1,
    "hidden": false,
    "description": "NixOS: Small Evaluation",
    "nixexprinput": "nixpkgs",
    "nixexprpath": "nixos/release-small.nix",
    "checkinterval": 300,
    "schedulingshares": 100,
    "enableemail": false,
    "emailoverride": "",
    "keepnr": 3,
    "inputs": {
      "nixpkgs": {
        "type": "git",
        "value": "git://github.com/NixOS/nixpkgs.git master",
        "emailresponsible": false
      }
    }
  }
}
</programlisting>
      </para>
    </listitem>
    <listitem>
      <para>
        Create a new project, and set the project's declarative input type,
        declarative input value, and declarative spec file to point to the
        source and JSON file you created in step 2.
      </para>
    </listitem>
  </orderedlist>
  <para>
    Hydra will create a special jobset named <literal>.jobsets</literal>.
    When the <literal>.jobsets</literal> jobset is evaluated, this static
    specification will be used for configuring the rest of the project's
    jobsets.
  </para>
</section>

<section xml:id="sec-generated-declarative-projects">

  <title>Generated, Declarative Projects</title>
  <para>
    Hydra also supports generated declarative projects, where jobsets are
    configured automatically from specification files instead of being
    managed through the UI. A jobset specification is a JSON object
    containing the configuration of the jobset, for example:
  </para>
  <programlisting language="json">
    {
        "enabled": 1,
        "hidden": false,
        "description": "js",
        "nixexprinput": "src",
        "nixexprpath": "release.nix",
        "checkinterval": 300,
        "schedulingshares": 100,
        "enableemail": false,
        "emailoverride": "",
        "keepnr": 3,
        "inputs": {
            "src": { "type": "git", "value": "git://github.com/shlevy/declarative-hydra-example.git", "emailresponsible": false },
            "nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git release-16.03", "emailresponsible": false }
        }
    }
  </programlisting>
  <para>
    To configure a declarative project, take the following steps:
  </para>
  <orderedlist numeration="arabic" spacing="compact">
    <listitem>
      <para>
        Create a jobset repository in the normal way (e.g. a git repo with
        a <literal>release.nix</literal> file, any other needed helper
        files, and taking any kind of hydra input), but without adding it
        to the UI. The nix expression of this repository should contain a
        single job, named <literal>jobsets</literal>. The output of the
        <literal>jobsets</literal> job should be a JSON file containing an
        object of jobset specifications. Each member of the object will
        become a jobset of the project, configured by the corresponding
        jobset specification.
      </para>
    </listitem>
    <listitem>
      <para>
        In some hydra-fetchable source (potentially, but not necessarily,
        the same repo you created in step 1), create a JSON file
        containing a jobset specification that points to the jobset
        repository you created in the first step, specifying any needed
        inputs (e.g. nixpkgs) as necessary.
      </para>
    </listitem>
    <listitem>
      <para>
        In the project creation/edit page, set declarative input type,
        declarative input value, and declarative spec file to point to the
        source and JSON file you created in step 2.
      </para>
    </listitem>
  </orderedlist>
  <para>
    Hydra will create a special jobset named <literal>.jobsets</literal>,
    which whenever evaluated will go through the steps above in reverse
    order:
  </para>
  <orderedlist numeration="arabic" spacing="compact">
    <listitem>
      <para>
        Hydra will fetch the input specified by the declarative input type
        and value.
      </para>
    </listitem>
    <listitem>
      <para>
        Hydra will use the configuration given in the declarative spec
        file as the jobset configuration for this evaluation. In addition
        to any inputs specified in the spec file, hydra will also pass the
        <literal>declInput</literal> argument corresponding to the input
        fetched in step 1.
      </para>
    </listitem>
    <listitem>
      <para>
        As normal, hydra will build the jobs specified in the jobset
        repository, which in this case is the single
        <literal>jobsets</literal> job. When that job completes, hydra
        will read the created jobset specifications and create
        corresponding jobsets in the project, disabling any jobsets that
        used to exist but are not present in the current spec.
      </para>
    </listitem>
  </orderedlist>
</section>
</section>
