Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/devlake"
A client for the Apache DevLake Webhook API, covering the deployment and incident events that feed DORA metrics.
c, err := devlake.New(addr, apiKey)
err = c.SendDeployment(ctx, &devlake.DeploymentRequest{...})
err = c.SendIncident(ctx, &devlake.IncidentRequest{...})
err = c.SendIncidentClose(ctx, &devlake.IncidentRequestClose{...})
What DevLake wants and why the events are split
DevLake computes the four DORA metrics: deployment frequency, lead time for changes, change failure rate, and time to restore service. Two of the four are durations, which is why incidents are reported twice.
SendIncident opens an incident. SendIncidentClose closes it. Time to restore is the interval between them, so a service that reports incidents but never closes them produces a metric that only ever gets worse. The split API makes the second call something you have to forget rather than something you have to discover.
SendDeployment carries deployment commits. Those link a deployment back to the changes in it, which is what makes lead time computable.
Validation before the network call
Each request struct carries validation tags matching the webhook’s payload constraints, and the client validates before sending.
This is worth more here than in a typical API client. A webhook endpoint accepts a payload and returns 200; whether the payload was usable shows up later, as a metric that is subtly wrong or a record that never joins to anything. A malformed timestamp or a missing environment field does not fail loudly at the call site.
Validating locally converts that into an error at the point of the call, where the stack trace tells you which event was wrong. Validation runs through validator.
Telemetry must not break the thing it measures
Every send is a synchronous HTTP call to an external system, inside whatever code path just deployed or just detected an incident.
Two implications for how you wire it. Deployment reporting belongs in the deployment pipeline rather than in service startup, so a DevLake outage does not slow or fail a rollout. Incident reporting belongs after the incident is recorded in your own system of record, so a failed send loses a metric rather than the incident.
WithRetryAttempts and WithTimeout bound how long a failing send occupies the caller. The defaults are finite; do not raise them so far that a DevLake outage becomes a deployment outage.
Options
| Option | Effect |
|---|---|
WithTimeout | request timeout |
WithPingTimeout | health-check timeout |
WithPingURL | health-check target |
WithHTTPClient | inject a transport or a mock |
WithRetryAttempts | retries per send |
Requests authenticate with a bearer token supplied to New and are sent as JSON with contextual error wrapping, so a failure identifies which operation produced it.
Example
c, err := devlake.New("https://devlake.example.com", "api-key")
if err != nil {
log.Fatal(err)
}
err = c.HealthCheck(context.Background())
fmt.Println(err)
Full source is in example_devlake_test.go. More runnable examples are on pkg.go.dev.
Dependencies
Reaches the validation stack through validator.
Links
- Reference documentation
- Source code
- The same job for Sleuth: sleuth
- Payload validation: validator
- All nurago packages