openapi: "3.0.0"
info:
  version: 1.0.0
  title: Hydra API
  description: Specification of the Hydra REST API
servers:
  - url: https://hydra.nixos.org
paths:

  /login:
    post:
      summary: Log in using username/password credentials
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  description: user
                  type: string
                password:
                  description: password
                  type: string
      responses:
        '200':
          description: successful login
          content:
            application/json:
              schema:
                type: object
                properties:
                  username:
                    description: user
                    type: string
                  fullname:
                    description: full name
                    type: string
                  emailaddress:
                    description: email
                    type: string
                  userroles:
                    description: user roles
                    type: array
                    items:
                      type: string
        '403':
          description: login failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /:
    get:
      summary: Retrieves all projects
      description: Retrieves a list of all projects.
      responses:
        '200':
          description: List of all configured projects
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Project'
              examples:
                projects-success:
                  $ref: '#/components/examples/projects-success'

  /api/push:
    post:
      summary: trigger jobsets
      parameters:
        - in: query
          name: jobsets
          description: project and jobset formatted as "<project>:<jobset>" to evaluate
          schema:
            type: string
        - in: query
          name: force
          description: when set to true the jobset gets evaluated even when it did not change
          schema:
            type: boolean
      responses:
        '200':
          description: jobset trigger response
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobsetsTriggered:
                    type: array
                    items:
                      type: string


  /api/jobsets:
    get:
      summary: retrieve a jobset overview for a project
      parameters:
        - in: query
          name: project
          description: name of the project
          schema:
            type: string
      responses:
        '200':
          description: jobset overview
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobsetOverview'
        '404':
          description: project could not be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /search:
    get:
      summary: search for evaluations
      description: search for evaluations by name
      parameters:
        - in: query
          name: query
          schema:
            type: string
          description: string to search for
      responses:
        '200':
          description: search response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResult'
        '500':
          description: Empty search term or other internal error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: error message

  /project/{id}:
    put:
      summary: Create a project
      parameters:
        - name: id
          in: path
          description: project identifier
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  description: name of the project
                  type: string
                displayname:
                  description: display name of the project
                  type: string
                description:
                  description: description of the project
                  type: string
                homepage:
                  description: homepage of the project
                  type: string
                owner:
                  description: owner of the project
                  type: string
                enabled:
                  description: when set to true the project gets scheduled for evaluation
                  type: boolean
                enable_dynamic_run_command:
                  description: when true the project's jobsets support executing dynamically defined RunCommand hooks. Requires the server and project's configuration to also enable dynamic RunCommand.
                  type: boolean
                visible:
                  description: when set to true the project is displayed in the web interface
                  type: boolean
                declarative:
                  description: declarative input configured for this project
                  type: object
                  $ref: '#/components/schemas/DeclarativeInput'
      responses:
        '400':
          description: bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    description: error message
                    type: string
        '403':
          description: request unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    description: error message
                    type: string
        '200':
          description: projects exists
          content:
            application/json:
              schema:
                type: object
                properties:
                  redirect:
                    description: URL of the created project
                    type: string
        '201':
          description: successful project creation
          content:
            application/json:
              schema:
                type: object
                properties:
                  uri:
                    description: URL of the created project
                    type: string
                  name:
                    description: name of the project
                    type: string
                  redirect:
                    description: URL of the created project
                    type: string
                  type:
                    description: type of the created resource ("project")
                    type: string

    get:
      summary: Retrieves a project designated by name
      parameters:
        - name: id
          in: path
          description: project identifier
          required: true
          schema:
            type: string
      responses:
        '200':
          description: project response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Project'
              examples:
                project-success:
                  $ref: '#/components/examples/project-success'
        '404':
          description: project could not be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

    delete:
      summary: Deletes a project
      parameters:
        - name: id
          in: path
          description: project identifier
          required: true
          schema:
            type: string
      responses:
        '200':
          description: project deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  redirect:
                    type: string
                    description: root of the Hydra instance
        '404':
          description: project could not be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /jobset/{project-id}/{jobset-id}:
    put:
      summary: Creates a jobset in an existing project
      parameters:
        - name: project-id
          required: true
          in: path
          description: name of the project to create the jobset in
          schema:
            type: string
        - name: jobset-id
          required: true
          in: path
          description: name of the jobset to create
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Jobset'
      responses:
        '201':
          description: jobset creation response
          content:
            application/json:
              schema:
                type: object
                properties:
                  redirect:
                    type: string
                    description: url pointing to the webui for the created jobset
                  uri:
                    type: string
                    description: url to the created jobset
                  name:
                    type: string
                    description: name of the created jobset
                  'type':
                    type: string
                    description: Set to "jobset"
        '200':
          description: jobset creation response when jobset exists already
          content:
            application/json:
              schema:
                type: object
                properties:
                  redirect:
                    type: string
                    description: url pointing to the webui for the created jobset

    get:
      summary: Retrieves a jobset designated by project and jobset id
      parameters:
        - name: project-id
          in: path
          description: name of the project the jobset belongs to
          required: true
          schema:
            type: string
        - name: jobset-id
          in: path
          description: name of the jobset to retrieve
          required: true
          schema:
            type: string
      responses:
        '200':
          description: jobset response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Jobset'
              examples:
                jobset-success:
                  $ref: '#/components/examples/jobset-success'
        '404':
          description: jobset couldn't be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

    delete:
      summary: Deletes a jobset designated by project and jobset id
      parameters:
        - name: project-id
          in: path
          description: name of the project the jobset belongs to
          required: true
          schema:
            type: string
        - name: jobset-id
          in: path
          description: name of the jobset to retrieve
          required: true
          schema:
            type: string
      responses:
        '200':
          description: jobset successfully deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  redirect:
                    type: string
                    description: root of the Hydra instance
        '404':
          description: jobset couldn't be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /jobset/{project-id}/{jobset-id}/evals:
    get:
      summary: Retrieves all evaluations of a jobset
      parameters:
      - name: project-id
        in: path
        description: project identifier
        required: true
        schema:
          type: string
      - name: jobset-id
        in: path
        description: jobset identifier
        required: true
        schema:
          type: string
      responses:
        '200':
          description: evaluations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Evaluations'
              examples:
                evals-success:
                  $ref: '#/components/examples/evals-success'
        '404':
          description: jobset couldn't be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /job/{project-id}/{jobset-id}/{job-id}/shield:
    get:
      summary: Generate data for a shields.io badge
      parameters:
      - name: project-id
        in: path
        description: project identifier
        required: true
        schema:
          type: string
      - name: jobset-id
        in: path
        description: jobset identifier
        required: true
        schema:
          type: string
      - name: job-id
        in: path
        description: job identifier
        required: true
        schema:
          type: string
      responses:
        '200':
          description: see <a href="https://shields.io/endpoint">https://shields.io/endpoint</a> on how to use this
          content:
            application/json:
              examples:
                shield-success:
                  value:
                    color: green
                    schemaVersion: 1
                    label: hydra build
                    message: passing

  /build/{build-id}:
    get:
      summary: Retrieves a single build of a jobset by id
      parameters:
      - name: build-id
        in: path
        description: build identifier
        required: true
        schema:
            type: integer
      responses:
        '200':
          description: build
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Build'
              examples:
                build-success:
                  $ref: '#/components/examples/build-success'
        '404':
          description: build couldn't be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /build/{build-id}/constituents:
    get:
      summary: Retrieves a build's constituent jobs
      parameters:
      - name: build-id
        in: path
        description: build identifier
        required: true
        schema:
            type: integer
      responses:
        '200':
          description: build
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Build'
        '404':
          description: build couldn't be found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /eval/{eval-id}:
    get:
      summary: Retrieves evaluations identified by eval id
      parameters:
        - name: eval-id
          in: path
          description: eval identifier
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: evaluation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobsetEval'

  /eval/{eval-id}/builds:
    get:
      summary: Retrieves all builds belonging to an evaluation identified by eval id
      parameters:
        - name: eval-id
          in: path
          description: eval identifier
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: builds
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobsetEvalBuilds'

