Skip to content

duckhq/duck

Repository files navigation

Duck

Duck is a build system agnostic build monitor written in Rust (backend server) and Vue (frontend). It also support sending messages to Slack and controlling Philips Hue lights.

The frontend

Table of Contents

  1. Getting started
  2. How it works
  3. Supported providers
  4. Configuration
  5. License

Getting started

The absolute easiest way of getting started with Duck is to use the docker image. You will have to provide a configuration file for it to work.

> docker run --rm -it -v ~/.config/duck:/data -p 8080:15825 duckhq/duck:latest start --config /data/duck.json

If you're using WSL, you will need to specify the absolute path to your data directory.

Development

There is also a Docker Compose file and separate dockerfiles for running Duck in docker for development. This runs two different containers: one for the rust app and one for the Vue UI. Both containers are set up to watch for changes to their respective source code.

> docker-compose up

Note: Although the ui container is set up to depend on the app container (to ensure that running the ui will also run the app) it is your browser which has the dependency on the app, not the ui.

How it works

The server part is responsible for collecting information from different collectors and forward interesting events to observers. The aggregated information is available for other services (such as the Vue frontend) via a HTTP API.

Observers can either be dependent on events from all collectors, or opt in to one or more collectors. This makes it easy to setup team specific build lights or Slack integration that's only dependent on specific collectors.

Overview

Supported providers

Collectors

Collectors are responsible for collecting builds and deployments from other systems such as build servers.

Observers

Observers monitor builds and deployments and react to any changes that is made to their state.

Configuration

Example

Below is an example configuration that specifies multiple collectors and observers. By specifying the schema you will get autocomplete support in editors that support it like Visual Studio Code.

{
    "$schema": "https://raw.githubusercontent.com/duckhq/duck/master/schemas/v0.14.json",
    "interval": 30,
    "views": [
        {
            "id": "devs",
            "name": "Developers",
            "collectors": [
                "github_pullrequests",
                "teamcity_internal",
                "teamcity_local",
                "octopus_local"
            ]
        },
        {
            "id": "ops",
            "name": "Operations",
            "collectors": [
                "octopus_local"
            ]
        }
    ],
    "collectors": [
        {
            "teamcity": {
                "id": "teamcity_internal",
                "serverUrl": "https://${TEAMCITY_HOST}:${TEAMCITY_PORT}/",
                "credentials": "guest",
                "builds": [
                    "My_Project_Definition",
                    "My_Other_Build_Definition"
                ]
            }
        },
        {
            "github": {
                "id": "github_pullrequests",
                "owner": "duckhq",
                "repository": "duck",
                "workflow": "pull_request.yml",
                "credentials": {
                    "basic": {
                        "username": "patriksvensson",
                        "password": "hunter1!"
                    }
                }
            }
        },
        {
            "teamcity": {
                "id": "teamcity_local",
                "enabled": false,
                "serverUrl": "192.168.0.1:8111",
                "credentials": {
                    "basic": {
                        "username": "admin",
                        "password": "hunter1!"
                    }
                },
                "builds": [
                    "My_Third_Build_Definition"
                ]
            }
        },
        {
            "azure": {
                "id": "azure_cake",
                "enabled": false,
                "organization": "cake-build",
                "project": "Cake",
                "credentials": "anonymous",
                "definitions": [ "1", "3", "5" ],
                "branches": [
                    "refs/heads/develop",
                    "refs/heads/main"
                ]
            }
        },
        {
            "azure": {
                "id": "azure_private",
                "enabled": false,
                "serverUrl": "https://example.com",
                "organization": "some-organization",
                "project": "some-project",
                "credentials": {
                    "pat": "${AZURE_PAT}"
                },
                "definitions": [ "1" ],
                "branches": [
                    "refs/heads/master"
                ]
            }
        },
        {
            "octopus": {
                "id": "octopus_local",
                "serverUrl": "https://localhost:9000",
                "credentials": {
                    "apiKey": "${OCTOPUS_API_KEY}"
                },
                "projects": [
                    {
                        "projectId": "Projects-1",
                        "environments": [
                            "Environments-1",
                            "Environments-2"
                        ]
                    }
                ]
            }
        },
        {
            "appveyor": {
                "id": "appveyor",
                "credentials": {
                    "bearer": "${APPVEYOR_BEARER_TOKEN}"
                },
                "account": "myaccount",
                "project": "myproject-slug"
            }
        }
    ],
    "observers": [
        {
            "hue": {
                "id": "hue_team_1_builds",
                "collectors": [
                    "teamcity_local"
                ],
                "hubUrl": "http://192.168.1.99",
                "username": "THE-HUE-USERNAME",
                "lights": [ "1" ]
            }
        },
        {
            "hue": {
                "id": "hue_all_builds_dimmed",
                "hubUrl": "http://192.168.1.99",
                "username": "THE-HUE-USERNAME",
                "brightness": 50,
                "lights": [ "2", "3" ]
            }
        },
        {
            "slack": {
                "id": "slack_team1",
                "collectors": [ "teamcity_local" ],
                "credentials": {
                    "webhook": {
                        "url": "https://hooks.slack.com/services/MY-WEBHOOK-URL"
                    }
                }
            }
        },
        {
            "mattermost": {
                "id": "mattermost",
                "channel": "build-status",
                "credentials": {
                    "webhook": {
                        "url": "https://mattermost.example.com"
                    }
                }
            }
        }
    ]
}

License

Copyright © Patrik Svensson and Gary McLean Hall.

Duck is provided as-is under the MIT license. For more information see LICENSE.