components:
  schemas:

    SearchResult:
      type: object
      properties:
        jobsets:
          description: jobsets matching search term
          type: array
          items:
            $ref: '#/components/schemas/Jobset'
        projects:
          description: projects missing search term
          type: array
          items:
            $ref: '#/components/schemas/Project'
        builds:
          description: builds matching search term
          type: array
          items:
            $ref: '#/components/schemas/Build'
        buildsdrv:
          description: derivations matching search term
          type: array
          items:
            $ref: '#/components/schemas/Build'


    Error:
      type: object
      properties:
        error:
          description: error message
          type: string

    Project:
      type: object
      properties:
        owner:
          description: username of the project owner
          type: string
        name:
          description: name of the project
          type: string
        displayname:
          description: name to be displayed in the web interface
          type: string
        description:
          description: description of the project
          type: string
        homepage:
          description: homepage of the project
          type: string
        hidden:
          description: when set to true the project is not displayed in the web interface
          type: boolean
        enabled:
          description: when set to true the project gets scheduled for evaluation
          type: boolean
        enable_dynamic_run_command:
          description: when true the project's jobsets support executing dynamically defined RunCommand hooks. Requires the server and project's configuration to also enable dynamic RunCommand.
          type: boolean
        declarative:
          description: declarative input configured for this project
          type: object
          $ref: '#/components/schemas/DeclarativeInput'
        jobsets:
          description: list of jobsets belonging to this project
          type: array
          items:
            type: string

    DeclarativeInput:
      type: object
      properties:
        file:
          description: The file in `value` which contains the declarative spec file. Relative to the root of `value`.
          type: string
        type:
          description: The type of the declarative input.
          type: string
        value:
          description: The value of the declarative input.
          type: string

    JobsetInput:
      type: object
      properties:
        name:
          description: name of the input
          type: string
        value:
          description: value of the input
          type: string
        type:
          description: type of input
          type: string
        emailresponsible:
          description: whether or not to email responsible parties
          type: boolean

    Jobset:
      type: object
      properties:
        name:
          description: the name of the jobset
          type: string
        project:
          description: the project this jobset belongs to
          type: string
        description:
          nullable: true
          description: a description of the jobset
          type: string
        nixexprinput:
          nullable: true
          description: the name of the jobset input which contains the nixexprpath
          type: string
        nixexprpath:
          nullable: true
          description: the path to the file to evaluate
          type: string
        errormsg:
          nullable: true
          description: contains the stderr output of the nix-instantiate command
          type: string
        errortime:
          nullable: true
          description: timestamp associated with errormsg
          type: integer
        lastcheckedtime:
          nullable: true
          description: the last time the evaluator looked at this jobset
          type: integer
        triggertime:
          nullable: true
          description: set to the time we were triggered by a push event
          type: integer
        enabled:
          description: 0 is disabled, 1 is enabled, 2 is one-shot, and 3 is one-at-a-time
          type: integer
        enableemail:
          description: when true the jobset sends emails when previously-successful builds fail
          type: boolean
        enable_dynamic_run_command:
          description: when true the jobset supports executing dynamically defined RunCommand hooks. Requires the server and project's configuration to also enable dynamic RunCommand.
          type: boolean
        visible:
          description: when true the jobset is visible in the web frontend
          type: boolean
        emailoverride:
          description: email address to send notices to instead of the package maintainer (can be a comma separated list)
          type: string
        keepnr:
          description: number or evaluations to keep
          type: integer
        checkinterval:
          description: interval (in seconds) in which to check for evaluation
          type: integer
        schedulingshares:
          description: how many shares to be allocated to the jobset
          type: integer
        fetcherrormsg:
          nullable: true
          description: contains the error message when there was a problem fetching sources for a jobset
          type: string
        startime:
          nullable: true
          description: set to the time the latest evaluation started (if one is currently running)
          type: integer
        type:
          description: the type of the jobset
          type: integer
        flake:
          nullable: true
          description: the flake uri to evaluate
          type: string
        inputs:
          description: inputs configured for this jobset
          type: object
          additionalProperties:
            $ref: '#/components/schemas/JobsetInput'

    JobsetEvalInput:
      type: object
      properties:
        uri:
          nullable: true
          description: URI of this input (which differs depending on the type of the input)
          type: string
        'type':
          description: The type of this input
          type: string
        revision:
          nullable: true
          description: A Git/Mercurial commit hash or a Subversion revision number.
          type: string
        value:
          nullable: true
          description: A value that corresponds to the type of input
          oneOf:
            - type: boolean
            - type: string
            - type: array
              items:
                type: string
          type: boolean
        dependency:
          nullable: true
          description: >
            **Deprecated**: The build id of another build
          type: string


    JobsetEval:
      type: object
      properties:
        id:
          type: integer
        timestamp:
          description: Time in seconds since the Unix epoch when this evaluation was created.
          type: integer
        checkouttime:
          description: How long it took (in seconds) to fetch the jobset inputs.
          type: integer
        evaltime:
          description: How long it took (in seconds) to evaluate the jobset.
          type: integer
        hasnewbuilds:
          description: Whether the number of JobsetEval members is different from the prior evaluation. This is always true on the first evaluation.
          type: boolean
        flake:
          description: For flake jobsets, the immutable flake reference allowing you to reproduce this evaluation. Null otherwise.
          nullable: true
          type: string
        builds:
          description: List of builds generated for this jobset evaluation.
          type: array
          items:
            type: integer
        jobsetevalinputs:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/JobsetEvalInput'

    JobsetEvalBuilds:
      type: array
      items:
        type: object
        additionalProperties:
          $ref: '#/components/schemas/Build'

    JobsetOverview:
      type: array
      items:
          type: object
          properties:
            name:
              description: name of the jobset
              type: string
            project:
              description: name of the project
              type: string
            nrtotal:
              description: number of evaluations
              type: integer
            checkinterval:
              description: interval in seconds at which to check the jobset inputs
              type: integer
            haserrormsg:
              description: true if the evaluation had errors
              type: boolean
            nrscheduled:
              description: number of scheduled evaluations
              type: integer
            nrfailed:
              description: number of failed evaluations
              type: integer
            errortime:
              description: time an error occurred during evaluation (unix time stamp)
              type: integer
            fetcherrormsg:
              nullable: true
              description: contains the error message when there was a problem fetching sources for a jobset
            starttime:
              nullable: true
              description: time when build started
              type: integer
            lastcheckedtime:
              description: the last time the jobset inputs where checked to see if an evaluation needs to be scheduled (unix time stamp)
              type: integer
            triggertime:
              nullable: true
              description: time of the last evaluation trigger for this jobset (unix time stamp)
              type: integer



    Evaluations:
      type: object
      properties:
        first:
          description: first list of results
          type: string
        next:
          description: next list of results
          type: string
        last:
          description: last list of results
          type: string
        evals:
          type: array
          description: List of evaluations
          items:
            type: object
            additionalProperties:
              $ref: '#/components/schemas/JobsetEval'

    BuildProduct:
      type: object
      properties:
        filesize:
          nullable: true
          description: Size of the produced file
          type: integer
        defaultpath:
          description: if path is a directory, the default file relative to path to be served
          type: string
        'type':
          description: Types of build product (user defined)
          type: string
        name:
          description: Name of the file
          type: string
        path:
          description: the nix store path
          type: string
        subtype:
          description: user-specified
          type: string
        sha256hash:
          nullable: true
          description: sha256 hash of the file
          type: string

    BuildOutput:
      type: object
      properties:
        path:
          description: The nix store path
          type: string

    Build:
      type: object
      properties:
        id:
          type: integer
        starttime:
          description: time when build started
          type: integer
        stoptime:
          description: time when build ended
          type: integer
        timestamp:
          description: time when the build was first created
          type: integer
        jobsetevals:
          description: list of evaluations this build is part of
          type: array
          items:
            type: integer
        finished:
          description: true when the build is finished
          type: boolean
        nixname:
          description: name from the build's derivation
          type: string
        buildstatus:
          nullable: true # should only be null if finished is false
          description: |
            Indicates the build status:</br>
            <ul>
             <li>0 : succeeded</li>
             <li>1 : failed</li>
             <li>2 : dependency failed</li>
             <li>3 : aborted</li>
             <li>4 : canceled by the user</li>
             <li>6 : failed with output</li>
             <li>7 : timed out</li>
             <li>9 : aborted</li>
             <li>10 : log size limit exceeded</li>
             <li>11 : output size limit exceeded</li>
             <li>*  : failed</li>
            </ul>
            <strong>Note:</strong>buildstatus should only be `null` if `finished` is false.
          type: integer
        jobset:
          description: jobset this build belongs to
          type: string
        priority:
          description: determines the priority with which this build will be executed (higher value means higher priority)
          type: integer
        job:
          description: nix attribute from the nixexprpath
          type: string
        drvpath:
          description: filename of the drv
          type: string
        system:
          description: system this build was done for
          type: string
        project:
          description: project this build belongs to
          type: string
        buildproducts:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/BuildProduct'
        buildoutputs:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/BuildOutput'
        buildmetrics:
          description: |
            user defined build metrics from `$out/nix-support/hydra-metrics`. The file should
            define metrics separated by new lines using the following format:

            ```
            <name> <value>[ <unit>]
            ```
            The name and unit fields are strings, the value is a float. The unit is optional.
          type: object
          properties:
            name:
              type: string
              description: name of the measured build metric
            value:
              type: string
              description: measured value
            unit:
              type: string
              description: unit of the measured build metric

  examples:
    projects-success:
      value:
      - displayname: Foo Bar
        description: Foo Bar Baz Qux
        enabled: true
        owner: alice
        jobsets:
          - bar-jobset
        hidden: false
        homepage: https://example.com/
        name: foobar
      - jobsets:
          - test-jobset
        hidden: false
        name: hello
        homepage: https://example.com/
        description: Hi There
        displayname: Hello
        enabled: true
        owner: alice

    project-success:
      value:
        jobsets:
          - bar-jobset
        homepage: https://example.com/
        name: foobar
        hidden: false
        enabled: true
        displayname: Foo Bar
        description: Foo Bar Baz Qux
        owner: alice

    jobset-success:
      value:
        triggertime: null
        enableemail: false
        jobsetinputs:
          nixpkgs:
            type: git
            name: nixpkgs
            emailresponsible: false
            jobsetinputalts:
              - https://github.com/NixOS/nixpkgs.git
          officialRelease:
            jobsetinputalts:
              - 'false'
            emailresponsible: false
            name: officialRelease
            type: boolean
        fetcherrormsg: ''
        hidden: false
        schedulingshares: 1
        emailoverride: ''
        starttime: null
        description: ''
        errormsg: ''
        lastcheckedtime: null
        nixexprinput: nixpkgs
        checkinterval: 0
        project: foobar
        flake: ''
        type: 0
        enabled: 1
        name: bar-jobset
        keepnr: 0
        nixexprpath: pkgs/top-level/release.nix
        errortime: null

    evals-success:
      value:
        last: '?page=1'
        evals:
          - builds:
              - 2
            jobsetevalinputs:
              hydra:
                revision: 84a3aecb1d976366060d0f0fd4df7d67b0855f5e
                uri: 'https://github.com/gilligan/hydra'
                type: git
                value: null
                dependency: null
              nixpkgs:
                dependency: null
                value: null
                uri: 'https://github.com/nixos/nixpkgs-channels'
                type: git
                revision: ab3adfe1c769c22b6629e59ea0ef88ec8ee4563f
            id: 2
            hasnewbuilds: 1
        first: '?page=1'

    build-success:
      value:
        buildproducts:
          '1':
            filesize: null
            defaultpath: ''
            name: hello-2.10
            type: nix-build
            sha256hash: null
            subtype: ''
            path: /nix/store/y26qxcq1gg2hrqpxdc58b2fghv2bhxjg-hello-2.10
        id: 1
        buildstatus: 0
        nixname: hello-2.10
        finished: 1
        jobsetevals:
          - 1
        stoptime: 1588365711
        system: x86_64-linux
        drvpath: /nix/store/ab9zv2y5gm8hr6g318p0s6kaclwj4slr-hello-2.10.drv
        buildoutputs:
          out:
            path: /nix/store/y26qxcq1gg2hrqpxdc58b2fghv2bhxjg-hello-2.10
        job: hello
        jobset: hello
        buildmetrics: {}
        priority: 100
        project: example-hello
        starttime: 1588365711
        timestamp: 1588365711
